reth_trie_common/
nibbles.rs

1use alloc::vec::Vec;
2use derive_more::Deref;
3pub use nybbles::Nibbles;
4
5/// The representation of nibbles of the merkle trie stored in the database.
6#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash, derive_more::Index)]
7#[cfg_attr(any(test, feature = "serde"), derive(serde::Serialize, serde::Deserialize))]
8#[cfg_attr(feature = "test-utils", derive(arbitrary::Arbitrary))]
9pub struct StoredNibbles(pub Nibbles);
10
11impl From<Nibbles> for StoredNibbles {
12    #[inline]
13    fn from(value: Nibbles) -> Self {
14        Self(value)
15    }
16}
17
18impl From<Vec<u8>> for StoredNibbles {
19    #[inline]
20    fn from(value: Vec<u8>) -> Self {
21        Self(Nibbles::from_nibbles_unchecked(value))
22    }
23}
24
25#[cfg(any(test, feature = "reth-codec"))]
26impl reth_codecs::Compact for StoredNibbles {
27    fn to_compact<B>(&self, buf: &mut B) -> usize
28    where
29        B: bytes::BufMut + AsMut<[u8]>,
30    {
31        for i in self.0.iter() {
32            buf.put_u8(i);
33        }
34        self.0.len()
35    }
36
37    fn from_compact(mut buf: &[u8], len: usize) -> (Self, &[u8]) {
38        use bytes::Buf;
39
40        let nibbles = &buf[..len];
41        buf.advance(len);
42        (Self(Nibbles::from_nibbles_unchecked(nibbles)), buf)
43    }
44}
45
46/// The representation of nibbles of the merkle trie stored in the database.
47#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Deref)]
48#[cfg_attr(any(test, feature = "serde"), derive(serde::Serialize, serde::Deserialize))]
49#[cfg_attr(feature = "test-utils", derive(arbitrary::Arbitrary))]
50pub struct StoredNibblesSubKey(pub Nibbles);
51
52impl From<Nibbles> for StoredNibblesSubKey {
53    #[inline]
54    fn from(value: Nibbles) -> Self {
55        Self(value)
56    }
57}
58
59impl From<Vec<u8>> for StoredNibblesSubKey {
60    #[inline]
61    fn from(value: Vec<u8>) -> Self {
62        Self(Nibbles::from_nibbles_unchecked(value))
63    }
64}
65
66impl From<StoredNibblesSubKey> for Nibbles {
67    #[inline]
68    fn from(value: StoredNibblesSubKey) -> Self {
69        value.0
70    }
71}
72
73#[cfg(any(test, feature = "reth-codec"))]
74impl reth_codecs::Compact for StoredNibblesSubKey {
75    fn to_compact<B>(&self, buf: &mut B) -> usize
76    where
77        B: bytes::BufMut + AsMut<[u8]>,
78    {
79        assert!(self.0.len() <= 64);
80
81        // right-pad with zeros
82        for i in self.0.iter() {
83            buf.put_u8(i);
84        }
85        static ZERO: &[u8; 64] = &[0; 64];
86        buf.put_slice(&ZERO[self.0.len()..]);
87
88        buf.put_u8(self.0.len() as u8);
89        64 + 1
90    }
91
92    fn from_compact(buf: &[u8], _len: usize) -> (Self, &[u8]) {
93        let len = buf[64] as usize;
94        (Self(Nibbles::from_nibbles_unchecked(&buf[..len])), &buf[65..])
95    }
96}
97
98#[cfg(test)]
99mod tests {
100    use super::*;
101    use bytes::BytesMut;
102    use reth_codecs::Compact;
103
104    #[test]
105    fn test_stored_nibbles_from_nibbles() {
106        let nibbles = Nibbles::from_nibbles_unchecked(vec![0x02, 0x04, 0x06]);
107        let stored = StoredNibbles::from(nibbles);
108        assert_eq!(stored.0, nibbles);
109    }
110
111    #[test]
112    fn test_stored_nibbles_from_vec() {
113        let bytes = vec![0x02, 0x04, 0x06];
114        let stored = StoredNibbles::from(bytes.clone());
115        assert_eq!(stored.0.to_vec(), bytes);
116    }
117
118    #[test]
119    fn test_stored_nibbles_to_compact() {
120        let stored = StoredNibbles::from(vec![0x02, 0x04]);
121        let mut buf = BytesMut::with_capacity(10);
122        let len = stored.to_compact(&mut buf);
123        assert_eq!(len, 2);
124        assert_eq!(buf, &vec![0x02, 0x04][..]);
125    }
126
127    #[test]
128    fn test_stored_nibbles_from_compact() {
129        let buf = vec![0x02, 0x04, 0x06];
130        let (stored, remaining) = StoredNibbles::from_compact(&buf, 2);
131        assert_eq!(stored.0.to_vec(), vec![0x02, 0x04]);
132        assert_eq!(remaining, &[0x06]);
133    }
134
135    #[test]
136    fn test_stored_nibbles_subkey_to_compact() {
137        let subkey = StoredNibblesSubKey::from(vec![0x02, 0x04]);
138        let mut buf = BytesMut::with_capacity(65);
139        let len = subkey.to_compact(&mut buf);
140        assert_eq!(len, 65);
141        assert_eq!(buf[..2], [0x02, 0x04]);
142        assert_eq!(buf[64], 2); // Length byte
143    }
144
145    #[test]
146    fn test_stored_nibbles_subkey_from_compact() {
147        let mut buf = vec![0x02, 0x04];
148        buf.resize(65, 0);
149        buf[64] = 2;
150        let (subkey, remaining) = StoredNibblesSubKey::from_compact(&buf, 65);
151        assert_eq!(subkey.0.to_vec(), vec![0x02, 0x04]);
152        assert_eq!(remaining, &[] as &[u8]);
153    }
154
155    #[test]
156    fn test_serialization_stored_nibbles() {
157        let stored = StoredNibbles::from(vec![0x02, 0x04]);
158        let serialized = serde_json::to_string(&stored).unwrap();
159        let deserialized: StoredNibbles = serde_json::from_str(&serialized).unwrap();
160        assert_eq!(stored, deserialized);
161    }
162
163    #[test]
164    fn test_serialization_stored_nibbles_subkey() {
165        let subkey = StoredNibblesSubKey::from(vec![0x02, 0x04]);
166        let serialized = serde_json::to_string(&subkey).unwrap();
167        let deserialized: StoredNibblesSubKey = serde_json::from_str(&serialized).unwrap();
168        assert_eq!(subkey, deserialized);
169    }
170}