alloy_trie/hash_builder/
value.rs

1use alloc::vec::Vec;
2use alloy_primitives::{hex, B256};
3use core::fmt;
4
5/// Hash builder value.
6///
7/// Stores [`HashBuilderValueRef`] efficiently by reusing resources.
8#[derive(Clone, PartialEq, Eq)]
9#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
10pub struct HashBuilderValue {
11    /// Stores the bytes of either the leaf node value or the hash of adjacent nodes.
12    #[cfg_attr(feature = "serde", serde(with = "hex"))]
13    buf: Vec<u8>,
14    /// The kind of value that is stored in `buf`.
15    kind: HashBuilderValueKind,
16}
17
18impl Default for HashBuilderValue {
19    fn default() -> Self {
20        Self { buf: Vec::with_capacity(128), kind: HashBuilderValueKind::default() }
21    }
22}
23
24impl fmt::Debug for HashBuilderValue {
25    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
26        self.as_ref().fmt(f)
27    }
28}
29
30#[cfg(feature = "arbitrary")]
31impl<'u> arbitrary::Arbitrary<'u> for HashBuilderValue {
32    fn arbitrary(g: &mut arbitrary::Unstructured<'u>) -> arbitrary::Result<Self> {
33        let kind = HashBuilderValueKind::arbitrary(g)?;
34        let buf = match kind {
35            HashBuilderValueKind::Bytes => Vec::arbitrary(g)?,
36            HashBuilderValueKind::Hash => B256::arbitrary(g)?.to_vec(),
37        };
38        Ok(Self { buf, kind })
39    }
40}
41
42#[cfg(feature = "arbitrary")]
43impl proptest::arbitrary::Arbitrary for HashBuilderValue {
44    type Parameters = ();
45    type Strategy = proptest::strategy::BoxedStrategy<Self>;
46
47    fn arbitrary_with((): Self::Parameters) -> Self::Strategy {
48        use proptest::prelude::*;
49
50        proptest::arbitrary::any::<HashBuilderValueKind>()
51            .prop_flat_map(|kind| {
52                let range = match kind {
53                    HashBuilderValueKind::Bytes => 0..=128,
54                    HashBuilderValueKind::Hash => 32..=32,
55                };
56                proptest::collection::vec(any::<u8>(), range)
57                    .prop_map(move |buf| Self { buf, kind })
58            })
59            .boxed()
60    }
61}
62
63impl HashBuilderValue {
64    /// Creates a new empty value.
65    pub fn new() -> Self {
66        Self::default()
67    }
68
69    /// Returns the value as a reference.
70    #[inline]
71    pub fn as_ref(&self) -> HashBuilderValueRef<'_> {
72        match self.kind {
73            HashBuilderValueKind::Bytes => HashBuilderValueRef::Bytes(&self.buf),
74            HashBuilderValueKind::Hash => {
75                debug_assert_eq!(self.buf.len(), 32);
76                HashBuilderValueRef::Hash(unsafe { self.buf[..].try_into().unwrap_unchecked() })
77            }
78        }
79    }
80
81    /// Returns the value as a slice.
82    pub fn as_slice(&self) -> &[u8] {
83        &self.buf
84    }
85
86    /// Like `set_from_ref`, but takes ownership of the bytes.
87    pub fn set_bytes_owned(&mut self, bytes: Vec<u8>) {
88        self.buf = bytes;
89        self.kind = HashBuilderValueKind::Bytes;
90    }
91
92    /// Sets the value from the given bytes.
93    #[inline]
94    pub fn set_from_ref(&mut self, value: HashBuilderValueRef<'_>) {
95        self.buf.clear();
96        self.buf.extend_from_slice(value.as_slice());
97        self.kind = value.kind();
98    }
99
100    /// Clears the value.
101    #[inline]
102    pub fn clear(&mut self) {
103        self.buf.clear();
104        self.kind = HashBuilderValueKind::default();
105    }
106}
107
108/// The kind of the current hash builder value.
109#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
110#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
111#[cfg_attr(feature = "arbitrary", derive(derive_arbitrary::Arbitrary, proptest_derive::Arbitrary))]
112enum HashBuilderValueKind {
113    /// Value of the leaf node.
114    #[default]
115    Bytes,
116    /// Hash of adjacent nodes.
117    Hash,
118}
119
120/// Hash builder value reference.
121pub enum HashBuilderValueRef<'a> {
122    /// Value of the leaf node.
123    Bytes(&'a [u8]),
124    /// Hash of adjacent nodes.
125    Hash(&'a B256),
126}
127
128impl<'a> HashBuilderValueRef<'a> {
129    /// Returns the value as a slice.
130    pub const fn as_slice(&self) -> &'a [u8] {
131        match *self {
132            HashBuilderValueRef::Bytes(bytes) => bytes,
133            HashBuilderValueRef::Hash(hash) => hash.as_slice(),
134        }
135    }
136
137    /// Returns the kind of the value.
138    const fn kind(&self) -> HashBuilderValueKind {
139        match *self {
140            HashBuilderValueRef::Bytes(_) => HashBuilderValueKind::Bytes,
141            HashBuilderValueRef::Hash(_) => HashBuilderValueKind::Hash,
142        }
143    }
144}
145
146impl fmt::Debug for HashBuilderValueRef<'_> {
147    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
148        let name = match *self {
149            HashBuilderValueRef::Bytes(_) => "Bytes",
150            HashBuilderValueRef::Hash(_) => "Hash",
151        };
152        let slice = hex::encode_prefixed(self.as_slice());
153        write!(f, "{name}({slice})")
154    }
155}