Skip to main content

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}