1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
//! Hashing trait.
//!
//! # Architecture
//! This module defines the abstract contract for computing cryptographic hashes.
//! By abstracting the hashing mechanism into a trait, the crate decouples its
//! content-addressing logic from the specific cryptographic algorithm (e.g., SHA-1,
//! SHA-256, SHA-512). This allows consumers to swap algorithms or inject hardware-accelerated
//! implementations without modifying the core object database logic.
//!
//! # Design Rationale: Streaming Cryptography
//! The trait operates on `R: Read` rather than `&[u8]` or `Vec<u8>`. This is a critical
//! architectural decision for performance and security. Git objects, particularly blobs,
//! can be gigabytes in size. Loading an entire object into memory to hash it would cause
//! severe memory fragmentation and potential out-of-memory (OOM) errors. By requiring a
//! reader, the hasher processes data in fixed-size chunks, maintaining a constant memory
//! footprint regardless of the input size.
use crateVctrlError;
use crateHash;
use Read;
/// Trait for computing hash values.
///
/// # Why this exists
/// In a content-addressable storage (CAS) system, the identifier of an object is derived
/// from its content. This trait provides the contract for that derivation. Separating it
/// from the encoder or storage backend allows for independent optimization and testing
/// of the cryptographic pipeline.
///
/// # How it works
/// The trait uses a generic method (`<R: Read + Send>`) instead of a dynamic trait object
/// (`&mut dyn Read`). This leverages Rust's monomorphization: the compiler generates a
/// specialized version of the `hash` method for every concrete reader type used at runtime.
/// This eliminates dynamic dispatch overhead, allowing the compiler to aggressively inline
/// the read loops and buffering logic.
///
/// # Design Rationale: Thread Safety
/// The trait requires `Send + Sync` on `Self`, and `Send` on the reader `R`. Hashing is
/// a CPU-bound, stateless operation (from the perspective of the hasher). By enforcing
/// thread safety, the engine can safely distribute hashing tasks across a thread pool.
/// For example, when writing a packfile, multiple objects can be hashed concurrently on
/// different threads without requiring external synchronization.
///
/// # Examples
///
/// Implementing the trait for a mock hasher that reads stream to completion:
///
/// ```
/// # use libvctrl_handler::traits::core::hasher::Hasher;
/// # use libvctrl_handler::{Hash, VctrlError};
/// # use std::io::Read;
/// #
/// struct MockHasher;
///
/// impl Hasher for MockHasher {
/// fn hash<R: Read + Send>(&self, mut reader: R) -> Result<Hash, VctrlError> {
/// // In a real implementation, this would update a cryptographic state
/// // (e.g., SHA-512) and finalize it. Here, we just drain the reader.
/// let mut buf = Vec::new();
/// reader.read_to_end(&mut buf)?;
/// // Return a deterministic mock hash
/// Hash::from_bytes(&[0_u8; 64])
/// }
/// }
///
/// let hasher = MockHasher;
/// let data = std::io::Cursor::new(b"some data".to_vec());
/// let hash = hasher.hash(data)?;
/// assert_eq!(hash.as_bytes(), &[0_u8; 64]);
/// # Ok::<(), VctrlError>(())
/// ```