1use super::{super::Nibbles, encode_path_leaf, unpack_path_to_nibbles, RlpNode};
2use alloy_primitives::{hex, Bytes};
3use alloy_rlp::{length_of_length, BufMut, Decodable, Encodable, Header};
4use core::fmt;
5
6#[allow(unused_imports)]
7use alloc::vec::Vec;
8
9#[derive(PartialEq, Eq, Clone)]
17#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
18pub struct LeafNode {
19 pub key: Nibbles,
21 pub value: Vec<u8>,
23}
24
25impl fmt::Debug for LeafNode {
26 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
27 f.debug_struct("LeafNode")
28 .field("key", &self.key)
29 .field("value", &hex::encode(&self.value))
30 .finish()
31 }
32}
33
34impl Encodable for LeafNode {
35 #[inline]
36 fn encode(&self, out: &mut dyn BufMut) {
37 self.as_ref().encode(out)
38 }
39
40 #[inline]
41 fn length(&self) -> usize {
42 self.as_ref().length()
43 }
44}
45
46impl Decodable for LeafNode {
47 fn decode(buf: &mut &[u8]) -> alloy_rlp::Result<Self> {
48 let mut bytes = Header::decode_bytes(buf, true)?;
49 let encoded_key = Bytes::decode(&mut bytes)?;
50 if encoded_key.is_empty() {
51 return Err(alloy_rlp::Error::Custom("leaf node key empty"));
52 }
53
54 let first = match encoded_key[0] & 0xf0 {
56 Self::ODD_FLAG => Some(encoded_key[0] & 0x0f),
57 Self::EVEN_FLAG => None,
58 _ => return Err(alloy_rlp::Error::Custom("node is not leaf")),
59 };
60
61 let key = unpack_path_to_nibbles(first, &encoded_key[1..]);
62 let value = Bytes::decode(&mut bytes)?.into();
63 Ok(Self { key, value })
64 }
65}
66
67impl LeafNode {
68 pub const EVEN_FLAG: u8 = 0x20;
70
71 pub const ODD_FLAG: u8 = 0x30;
73
74 pub const fn new(key: Nibbles, value: Vec<u8>) -> Self {
76 Self { key, value }
77 }
78
79 pub fn as_ref(&self) -> LeafNodeRef<'_> {
81 LeafNodeRef { key: &self.key, value: &self.value }
82 }
83}
84
85pub struct LeafNodeRef<'a> {
87 pub key: &'a Nibbles,
89 pub value: &'a [u8],
91}
92
93impl fmt::Debug for LeafNodeRef<'_> {
94 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
95 f.debug_struct("LeafNodeRef")
96 .field("key", &self.key)
97 .field("value", &hex::encode(self.value))
98 .finish()
99 }
100}
101
102impl Encodable for LeafNodeRef<'_> {
104 #[inline]
105 fn encode(&self, out: &mut dyn BufMut) {
106 Header { list: true, payload_length: self.rlp_payload_length() }.encode(out);
107 encode_path_leaf(self.key, true).as_slice().encode(out);
108 self.value.encode(out);
109 }
110
111 #[inline]
112 fn length(&self) -> usize {
113 let payload_length = self.rlp_payload_length();
114 payload_length + length_of_length(payload_length)
115 }
116}
117
118impl<'a> LeafNodeRef<'a> {
119 pub const fn new(key: &'a Nibbles, value: &'a [u8]) -> Self {
121 Self { key, value }
122 }
123
124 #[inline]
126 pub fn rlp(&self, rlp: &mut Vec<u8>) -> RlpNode {
127 self.encode(rlp);
128 RlpNode::from_rlp(rlp)
129 }
130
131 #[inline]
133 fn rlp_payload_length(&self) -> usize {
134 let mut encoded_key_len = self.key.len() / 2 + 1;
135 if encoded_key_len != 1 {
137 encoded_key_len += length_of_length(encoded_key_len);
138 }
139 encoded_key_len + Encodable::length(&self.value)
140 }
141}
142
143#[cfg(test)]
144mod tests {
145 use super::*;
146
147 #[test]
149 fn encode_leaf_node_nibble() {
150 let nibbles = Nibbles::from_nibbles_unchecked(hex!("0604060f"));
151 let encoded = encode_path_leaf(&nibbles, true);
152 assert_eq!(encoded[..], hex!("20646f"));
153 }
154
155 #[test]
156 fn rlp_leaf_node_roundtrip() {
157 let nibble = Nibbles::from_nibbles_unchecked(hex!("0604060f"));
158 let val = hex!("76657262");
159 let leaf = LeafNode::new(nibble, val.to_vec());
160 let rlp = leaf.as_ref().rlp(&mut vec![]);
161 assert_eq!(rlp.as_ref(), hex!("c98320646f8476657262"));
162 assert_eq!(LeafNode::decode(&mut &rlp[..]).unwrap(), leaf);
163 }
164}