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