bc_components/
digest_provider.rs

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