use sha2::{Digest, Sha256, Sha512}; use md5::Md5; use crate::meta_plugin::MetaPlugin; #[derive(Debug, Clone)] enum HashMethod { Md5, Sha256, Sha512, } impl Default for HashMethod { fn default() -> Self { HashMethod::Sha256 } } impl HashMethod { fn from_str(s: &str) -> Option { match s { "md5" => Some(HashMethod::Md5), "sha256" => Some(HashMethod::Sha256), "sha512" => Some(HashMethod::Sha512), _ => None, } } } #[derive(Debug, Clone)] pub struct DigestMetaPlugin { md5_hasher: Option, sha256_hasher: Option, sha512_hasher: Option, is_finalized: bool, meta_name: String, outputs: std::collections::HashMap, options: std::collections::HashMap, methods: Vec, } impl Default for DigestMetaPlugin { fn default() -> Self { Self { md5_hasher: None, sha256_hasher: None, sha512_hasher: None, is_finalized: false, meta_name: "digest".to_string(), outputs: std::collections::HashMap::new(), options: std::collections::HashMap::new(), methods: vec![HashMethod::Sha256], } } } impl DigestMetaPlugin { pub fn new( options: Option>, outputs: Option>, ) -> DigestMetaPlugin { let mut plugin = DigestMetaPlugin::default(); // Set default outputs let default_outputs = vec![ ("digest_md5".to_string(), serde_yaml::Value::String("digest_md5".to_string())), ("digest_sha256".to_string(), serde_yaml::Value::String("digest_sha256".to_string())), ("digest_sha512".to_string(), serde_yaml::Value::String("digest_sha512".to_string())), ]; for (key, value) in default_outputs { plugin.outputs.insert(key, value); } // Apply provided options if let Some(opts) = options { for (key, value) in opts { plugin.options.insert(key, value); } } // Apply provided outputs if let Some(outs) = outputs { for (key, value) in outs { plugin.outputs.insert(key, value); } } // Configure methods based on options if let Some(method_value) = plugin.options.get("method") { if let Some(method_str) = method_value.as_str() { if let Some(method) = HashMethod::from_str(method_str) { plugin.methods = vec![method]; } } } // Initialize hashers based on selected methods for method in &plugin.methods { match method { HashMethod::Md5 => plugin.md5_hasher = Some(Md5::new()), HashMethod::Sha256 => plugin.sha256_hasher = Some(Sha256::new()), HashMethod::Sha512 => plugin.sha512_hasher = Some(Sha512::new()), } } plugin } pub fn new_simple() -> DigestMetaPlugin { Self::new(None, None) } } impl MetaPlugin for DigestMetaPlugin { fn is_finalized(&self) -> bool { self.is_finalized } fn set_finalized(&mut self, finalized: bool) { self.is_finalized = finalized; } fn initialize(&mut self) -> crate::meta_plugin::MetaPluginResponse { crate::meta_plugin::MetaPluginResponse { metadata: Vec::new(), is_finalized: false, } } fn finalize(&mut self) -> crate::meta_plugin::MetaPluginResponse { if self.is_finalized { return crate::meta_plugin::MetaPluginResponse { metadata: Vec::new(), is_finalized: true, }; } let mut metadata = Vec::new(); // Process each method for method in &self.methods { match method { HashMethod::Md5 => { if let Some(hasher) = self.md5_hasher.take() { let hash_result = hasher.finalize(); let hex_string = format!("{:x}", hash_result); if let Some(meta_data) = crate::meta_plugin::process_metadata_outputs( "digest_md5", hex_string, &self.outputs ) { metadata.push(meta_data); } } } HashMethod::Sha256 => { if let Some(hasher) = self.sha256_hasher.take() { let hash_result = hasher.finalize_reset(); let hex_string = format!("{:x}", hash_result); if let Some(meta_data) = crate::meta_plugin::process_metadata_outputs( "digest_sha256", hex_string, &self.outputs ) { metadata.push(meta_data); } } } HashMethod::Sha512 => { if let Some(hasher) = self.sha512_hasher.take() { let hash_result = hasher.finalize_reset(); let hex_string = format!("{:x}", hash_result); if let Some(meta_data) = crate::meta_plugin::process_metadata_outputs( "digest_sha512", hex_string, &self.outputs ) { metadata.push(meta_data); } } } } } self.is_finalized = true; crate::meta_plugin::MetaPluginResponse { metadata, is_finalized: true, } } fn update(&mut self, data: &[u8]) -> crate::meta_plugin::MetaPluginResponse { if self.is_finalized { return crate::meta_plugin::MetaPluginResponse { metadata: Vec::new(), is_finalized: true, }; } for method in &self.methods { match method { HashMethod::Md5 => { if let Some(hasher) = &mut self.md5_hasher { hasher.update(data); } } HashMethod::Sha256 => { if let Some(hasher) = &mut self.sha256_hasher { hasher.update(data); } } HashMethod::Sha512 => { if let Some(hasher) = &mut self.sha512_hasher { hasher.update(data); } } } } crate::meta_plugin::MetaPluginResponse { metadata: Vec::new(), is_finalized: false, } } fn meta_name(&self) -> String { self.meta_name.clone() } fn outputs(&self) -> &std::collections::HashMap { &self.outputs } fn outputs_mut(&mut self) -> &mut std::collections::HashMap { &mut self.outputs } fn default_outputs(&self) -> Vec { vec![ "digest_md5".to_string(), "digest_sha256".to_string(), "digest_sha512".to_string(), ] } fn default_options(&self) -> std::collections::HashMap { let mut options = std::collections::HashMap::new(); options.insert("method".to_string(), serde_yaml::Value::String("sha256".to_string())); options } fn options(&self) -> &std::collections::HashMap { &self.options } fn options_mut(&mut self) -> &mut std::collections::HashMap { &mut self.options } }