1use super::{BranchNodeCompact, StoredNibblesSubKey};
2
3#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
7#[cfg_attr(any(test, feature = "serde"), derive(serde::Serialize, serde::Deserialize))]
8pub struct StorageTrieEntry {
9 pub nibbles: StoredNibblesSubKey,
11 pub node: BranchNodeCompact,
13}
14
15#[cfg(any(test, feature = "reth-codec"))]
19impl reth_codecs::Compact for StorageTrieEntry {
20 fn to_compact<B>(&self, buf: &mut B) -> usize
21 where
22 B: bytes::BufMut + AsMut<[u8]>,
23 {
24 let nibbles_len = self.nibbles.to_compact(buf);
25 let node_len = self.node.to_compact(buf);
26 nibbles_len + node_len
27 }
28
29 fn from_compact(buf: &[u8], len: usize) -> (Self, &[u8]) {
30 let (nibbles, buf) = StoredNibblesSubKey::from_compact(buf, 65);
31 let (node, buf) = BranchNodeCompact::from_compact(buf, len - 65);
32 let this = Self { nibbles, node };
33 (this, buf)
34 }
35}
36
37#[derive(Debug, Clone, PartialEq, Eq)]
41#[cfg_attr(any(test, feature = "serde"), derive(serde::Serialize, serde::Deserialize))]
42pub struct TrieChangeSetsEntry {
43 pub nibbles: StoredNibblesSubKey,
45 pub node: Option<BranchNodeCompact>,
47}
48
49#[cfg(any(test, feature = "reth-codec"))]
50impl reth_codecs::Compact for TrieChangeSetsEntry {
51 fn to_compact<B>(&self, buf: &mut B) -> usize
52 where
53 B: bytes::BufMut + AsMut<[u8]>,
54 {
55 let nibbles_len = self.nibbles.to_compact(buf);
56 let node_len = self.node.as_ref().map(|node| node.to_compact(buf)).unwrap_or(0);
57 nibbles_len + node_len
58 }
59
60 fn from_compact(buf: &[u8], len: usize) -> (Self, &[u8]) {
61 if len == 0 {
62 return (
64 Self { nibbles: StoredNibblesSubKey::from(super::Nibbles::default()), node: None },
65 buf,
66 )
67 }
68
69 let (nibbles, buf) = StoredNibblesSubKey::from_compact(buf, 65);
70
71 if len <= 65 {
72 return (Self { nibbles, node: None }, buf)
73 }
74
75 let (node, buf) = BranchNodeCompact::from_compact(buf, len - 65);
76 (Self { nibbles, node: Some(node) }, buf)
77 }
78}
79
80#[cfg(test)]
81mod tests {
82 use super::*;
83 use bytes::BytesMut;
84 use reth_codecs::Compact;
85
86 #[test]
87 fn test_trie_changesets_entry_full_empty() {
88 let entry = TrieChangeSetsEntry { nibbles: StoredNibblesSubKey::from(vec![]), node: None };
90
91 let mut buf = BytesMut::new();
92 let len = entry.to_compact(&mut buf);
93
94 assert_eq!(len, 65);
97 assert_eq!(buf.len(), 65);
98
99 let (decoded, remaining) = TrieChangeSetsEntry::from_compact(&buf, len);
101 assert_eq!(decoded.nibbles.0.to_vec(), Vec::<u8>::new());
102 assert_eq!(decoded.node, None);
103 assert_eq!(remaining.len(), 0);
104 }
105
106 #[test]
107 fn test_trie_changesets_entry_none_node() {
108 let nibbles_data = vec![0x01, 0x02, 0x03, 0x04];
110 let entry = TrieChangeSetsEntry {
111 nibbles: StoredNibblesSubKey::from(nibbles_data.clone()),
112 node: None,
113 };
114
115 let mut buf = BytesMut::new();
116 let len = entry.to_compact(&mut buf);
117
118 assert_eq!(len, 65);
120
121 let (decoded, remaining) = TrieChangeSetsEntry::from_compact(&buf, len);
123 assert_eq!(decoded.nibbles.0.to_vec(), nibbles_data);
124 assert_eq!(decoded.node, None);
125 assert_eq!(remaining.len(), 0);
126 }
127
128 #[test]
129 fn test_trie_changesets_entry_empty_path_with_node() {
130 let test_node = BranchNodeCompact::new(
134 0b1111_1111_1111_1111, 0b1111_1111_1111_1111, 0b0000_0000_0000_0000, vec![], None, );
140
141 let entry = TrieChangeSetsEntry {
142 nibbles: StoredNibblesSubKey::from(vec![]),
143 node: Some(test_node.clone()),
144 };
145
146 let mut buf = BytesMut::new();
147 let len = entry.to_compact(&mut buf);
148
149 let mut temp_buf = BytesMut::new();
151 let node_len = test_node.to_compact(&mut temp_buf);
152 assert_eq!(len, 65 + node_len);
153
154 let (decoded, remaining) = TrieChangeSetsEntry::from_compact(&buf, len);
156 assert_eq!(decoded.nibbles.0.to_vec(), Vec::<u8>::new());
157 assert_eq!(decoded.node, Some(test_node));
158 assert_eq!(remaining.len(), 0);
159 }
160
161 #[test]
162 fn test_trie_changesets_entry_normal() {
163 let nibbles_data = vec![0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f];
165 let test_node = BranchNodeCompact::new(
167 0b0000_0000_1111_0000, 0b0000_0000_0011_0000, 0b0000_0000_0000_0000, vec![], None, );
173
174 let entry = TrieChangeSetsEntry {
175 nibbles: StoredNibblesSubKey::from(nibbles_data.clone()),
176 node: Some(test_node.clone()),
177 };
178
179 let mut buf = BytesMut::new();
180 let len = entry.to_compact(&mut buf);
181
182 let mut temp_buf = BytesMut::new();
184 let node_len = test_node.to_compact(&mut temp_buf);
185 assert_eq!(len, 65 + node_len);
186
187 let (decoded, remaining) = TrieChangeSetsEntry::from_compact(&buf, len);
189 assert_eq!(decoded.nibbles.0.to_vec(), nibbles_data);
190 assert_eq!(decoded.node, Some(test_node));
191 assert_eq!(remaining.len(), 0);
192 }
193
194 #[test]
195 fn test_trie_changesets_entry_from_compact_zero_len() {
196 let buf = vec![0x01, 0x02, 0x03];
198 let (decoded, remaining) = TrieChangeSetsEntry::from_compact(&buf, 0);
199
200 assert_eq!(decoded.nibbles.0.to_vec(), Vec::<u8>::new());
202 assert_eq!(decoded.node, None);
203 assert_eq!(remaining, &buf[..]); }
205}