ethrex_rlp/structs.rs
1use super::{
2 decode::{RLPDecode, decode_rlp_item, get_item_with_prefix},
3 encode::{RLPEncode, encode_length},
4 error::RLPDecodeError,
5};
6use alloc::format;
7use alloc::vec::Vec;
8use bytes::BufMut;
9use bytes::Bytes;
10
11/// # Struct decoding helper
12///
13/// Used to decode a struct from RLP format.
14/// The struct's fields must implement [`RLPDecode`].
15/// The struct is expected as a list, with its values being the fields
16/// in the order they are passed to [`Decoder::decode_field`].
17///
18/// # Examples
19///
20/// ```
21/// # use ethrex_rlp::structs::Decoder;
22/// # use ethrex_rlp::error::RLPDecodeError;
23/// # use ethrex_rlp::decode::RLPDecode;
24/// #[derive(Debug, PartialEq, Eq)]
25/// struct Simple {
26/// pub a: u8,
27/// pub b: u16,
28/// }
29///
30/// impl RLPDecode for Simple {
31/// fn decode_unfinished(buf: &[u8]) -> Result<(Self, &[u8]), RLPDecodeError> {
32/// let decoder = Decoder::new(&buf).unwrap();
33/// // The fields are expected in the same order as given here
34/// let (a, decoder) = decoder.decode_field("a").unwrap();
35/// let (b, decoder) = decoder.decode_field("b").unwrap();
36/// let rest = decoder.finish().unwrap();
37/// Ok((Simple { a, b }, rest))
38/// }
39/// }
40///
41/// let bytes = [0xc2, 61, 75];
42/// let decoded = Simple::decode(&bytes).unwrap();
43///
44/// assert_eq!(decoded, Simple { a: 61, b: 75 });
45/// ```
46#[derive(Debug)]
47#[must_use = "`Decoder` must be consumed with `finish` to perform decoding checks"]
48pub struct Decoder<'a> {
49 payload: &'a [u8],
50 remaining: &'a [u8],
51}
52
53impl<'a> Decoder<'a> {
54 pub fn new(buf: &'a [u8]) -> Result<Self, RLPDecodeError> {
55 match decode_rlp_item(buf)? {
56 (true, payload, remaining) => Ok(Self { payload, remaining }),
57 (false, _, _) => Err(RLPDecodeError::UnexpectedString),
58 }
59 }
60
61 pub fn decode_field<T: RLPDecode>(self, name: &str) -> Result<(T, Self), RLPDecodeError> {
62 let (field, rest) = <T as RLPDecode>::decode_unfinished(self.payload)
63 .map_err(|err| field_decode_error::<T>(name, err))?;
64 let updated_self = Self {
65 payload: rest,
66 ..self
67 };
68 Ok((field, updated_self))
69 }
70
71 /// Returns the next field without decoding it, i.e. the payload bytes including its prefix.
72 pub fn get_encoded_item(self) -> Result<(Vec<u8>, Self), RLPDecodeError> {
73 self.get_encoded_item_ref()
74 .map(|(field, updated_self)| (field.to_vec(), updated_self))
75 }
76
77 /// Returns the next field without decoding it, i.e. the payload bytes including its prefix.
78 pub fn get_encoded_item_ref(self) -> Result<(&'a [u8], Self), RLPDecodeError> {
79 get_item_with_prefix(self.payload).map(|(field, rest)| {
80 let updated_self = Self {
81 payload: rest,
82 ..self
83 };
84 (field, updated_self)
85 })
86 }
87
88 /// Returns Some(field) if there's some field to decode, otherwise returns None
89 pub fn decode_optional_field<T: RLPDecode>(self) -> (Option<T>, Self) {
90 match <T as RLPDecode>::decode_unfinished(self.payload) {
91 Ok((field, rest)) => {
92 let updated_self = Self {
93 payload: rest,
94 ..self
95 };
96 (Some(field), updated_self)
97 }
98 Err(_) => (None, self),
99 }
100 }
101
102 /// Finishes encoding the struct and returns the remaining bytes after the item.
103 /// If the item's payload is not empty, returns an error.
104 pub const fn finish(self) -> Result<&'a [u8], RLPDecodeError> {
105 if self.payload.is_empty() {
106 Ok(self.remaining)
107 } else {
108 Err(RLPDecodeError::MalformedData)
109 }
110 }
111
112 /// Returns true if the decoder has finished decoding the given input
113 pub const fn is_done(&self) -> bool {
114 self.payload.is_empty()
115 }
116
117 /// Same as [`finish`](Self::finish), but discards the item's remaining payload
118 /// instead of failing.
119 pub const fn finish_unchecked(self) -> &'a [u8] {
120 self.remaining
121 }
122
123 pub const fn get_payload_len(&self) -> usize {
124 self.payload.len()
125 }
126}
127
128fn field_decode_error<T>(field_name: &str, err: RLPDecodeError) -> RLPDecodeError {
129 let typ = core::any::type_name::<T>();
130 let err_msg = format!("Error decoding field '{field_name}' of type {typ}: {err}");
131 RLPDecodeError::Custom(err_msg)
132}
133
134/// # Struct encoding helper
135///
136/// Used to encode a struct into RLP format.
137/// The struct's fields must implement [`RLPEncode`].
138/// The struct is encoded as a list, with its values being the fields
139/// in the order they are passed to [`Encoder::encode_field`].
140///
141/// # Examples
142///
143/// ```
144/// # use ethrex_rlp::structs::Encoder;
145/// # use ethrex_rlp::encode::RLPEncode;
146/// # use bytes::BufMut;
147/// #[derive(Debug, PartialEq, Eq)]
148/// struct Simple {
149/// pub a: u8,
150/// pub b: u16,
151/// }
152///
153/// impl RLPEncode for Simple {
154/// fn encode(&self, buf: &mut dyn BufMut) {
155/// // The fields are encoded in the order given here
156/// Encoder::new(buf)
157/// .encode_field(&self.a)
158/// .encode_field(&self.b)
159/// .finish();
160/// }
161/// }
162///
163/// let mut buf = vec![];
164/// Simple { a: 61, b: 75 }.encode(&mut buf);
165///
166/// assert_eq!(&buf, &[0xc2, 61, 75]);
167/// ```
168#[must_use = "`Encoder` must be consumed with `finish` to perform the encoding"]
169pub struct Encoder<'a> {
170 buf: &'a mut dyn BufMut,
171 temp_buf: Vec<u8>,
172}
173
174// NOTE: BufMut doesn't implement Debug, so we can't derive Debug for Encoder.
175impl core::fmt::Debug for Encoder<'_> {
176 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
177 f.debug_struct("Encoder")
178 .field("buf", &"...")
179 .field("temp_buf", &self.temp_buf)
180 .finish()
181 }
182}
183
184impl<'a> Encoder<'a> {
185 /// Creates a new encoder that writes to the given buffer.
186 pub fn new(buf: &'a mut dyn BufMut) -> Self {
187 // PERF: we could pre-allocate the buffer or switch to `ArrayVec`` if we could
188 // bound the size of the encoded data.
189 Self {
190 buf,
191 temp_buf: Default::default(),
192 }
193 }
194
195 /// Stores a field to be encoded.
196 pub fn encode_field<T: RLPEncode>(mut self, value: &T) -> Self {
197 <T as RLPEncode>::encode(value, &mut self.temp_buf);
198 self
199 }
200
201 /// If `Some`, stores a field to be encoded, else does nothing.
202 pub fn encode_optional_field<T: RLPEncode>(mut self, opt_value: &Option<T>) -> Self {
203 if let Some(value) = opt_value {
204 <T as RLPEncode>::encode(value, &mut self.temp_buf);
205 }
206 self
207 }
208
209 /// Stores a (key, value) list where the values are already encoded (i.e. value = RLP prefix || payload)
210 /// but the keys are not encoded
211 pub fn encode_key_value_list<T: RLPEncode>(mut self, list: &Vec<(Bytes, Bytes)>) -> Self {
212 for (key, value) in list {
213 <Bytes>::encode(key, &mut self.temp_buf);
214 // value is already encoded
215 self.temp_buf.put_slice(value);
216 }
217 self
218 }
219
220 /// Finishes encoding the struct and writes the result to the buffer.
221 pub fn finish(self) {
222 encode_length(self.temp_buf.len(), self.buf);
223 self.buf.put_slice(&self.temp_buf);
224 }
225
226 /// Adds a raw value to the buffer without rlp-encoding it
227 pub fn encode_raw(mut self, value: &[u8]) -> Self {
228 self.temp_buf.put_slice(value);
229 self
230 }
231
232 /// Stores a field to be encoded as bytes
233 /// This method is used to bypass the conflicting implementations between Vec<T> and Vec<u8>
234 pub fn encode_bytes(mut self, value: &[u8]) -> Self {
235 <[u8] as RLPEncode>::encode(value, &mut self.temp_buf);
236 self
237 }
238}