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
25impl PartialEq<[u8]> for StoredNibbles {
26    #[inline]
27    fn eq(&self, other: &[u8]) -> bool {
28        self.0.as_slice() == other
29    }
30}
31
32impl PartialOrd<[u8]> for StoredNibbles {
33    #[inline]
34    fn partial_cmp(&self, other: &[u8]) -> Option<core::cmp::Ordering> {
35        self.0.as_slice().partial_cmp(other)
36    }
37}
38
39impl core::borrow::Borrow<[u8]> for StoredNibbles {
40    #[inline]
41    fn borrow(&self) -> &[u8] {
42        self.0.as_slice()
43    }
44}
45
46#[cfg(any(test, feature = "reth-codec"))]
47impl reth_codecs::Compact for StoredNibbles {
48    fn to_compact<B>(&self, buf: &mut B) -> usize
49    where
50        B: bytes::BufMut + AsMut<[u8]>,
51    {
52        buf.put_slice(self.0.as_slice());
53        self.0.len()
54    }
55
56    fn from_compact(mut buf: &[u8], len: usize) -> (Self, &[u8]) {
57        use bytes::Buf;
58
59        let nibbles = &buf[..len];
60        buf.advance(len);
61        (Self(Nibbles::from_nibbles_unchecked(nibbles)), buf)
62    }
63}
64
65/// The representation of nibbles of the merkle trie stored in the database.
66#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Deref)]
67#[cfg_attr(any(test, feature = "serde"), derive(serde::Serialize, serde::Deserialize))]
68#[cfg_attr(feature = "test-utils", derive(arbitrary::Arbitrary))]
69pub struct StoredNibblesSubKey(pub Nibbles);
70
71impl From<Nibbles> for StoredNibblesSubKey {
72    #[inline]
73    fn from(value: Nibbles) -> Self {
74        Self(value)
75    }
76}
77
78impl From<Vec<u8>> for StoredNibblesSubKey {
79    #[inline]
80    fn from(value: Vec<u8>) -> Self {
81        Self(Nibbles::from_nibbles_unchecked(value))
82    }
83}
84
85impl From<StoredNibblesSubKey> for Nibbles {
86    #[inline]
87    fn from(value: StoredNibblesSubKey) -> Self {
88        value.0
89    }
90}
91
92#[cfg(any(test, feature = "reth-codec"))]
93impl reth_codecs::Compact for StoredNibblesSubKey {
94    fn to_compact<B>(&self, buf: &mut B) -> usize
95    where
96        B: bytes::BufMut + AsMut<[u8]>,
97    {
98        assert!(self.0.len() <= 64);
99
100        // right-pad with zeros
101        buf.put_slice(&self.0[..]);
102        static ZERO: &[u8; 64] = &[0; 64];
103        buf.put_slice(&ZERO[self.0.len()..]);
104
105        buf.put_u8(self.0.len() as u8);
106        64 + 1
107    }
108
109    fn from_compact(buf: &[u8], _len: usize) -> (Self, &[u8]) {
110        let len = buf[64] as usize;
111        (Self(Nibbles::from_nibbles_unchecked(&buf[..len])), &buf[65..])
112    }
113}
114
115#[cfg(test)]
116mod tests {
117    use super::*;
118    use bytes::BytesMut;
119    use reth_codecs::Compact;
120
121    #[test]
122    fn test_stored_nibbles_from_nibbles() {
123        let nibbles = Nibbles::from_nibbles_unchecked(vec![0x12, 0x34, 0x56]);
124        let stored = StoredNibbles::from(nibbles.clone());
125        assert_eq!(stored.0, nibbles);
126    }
127
128    #[test]
129    fn test_stored_nibbles_from_vec() {
130        let bytes = vec![0x12, 0x34, 0x56];
131        let stored = StoredNibbles::from(bytes.clone());
132        assert_eq!(stored.0.as_slice(), bytes.as_slice());
133    }
134
135    #[test]
136    fn test_stored_nibbles_equality() {
137        let bytes = vec![0x12, 0x34];
138        let stored = StoredNibbles::from(bytes.clone());
139        assert_eq!(stored, *bytes.as_slice());
140    }
141
142    #[test]
143    fn test_stored_nibbles_partial_cmp() {
144        let stored = StoredNibbles::from(vec![0x12, 0x34]);
145        let other = vec![0x12, 0x35];
146        assert!(stored < *other.as_slice());
147    }
148
149    #[test]
150    fn test_stored_nibbles_to_compact() {
151        let stored = StoredNibbles::from(vec![0x12, 0x34]);
152        let mut buf = BytesMut::with_capacity(10);
153        let len = stored.to_compact(&mut buf);
154        assert_eq!(len, 2);
155        assert_eq!(buf, &vec![0x12, 0x34][..]);
156    }
157
158    #[test]
159    fn test_stored_nibbles_from_compact() {
160        let buf = vec![0x12, 0x34, 0x56];
161        let (stored, remaining) = StoredNibbles::from_compact(&buf, 2);
162        assert_eq!(stored.0.as_slice(), &[0x12, 0x34]);
163        assert_eq!(remaining, &[0x56]);
164    }
165
166    #[test]
167    fn test_stored_nibbles_subkey_from_nibbles() {
168        let nibbles = Nibbles::from_nibbles_unchecked(vec![0x12, 0x34]);
169        let subkey = StoredNibblesSubKey::from(nibbles.clone());
170        assert_eq!(subkey.0, nibbles);
171    }
172
173    #[test]
174    fn test_stored_nibbles_subkey_to_compact() {
175        let subkey = StoredNibblesSubKey::from(vec![0x12, 0x34]);
176        let mut buf = BytesMut::with_capacity(65);
177        let len = subkey.to_compact(&mut buf);
178        assert_eq!(len, 65);
179        assert_eq!(buf[..2], [0x12, 0x34]);
180        assert_eq!(buf[64], 2); // Length byte
181    }
182
183    #[test]
184    fn test_stored_nibbles_subkey_from_compact() {
185        let mut buf = vec![0x12, 0x34];
186        buf.resize(65, 0);
187        buf[64] = 2;
188        let (subkey, remaining) = StoredNibblesSubKey::from_compact(&buf, 65);
189        assert_eq!(subkey.0.as_slice(), &[0x12, 0x34]);
190        assert_eq!(remaining, &[] as &[u8]);
191    }
192
193    #[test]
194    fn test_serialization_stored_nibbles() {
195        let stored = StoredNibbles::from(vec![0x12, 0x34]);
196        let serialized = serde_json::to_string(&stored).unwrap();
197        let deserialized: StoredNibbles = serde_json::from_str(&serialized).unwrap();
198        assert_eq!(stored, deserialized);
199    }
200
201    #[test]
202    fn test_serialization_stored_nibbles_subkey() {
203        let subkey = StoredNibblesSubKey::from(vec![0x12, 0x34]);
204        let serialized = serde_json::to_string(&subkey).unwrap();
205        let deserialized: StoredNibblesSubKey = serde_json::from_str(&serialized).unwrap();
206        assert_eq!(subkey, deserialized);
207    }
208}