alloy_trie/hash_builder/
value.rs1use alloc::vec::Vec;
2use alloy_primitives::{hex, B256};
3use core::fmt;
4
5#[derive(Clone, PartialEq, Eq)]
9#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
10pub struct HashBuilderValue {
11 #[cfg_attr(feature = "serde", serde(with = "hex"))]
13 buf: Vec<u8>,
14 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 pub fn new() -> Self {
66 Self::default()
67 }
68
69 #[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 pub fn as_slice(&self) -> &[u8] {
83 &self.buf
84 }
85
86 pub fn set_bytes_owned(&mut self, bytes: Vec<u8>) {
88 self.buf = bytes;
89 self.kind = HashBuilderValueKind::Bytes;
90 }
91
92 #[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 #[inline]
102 pub fn clear(&mut self) {
103 self.buf.clear();
104 self.kind = HashBuilderValueKind::default();
105 }
106}
107
108#[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 #[default]
115 Bytes,
116 Hash,
118}
119
120pub enum HashBuilderValueRef<'a> {
122 Bytes(&'a [u8]),
124 Hash(&'a B256),
126}
127
128impl<'a> HashBuilderValueRef<'a> {
129 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 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}