//! Hash 计算模块 //! //! 使用 BLAKE3 算法计算内容 Hash use std::fmt; use std::str::FromStr; /// Hash 类型 /// /// 使用 BLAKE3 算法计算的 256 位 Hash #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct Hash([u8; 32]); impl Hash { /// 从字节数组创建 Hash pub fn from_bytes(bytes: [u8; 32]) -> Self { Self(bytes) } /// 获取 Hash 的字节表示 pub fn as_bytes(&self) -> &[u8; 32] { &self.0 } /// 转换为十六进制字符串 pub fn to_hex(&self) -> String { hex::encode(self.0) } /// 从十六进制字符串解析 pub fn from_hex(s: &str) -> Result { let decoded = hex::decode(s).map_err(|_| crate::error::CasError::InvalidHash(s.to_string())); let bytes = decoded?; if bytes.len() != 32 { return Err(crate::error::CasError::InvalidHash(s.to_string())); } let mut hash_bytes = [0u8; 32]; hash_bytes.copy_from_slice(&bytes); Ok(Self(hash_bytes)) } } impl fmt::Display for Hash { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{}", self.to_hex()) } } impl FromStr for Hash { type Err = crate::error::CasError; fn from_str(s: &str) -> Result { Self::from_hex(s) } } impl serde::Serialize for Hash { fn serialize(&self, serializer: S) -> Result where S: serde::Serializer, { serializer.serialize_str(&self.to_hex()) } } impl<'de> serde::Deserialize<'de> for Hash { fn deserialize(deserializer: D) -> Result where D: serde::Deserializer<'de>, { let s = String::deserialize(deserializer)?; Self::from_hex(&s).map_err(serde::de::Error::custom) } } /// 计算数据的 BLAKE3 Hash /// /// # 参数 /// - `data`: 要计算 Hash 的数据 /// /// # 返回 /// - 数据的 BLAKE3 Hash /// /// # 示例 /// ``` /// use bat_cas_engine::hash::compute_hash; /// /// let data = b"Hello, World!"; /// let hash = compute_hash(data); /// println!("Hash: {}", hash); /// ``` pub fn compute_hash(data: &[u8]) -> Hash { let hash_bytes = blake3::hash(data); Hash::from_bytes(*hash_bytes.as_bytes()) } /// 计算文件的 BLAKE3 Hash /// /// # 参数 /// - `path`: 文件路径 /// /// # 返回 /// - 成功:返回文件的 Hash /// - 失败:返回错误 pub async fn compute_file_hash(path: &std::path::Path) -> crate::error::Result { let data = tokio::fs::read(path).await?; Ok(compute_hash(&data)) } #[cfg(test)] mod tests { use super::*; fn test_hash_and_hex() -> (Hash, String) { let hash = compute_hash(b"Test data"); let hex = hash.to_hex(); (hash, hex) } #[test] fn test_compute_hash() { let data = b"Hello, World!"; let hash = compute_hash(data); // BLAKE3 Hash 应该是确定性的 let hash2 = compute_hash(data); assert_eq!(hash, hash2); } #[test] fn test_hash_to_string() { let (_hash, hex) = test_hash_and_hex(); // 应该是 64 个字符的十六进制字符串 assert_eq!(hex.len(), 64); } #[test] fn test_hash_from_string() { let (hash, hex) = test_hash_and_hex(); let parsed = Hash::from_hex(&hex).unwrap(); assert_eq!(hash, parsed); } #[test] fn test_hash_different_data() { let hash1 = compute_hash(b"Data 1"); let hash2 = compute_hash(b"Data 2"); assert_ne!(hash1, hash2); } #[test] fn test_hash_serialization() { let data = b"Serialization test"; let hash = compute_hash(data); let json = serde_json::to_string(&hash).unwrap(); let deserialized: Hash = serde_json::from_str(&json).unwrap(); assert_eq!(hash, deserialized); } }