reth_trie_common/
nibbles.rs1use alloc::vec::Vec;
2use derive_more::Deref;
3pub use nybbles::Nibbles;
4
5#[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#[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 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); }
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}