use anyhow::Result; use std::io; use lazy_static::lazy_static; extern crate enum_map; use enum_map::enum_map; use enum_map::{Enum, EnumMap}; pub mod none; pub mod program; pub mod sha2; use crate::digest_engine::none::DigestEngineNone; use crate::digest_engine::program::DigestEngineProgram; use crate::digest_engine::sha2::DigestEngineSha256; use strum::IntoEnumIterator; #[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 is_supported(&self) -> bool { true } fn create(&self) -> Result>; fn finalize(&mut self) -> io::Result; // Update the digest with new data fn update(&mut self, data: &[u8]); } use std::io::Write; // Writer that implements Write for the program digest engine struct ProgramWriter { stdin: std::process::ChildStdin, } impl Write for ProgramWriter { fn write(&mut self, buf: &[u8]) -> std::io::Result { self.stdin.write(buf) } fn flush(&mut self) -> std::io::Result<()> { self.stdin.flush() } } lazy_static! { pub static ref DIGEST_PROGRAMS: EnumMap> = enum_map! { DigestType::Sha256 => None, DigestType::Md5 => { let program = DigestEngineProgram::new("md5sum", vec![]); if program.supported { Some(program) } else { None } } DigestType::None => None }; } pub fn get_digest_engine(digest_type: DigestType) -> Box { match digest_type { DigestType::Sha256 => Box::new(DigestEngineSha256::new()), DigestType::Md5 => Box::new(DigestEngineProgram::new("md5sum", vec![])), DigestType::None => Box::new(DigestEngineNone::new()), } } pub fn default_digest_type() -> DigestType { let mut default = DigestType::None; for digest_type in DigestType::iter() { let digest_engine = get_digest_engine(digest_type.clone()); if digest_engine.is_supported() { default = digest_type; break; } } default }