bc_components/digest_provider.rs
1use std::{ rc::Rc, borrow::Cow };
2
3use crate::digest::Digest;
4
5/// A type that can provide a single unique digest that characterizes its contents.
6///
7/// This trait is used to define a common interface for objects that can produce a cryptographic
8/// digest (hash) of their content. Implementations of this trait use a `Cow<'_, Digest>` to avoid
9/// unnecessary cloning:
10/// - If the digest is already owned by the implementor, it can be returned by borrowing
11/// - If it doesn't exist yet, it can be created and returned by owning
12///
13/// # Use Cases
14///
15/// The `DigestProvider` trait is useful in scenarios where:
16///
17/// - You need to verify data integrity
18/// - You need a unique identifier for an object based on its content
19/// - You want to implement content-addressable storage
20/// - You need to compare objects by their content rather than identity
21///
22/// # Examples
23///
24/// Implementing `DigestProvider` for a custom type:
25///
26/// ```
27/// use std::borrow::Cow;
28/// use bc_components::{Digest, DigestProvider};
29///
30/// struct Document {
31/// content: Vec<u8>,
32/// cached_digest: Option<Digest>,
33/// }
34///
35/// impl Document {
36/// fn new(content: Vec<u8>) -> Self {
37/// Self {
38/// content,
39/// cached_digest: None,
40/// }
41/// }
42/// }
43///
44/// impl DigestProvider for Document {
45/// fn digest(&self) -> Cow<'_, Digest> {
46/// match &self.cached_digest {
47/// Some(digest) => Cow::Borrowed(digest),
48/// None => Cow::Owned(Digest::from_image(&self.content)),
49/// }
50/// }
51/// }
52///
53/// // Create a document and get its digest
54/// let doc = Document::new(b"important data".to_vec());
55/// let digest = doc.digest();
56/// ```
57///
58/// Using the provided implementation for `&[u8]`:
59///
60/// ```
61/// use std::borrow::Cow;
62/// use bc_components::{Digest, DigestProvider};
63///
64/// // The DigestProvider is implemented for &[u8], not for &[u8; N]
65/// let data: &[u8] = b"hello world";
66/// let digest_cow: Cow<'_, Digest> = data.digest();
67/// ```
68pub trait DigestProvider {
69 /// Returns a digest that uniquely characterizes the content of the implementing type.
70 fn digest(&self) -> Cow<'_, Digest>;
71}
72
73/// Implements DigestProvider for byte slices, creating a digest from the slice's contents.
74impl DigestProvider for &[u8] {
75 fn digest(&self) -> Cow<'_, Digest> {
76 Cow::Owned(Digest::from_image(self))
77 }
78}
79
80/// Implements DigestProvider for Rc-wrapped types that implement DigestProvider,
81/// delegating to the inner type's implementation.
82impl<T> DigestProvider for Rc<T> where T: DigestProvider {
83 fn digest(&self) -> Cow<'_, Digest> {
84 self.as_ref().digest()
85 }
86}