1use super::{BranchNodeCompact, StoredNibblesSubKey};
2use reth_primitives_traits::ValueWithSubKey;
3
4#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
8#[cfg_attr(any(test, feature = "serde"), derive(serde::Serialize, serde::Deserialize))]
9pub struct StorageTrieEntry {
10 pub nibbles: StoredNibblesSubKey,
12 pub node: BranchNodeCompact,
14}
15
16impl ValueWithSubKey for StorageTrieEntry {
17 type SubKey = StoredNibblesSubKey;
18
19 fn get_subkey(&self) -> Self::SubKey {
20 self.nibbles.clone()
21 }
22}
23
24#[cfg(any(test, feature = "reth-codec"))]
28impl reth_codecs::Compact for StorageTrieEntry {
29 fn to_compact<B>(&self, buf: &mut B) -> usize
30 where
31 B: bytes::BufMut + AsMut<[u8]>,
32 {
33 let nibbles_len = self.nibbles.to_compact(buf);
34 let node_len = self.node.to_compact(buf);
35 nibbles_len + node_len
36 }
37
38 fn from_compact(buf: &[u8], len: usize) -> (Self, &[u8]) {
39 let (nibbles, buf) = StoredNibblesSubKey::from_compact(buf, 65);
40 let (node, buf) = BranchNodeCompact::from_compact(buf, len - 65);
41 let this = Self { nibbles, node };
42 (this, buf)
43 }
44}
45
46#[derive(Debug, Clone, PartialEq, Eq)]
50#[cfg_attr(any(test, feature = "serde"), derive(serde::Serialize, serde::Deserialize))]
51pub struct TrieChangeSetsEntry {
52 pub nibbles: StoredNibblesSubKey,
54 pub node: Option<BranchNodeCompact>,
56}
57
58impl ValueWithSubKey for TrieChangeSetsEntry {
59 type SubKey = StoredNibblesSubKey;
60
61 fn get_subkey(&self) -> Self::SubKey {
62 self.nibbles.clone()
63 }
64}
65
66#[cfg(any(test, feature = "reth-codec"))]
67impl reth_codecs::Compact for TrieChangeSetsEntry {
68 fn to_compact<B>(&self, buf: &mut B) -> usize
69 where
70 B: bytes::BufMut + AsMut<[u8]>,
71 {
72 let nibbles_len = self.nibbles.to_compact(buf);
73 let node_len = self.node.as_ref().map(|node| node.to_compact(buf)).unwrap_or(0);
74 nibbles_len + node_len
75 }
76
77 fn from_compact(buf: &[u8], len: usize) -> (Self, &[u8]) {
78 if len == 0 {
79 return (
81 Self { nibbles: StoredNibblesSubKey::from(super::Nibbles::default()), node: None },
82 buf,
83 )
84 }
85
86 let (nibbles, buf) = StoredNibblesSubKey::from_compact(buf, 65);
87
88 if len <= 65 {
89 return (Self { nibbles, node: None }, buf)
90 }
91
92 let (node, buf) = BranchNodeCompact::from_compact(buf, len - 65);
93 (Self { nibbles, node: Some(node) }, buf)
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_trie_changesets_entry_full_empty() {
105 let entry = TrieChangeSetsEntry { nibbles: StoredNibblesSubKey::from(vec![]), node: None };
107
108 let mut buf = BytesMut::new();
109 let len = entry.to_compact(&mut buf);
110
111 assert_eq!(len, 65);
114 assert_eq!(buf.len(), 65);
115
116 let (decoded, remaining) = TrieChangeSetsEntry::from_compact(&buf, len);
118 assert_eq!(decoded.nibbles.0.to_vec(), Vec::<u8>::new());
119 assert_eq!(decoded.node, None);
120 assert_eq!(remaining.len(), 0);
121 }
122
123 #[test]
124 fn test_trie_changesets_entry_none_node() {
125 let nibbles_data = vec![0x01, 0x02, 0x03, 0x04];
127 let entry = TrieChangeSetsEntry {
128 nibbles: StoredNibblesSubKey::from(nibbles_data.clone()),
129 node: None,
130 };
131
132 let mut buf = BytesMut::new();
133 let len = entry.to_compact(&mut buf);
134
135 assert_eq!(len, 65);
137
138 let (decoded, remaining) = TrieChangeSetsEntry::from_compact(&buf, len);
140 assert_eq!(decoded.nibbles.0.to_vec(), nibbles_data);
141 assert_eq!(decoded.node, None);
142 assert_eq!(remaining.len(), 0);
143 }
144
145 #[test]
146 fn test_trie_changesets_entry_empty_path_with_node() {
147 let test_node = BranchNodeCompact::new(
151 0b1111_1111_1111_1111, 0b1111_1111_1111_1111, 0b0000_0000_0000_0000, vec![], None, );
157
158 let entry = TrieChangeSetsEntry {
159 nibbles: StoredNibblesSubKey::from(vec![]),
160 node: Some(test_node.clone()),
161 };
162
163 let mut buf = BytesMut::new();
164 let len = entry.to_compact(&mut buf);
165
166 let mut temp_buf = BytesMut::new();
168 let node_len = test_node.to_compact(&mut temp_buf);
169 assert_eq!(len, 65 + node_len);
170
171 let (decoded, remaining) = TrieChangeSetsEntry::from_compact(&buf, len);
173 assert_eq!(decoded.nibbles.0.to_vec(), Vec::<u8>::new());
174 assert_eq!(decoded.node, Some(test_node));
175 assert_eq!(remaining.len(), 0);
176 }
177
178 #[test]
179 fn test_trie_changesets_entry_normal() {
180 let nibbles_data = vec![0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f];
182 let test_node = BranchNodeCompact::new(
184 0b0000_0000_1111_0000, 0b0000_0000_0011_0000, 0b0000_0000_0000_0000, vec![], None, );
190
191 let entry = TrieChangeSetsEntry {
192 nibbles: StoredNibblesSubKey::from(nibbles_data.clone()),
193 node: Some(test_node.clone()),
194 };
195
196 let mut buf = BytesMut::new();
197 let len = entry.to_compact(&mut buf);
198
199 let mut temp_buf = BytesMut::new();
201 let node_len = test_node.to_compact(&mut temp_buf);
202 assert_eq!(len, 65 + node_len);
203
204 let (decoded, remaining) = TrieChangeSetsEntry::from_compact(&buf, len);
206 assert_eq!(decoded.nibbles.0.to_vec(), nibbles_data);
207 assert_eq!(decoded.node, Some(test_node));
208 assert_eq!(remaining.len(), 0);
209 }
210
211 #[test]
212 fn test_trie_changesets_entry_from_compact_zero_len() {
213 let buf = vec![0x01, 0x02, 0x03];
215 let (decoded, remaining) = TrieChangeSetsEntry::from_compact(&buf, 0);
216
217 assert_eq!(decoded.nibbles.0.to_vec(), Vec::<u8>::new());
219 assert_eq!(decoded.node, None);
220 assert_eq!(remaining, &buf[..]); }
222}