use super::{MetaPlugin, MetaPluginType, process_metadata_outputs}; #[derive(Debug, Clone)] pub struct EnvMetaPlugin { is_finalized: bool, outputs: std::collections::HashMap, env_vars: Vec<(String, String)>, } impl EnvMetaPlugin { /// Creates a new `EnvMetaPlugin` instance. /// /// # Arguments /// /// * `_options` - Optional configuration options for the plugin (unused in this implementation). /// * `outputs` - Optional output mappings for metadata. /// /// # Returns /// /// A new instance of `EnvMetaPlugin`. pub fn new( _options: Option>, outputs: Option>, ) -> Self { // Collect environment variables starting with KEEP_META_ let mut env_vars = Vec::new(); let mut outputs_map = std::collections::HashMap::new(); for (key, value) in std::env::vars() { if let Some(stripped_key) = key.strip_prefix("KEEP_META_") { // Add to env_vars to process later env_vars.push((stripped_key.to_string(), value)); // Add to outputs with default mapping to the stripped name outputs_map.insert( stripped_key.to_string(), serde_yaml::Value::String(stripped_key.to_string()) ); } } // Override with provided outputs if let Some(provided_outputs) = outputs { for (key, value) in provided_outputs { outputs_map.insert(key, value); } } EnvMetaPlugin { is_finalized: false, outputs: outputs_map, env_vars, } } } impl MetaPlugin for EnvMetaPlugin { /// Returns the type of this meta plugin. /// /// # Returns /// /// `MetaPluginType::Env`. fn meta_type(&self) -> MetaPluginType { MetaPluginType::Env } /// Checks if the plugin has been finalized. /// /// # Returns /// /// `true` if finalized, `false` otherwise. fn is_finalized(&self) -> bool { self.is_finalized } /// Sets the finalized state of the plugin. /// /// # Arguments /// /// * `finalized` - The new finalized state. fn set_finalized(&mut self, finalized: bool) { self.is_finalized = finalized; } /// Initializes the plugin, processing environment variables. /// /// # Returns /// /// A `MetaPluginResponse` with environment metadata and finalized state set to `true`. fn initialize(&mut self) -> crate::meta_plugin::MetaPluginResponse { // If already finalized, don't process again if self.is_finalized { return crate::meta_plugin::MetaPluginResponse { metadata: Vec::new(), is_finalized: true, }; } // Process all collected environment variables let mut metadata = Vec::new(); for (name, value) in &self.env_vars { if let Some(meta_data) = process_metadata_outputs( name, serde_yaml::Value::String(value.clone()), &self.outputs ) { metadata.push(meta_data); } } // Mark as finalized since this plugin only needs to run once self.is_finalized = true; crate::meta_plugin::MetaPluginResponse { metadata, is_finalized: true, } } /// Updates the plugin with new data (unused in this implementation). /// /// # Arguments /// /// * `_data` - The data chunk (unused). /// /// # Returns /// /// A `MetaPluginResponse` with empty metadata and finalized state. fn update(&mut self, _data: &[u8]) -> crate::meta_plugin::MetaPluginResponse { // If already finalized, don't process more data if self.is_finalized { return crate::meta_plugin::MetaPluginResponse { metadata: Vec::new(), is_finalized: true, }; } crate::meta_plugin::MetaPluginResponse { metadata: Vec::new(), is_finalized: false, } } /// Finalizes the plugin, calling initialize if not already done. /// /// # Returns /// /// A `MetaPluginResponse` with environment metadata if not finalized, or empty if already done. fn finalize(&mut self) -> crate::meta_plugin::MetaPluginResponse { // If not already finalized, we can call initialize if !self.is_finalized { return self.initialize(); } crate::meta_plugin::MetaPluginResponse { metadata: Vec::new(), is_finalized: true, } } /// Returns a reference to the outputs mapping. /// /// # Returns /// /// A reference to the `HashMap` of outputs. fn outputs(&self) -> &std::collections::HashMap { &self.outputs } /// Returns a mutable reference to the outputs mapping. /// /// # Returns /// /// A mutable reference to the `HashMap` of outputs. fn outputs_mut(&mut self) -> &mut std::collections::HashMap { &mut self.outputs } /// Returns the default output names based on collected env vars. /// /// # Returns /// /// A vector of environment variable names. fn default_outputs(&self) -> Vec { self.env_vars.iter() .map(|(name, _)| name.clone()) .collect() } /// Returns a reference to the options mapping (empty for this plugin). /// /// # Returns /// /// An empty `HashMap`. fn options(&self) -> &std::collections::HashMap { use once_cell::sync::Lazy; static EMPTY: Lazy> = Lazy::new(|| std::collections::HashMap::new()); &EMPTY } /// Returns a mutable reference to the options mapping. /// /// # Panics /// /// Panics with "options_mut() not implemented for EnvMetaPlugin". fn options_mut(&mut self) -> &mut std::collections::HashMap { panic!("options_mut() not implemented for EnvMetaPlugin") } } use crate::meta_plugin::register_meta_plugin; // Register the plugin at module initialization time #[ctor::ctor] fn register_env_plugin() { register_meta_plugin(MetaPluginType::Env, |options, outputs| { Box::new(EnvMetaPlugin::new(options, outputs)) }); }