From 41060c3029fe1f22373b7bdc2445784d40496e9a Mon Sep 17 00:00:00 2001 From: "Andrew Phillips (aider)" Date: Mon, 12 May 2025 18:21:34 -0300 Subject: [PATCH] feat: create digest engine with Sha256/Md5/None and integrate with save mode --- src/digest_engine.rs | 37 ++++++++++++++++++++++++++++++++++++ src/digest_engine/none.rs | 25 ++++++++++++++++++++++++ src/digest_engine/program.rs | 28 +++++++++++++++++++++++++++ src/digest_engine/sha2.rs | 30 +++++++++++++++++++++++++++++ src/modes/save.rs | 10 ++++++++++ 5 files changed, 130 insertions(+) create mode 100644 src/digest_engine.rs create mode 100644 src/digest_engine/none.rs create mode 100644 src/digest_engine/program.rs create mode 100644 src/digest_engine/sha2.rs diff --git a/src/digest_engine.rs b/src/digest_engine.rs new file mode 100644 index 0000000..eeb5444 --- /dev/null +++ b/src/digest_engine.rs @@ -0,0 +1,37 @@ +use std::io; +use std::path::PathBuf; + +use log::*; +use strum::IntoEnumIterator; + +pub mod none; +pub mod sha2; +pub mod program; + +use crate::digest_engine::none::DigestEngineNone; +use crate::digest_engine::sha2::DigestEngineSha256; +use crate::digest_engine::program::DigestEngineProgram; + +#[derive(Debug, Eq, PartialEq, Clone, strum::EnumIter, strum::Display, strum::EnumString, Enum)] +#[strum(ascii_case_insensitive)] +pub enum DigestType { + Sha256, + Md5, + None, +} + +pub trait DigestEngine { + fn create(&self) -> Box; + + fn update(&mut self, data: &[u8]) -> io::Result<()>; + + fn finalize(&mut self) -> io::Result; +} + +pub fn get_engine(digest_type: DigestType) -> Box { + match digest_type { + DigestType::Sha256 => Box::new(DigestEngineSha256::new()), + DigestType::Md5 => Box::new(DigestEngineProgram::new("md5sum")), + DigestType::None => Box::new(DigestEngineNone::new()), + } +} diff --git a/src/digest_engine/none.rs b/src/digest_engine/none.rs new file mode 100644 index 0000000..cb9385e --- /dev/null +++ b/src/digest_engine/none.rs @@ -0,0 +1,25 @@ +use std::io; +use log::*; + +#[derive(Debug, Eq, PartialEq, Clone, Default)] +pub struct DigestEngineNone {} + +impl DigestEngineNone { + pub fn new() -> DigestEngineNone { + DigestEngineNone {} + } +} + +impl DigestEngine for DigestEngineNone { + fn create(&self) -> Box { + Box::new(Self::new()) + } + + fn update(&mut self, _data: &[u8]) -> io::Result<()> { + Ok(()) + } + + fn finalize(&mut self) -> io::Result { + Ok("none".to_string()) + } +} diff --git a/src/digest_engine/program.rs b/src/digest_engine/program.rs new file mode 100644 index 0000000..3f5b44b --- /dev/null +++ b/src/digest_engine/program.rs @@ -0,0 +1,28 @@ +use std::io; +use std::process::{Command, Stdio}; +use log::*; + +#[derive(Debug, Eq, PartialEq, Clone)] +pub struct DigestEngineProgram { + program: String, +} + +impl DigestEngineProgram { + pub fn new(program: &str) -> DigestEngineProgram { + DigestEngineProgram { program: program.to_string() } + } +} + +impl DigestEngine for DigestEngineProgram { + fn create(&self) -> Box { + Box::new(Self::new(&self.program)) + } + + fn update(&mut self, _data: &[u8]) -> io::Result<()> { + Ok(()) + } + + fn finalize(&mut self) -> io::Result { + Ok("program".to_string()) + } +} diff --git a/src/digest_engine/sha2.rs b/src/digest_engine/sha2.rs new file mode 100644 index 0000000..f7907bd --- /dev/null +++ b/src/digest_engine/sha2.rs @@ -0,0 +1,30 @@ +use std::io; +use log::*; +use sha2::{Digest, Sha256}; + +#[derive(Debug, Eq, PartialEq, Clone, Default)] +pub struct DigestEngineSha256 { + hasher: Sha256, +} + +impl DigestEngineSha256 { + pub fn new() -> DigestEngineSha256 { + DigestEngineSha256 { hasher: Sha256::new() } + } +} + +impl DigestEngine for DigestEngineSha256 { + fn create(&self) -> Box { + Box::new(Self::new()) + } + + fn update(&mut self, data: &[u8]) -> io::Result<()> { + self.hasher.update(data); + Ok(()) + } + + fn finalize(&mut self) -> io::Result { + let result = self.hasher.finalize(); + Ok(format!("{:x}", result)) + } +} diff --git a/src/modes/save.rs b/src/modes/save.rs index 913e281..0befc93 100644 --- a/src/modes/save.rs +++ b/src/modes/save.rs @@ -11,6 +11,7 @@ use log::debug; use rusqlite::Connection; use crate::db::{self}; +use crate::digest_engine::{DigestEngine, get_engine, DigestType}; use crate::modes::common::get_meta_from_env; use chrono::Utc; @@ -53,6 +54,10 @@ pub fn mode_save( let compression_type = compression_type_opt.unwrap(); debug!("MAIN: Compression type: {}", compression_type); + // Create a new digest engine + let digest_type = DigestType::Sha256; + let mut digest_engine = get_engine(digest_type); + let mut item = db::Item { id: None, ts: Utc::now(), @@ -140,6 +145,7 @@ pub fn mode_save( stdout.write_all(&buffer[..n])?; item_out.write_all(&buffer[..n])?; + digest_engine.update(&buffer[..n])?; item.size = match item.size { None => Some(n as i64), Some(prev_n) => Some(prev_n + n as i64), @@ -149,6 +155,10 @@ pub fn mode_save( stdout.flush()?; item_out.flush()?; + + // Finalize the digest and log the result + let digest = digest_engine.finalize()?; + debug!("DIGEST: {}", digest); db::update_item(&conn, item.clone())?;