binary_codec_sv2/codec/
decodable.rs

1use crate::{
2    codec::{GetSize, SizeHint},
3    datatypes::{Signature, Sv2DataType, U32AsRef, B016M, B0255, B032, B064K, U24, U256},
4    Error,
5};
6use alloc::vec::Vec;
7use core::convert::TryFrom;
8#[cfg(not(feature = "no_std"))]
9use std::io::{Cursor, Read};
10
11/// Custom deserialization of types from binary data.
12///
13/// Defines the process of reconstructing a type from a sequence of bytes. It handles both simple
14/// and nested or complex data structures.
15pub trait Decodable<'a>: Sized {
16    /// Defines the expected structure of a type based on binary data.
17    ///
18    /// Returns a vector of [`FieldMarker`]s, each representing a component of the structure.
19    /// Useful for guiding the decoding process.
20    fn get_structure(data: &[u8]) -> Result<Vec<FieldMarker>, Error>;
21
22    /// Constructs the type from a vector of decoded fields.
23    ///
24    /// After the data has been split into fields, this method combines those fields
25    /// back into the original type, handling nested structures or composite fields.
26    fn from_decoded_fields(data: Vec<DecodableField<'a>>) -> Result<Self, Error>;
27
28    /// Decodes the type from raw bytes.
29    ///
30    /// Orchestrates the decoding process, calling `get_structure` to break down
31    /// the raw data, decoding each field, and then using `from_decoded_fields` to reassemble
32    /// the fields into the original type.
33    fn from_bytes(data: &'a mut [u8]) -> Result<Self, Error> {
34        let structure = Self::get_structure(data)?;
35        let mut fields = Vec::new();
36        let mut tail = data;
37
38        for field in structure {
39            let field_size = field.size_hint_(tail, 0)?;
40            if field_size > tail.len() {
41                return Err(Error::DecodableConversionError);
42            }
43            let (head, t) = tail.split_at_mut(field_size);
44            tail = t;
45            fields.push(field.decode(head)?);
46        }
47        Self::from_decoded_fields(fields)
48    }
49
50    /// Converts a readable input to self representation.
51    ///
52    /// Reads data from an input which implements [`std::ioRead`] and constructs the original struct
53    /// out of it.
54    #[cfg(not(feature = "no_std"))]
55    fn from_reader(reader: &mut impl Read) -> Result<Self, Error> {
56        let mut data = Vec::new();
57        reader.read_to_end(&mut data)?;
58
59        let structure = Self::get_structure(&data[..])?;
60
61        let mut fields = Vec::new();
62        let mut reader = Cursor::new(data);
63
64        for field in structure {
65            fields.push(field.from_reader(&mut reader)?);
66        }
67        Self::from_decoded_fields(fields)
68    }
69}
70
71// Primitive data marker.
72//
73// Fundamental data types that can be passed to a decoder to define the structure of the type to be
74// decoded in a standardized way.
75#[derive(Debug, Clone, Copy)]
76pub enum PrimitiveMarker {
77    U8,
78    U16,
79    Bool,
80    U24,
81    U256,
82    Signature,
83    U32,
84    U32AsRef,
85    F32,
86    U64,
87    B032,
88    B0255,
89    B064K,
90    B016M,
91}
92
93/// Recursive enum representing data structure fields.
94///
95/// A `FieldMarker` can either be a primitive or a nested structure. The marker helps the decoder
96/// understand the layout and type of each field in the data, guiding the decoding process.
97#[derive(Debug, Clone)]
98pub enum FieldMarker {
99    /// A primitive data type.
100    Primitive(PrimitiveMarker),
101
102    /// A structured type composed of multiple fields, allowing for nested data.
103    Struct(Vec<FieldMarker>),
104}
105
106/// Trait for retrieving the [`FieldMarker`] associated with a type.
107///
108/// Provides a standardized way to retrieve a `FieldMarker` for a type, allowing the protocol to
109/// identify the structure and layout of data fields during decoding.
110pub trait GetMarker {
111    /// Defines the structure of a type for decoding purposes, supporting both primitive and
112    /// structured types. It helps getting a marker for a type.
113    fn get_marker() -> FieldMarker;
114}
115
116// Represents a list of decode-able primitive data types.
117//
118#[derive(Debug)]
119pub enum DecodablePrimitive<'a> {
120    U8(u8),
121    U16(u16),
122    Bool(bool),
123    U24(U24),
124    U256(U256<'a>),
125    Signature(Signature<'a>),
126    U32(u32),
127    U32AsRef(U32AsRef<'a>),
128    F32(f32),
129    U64(u64),
130    B032(B032<'a>),
131    B0255(B0255<'a>),
132    B064K(B064K<'a>),
133    B016M(B016M<'a>),
134}
135
136/// Recursive enum representing a Decode-able field.
137///
138/// May be primitive or a nested struct.
139///
140/// Once the raw data is decoded, it is either classified as a primitive (e.g., integer, Boolean)
141/// or a struct, which may itself contain multiple decoded fields. This type encapsulates that
142/// distinction.
143#[derive(Debug)]
144pub enum DecodableField<'a> {
145    /// Primitive field.
146    Primitive(DecodablePrimitive<'a>),
147
148    /// Structured field, allowing for nested data structures.
149    Struct(Vec<DecodableField<'a>>),
150}
151
152impl SizeHint for PrimitiveMarker {
153    // PrimitiveMarker needs introspection to return a size hint. This method is not implementable.
154    fn size_hint(_data: &[u8], _offset: usize) -> Result<usize, Error> {
155        unimplemented!()
156    }
157
158    fn size_hint_(&self, data: &[u8], offset: usize) -> Result<usize, Error> {
159        match self {
160            Self::U8 => u8::size_hint(data, offset),
161            Self::U16 => u16::size_hint(data, offset),
162            Self::Bool => bool::size_hint(data, offset),
163            Self::U24 => U24::size_hint(data, offset),
164            Self::U256 => U256::size_hint(data, offset),
165            Self::Signature => Signature::size_hint(data, offset),
166            Self::U32 => u32::size_hint(data, offset),
167            Self::U32AsRef => U32AsRef::size_hint(data, offset),
168            Self::F32 => f32::size_hint(data, offset),
169            Self::U64 => u64::size_hint(data, offset),
170            Self::B032 => B032::size_hint(data, offset),
171            Self::B0255 => B0255::size_hint(data, offset),
172            Self::B064K => B064K::size_hint(data, offset),
173            Self::B016M => B016M::size_hint(data, offset),
174        }
175    }
176}
177
178impl SizeHint for FieldMarker {
179    // FieldMarker need introspection to return a size hint. This method is not implementeable
180    fn size_hint(_data: &[u8], _offset: usize) -> Result<usize, Error> {
181        unimplemented!()
182    }
183
184    fn size_hint_(&self, data: &[u8], offset: usize) -> Result<usize, Error> {
185        match self {
186            Self::Primitive(p) => p.size_hint_(data, offset),
187            Self::Struct(ps) => {
188                let mut size = 0;
189                for p in ps {
190                    size += p.size_hint_(data, offset + size)?;
191                }
192                Ok(size)
193            }
194        }
195    }
196}
197
198impl SizeHint for Vec<FieldMarker> {
199    // FieldMarker need introspection to return a size hint. This method is not implementeable
200    fn size_hint(_data: &[u8], _offset: usize) -> Result<usize, Error> {
201        unimplemented!()
202    }
203
204    fn size_hint_(&self, data: &[u8], offset: usize) -> Result<usize, Error> {
205        let mut size = 0;
206        for field in self {
207            let field_size = field.size_hint_(data, offset + size)?;
208            size += field_size;
209        }
210        Ok(size)
211    }
212}
213
214impl From<PrimitiveMarker> for FieldMarker {
215    fn from(v: PrimitiveMarker) -> Self {
216        FieldMarker::Primitive(v)
217    }
218}
219
220impl TryFrom<Vec<FieldMarker>> for FieldMarker {
221    type Error = crate::Error;
222
223    fn try_from(mut v: Vec<FieldMarker>) -> Result<Self, crate::Error> {
224        match v.len() {
225            // It shouldn't be possible to call this function with a void Vec but for safety
226            // reasons it is implemented with TryFrom and not From if needed should be possible
227            // to use From and just panic
228            0 => Err(crate::Error::VoidFieldMarker),
229            // This is always safe: if v.len is 1 pop can not fail
230            1 => Ok(v.pop().unwrap()),
231            _ => Ok(FieldMarker::Struct(v)),
232        }
233    }
234}
235
236impl<'a> From<DecodableField<'a>> for Vec<DecodableField<'a>> {
237    fn from(v: DecodableField<'a>) -> Self {
238        match v {
239            DecodableField::Primitive(p) => vec![DecodableField::Primitive(p)],
240            DecodableField::Struct(ps) => ps,
241        }
242    }
243}
244
245impl PrimitiveMarker {
246    // Decodes a primitive value from a byte slice at the given offset, returning the corresponding
247    // `DecodablePrimitive`. The specific decoding logic depends on the type of the primitive (e.g.,
248    // `u8`, `u16`, etc.).
249    fn decode<'a>(&self, data: &'a mut [u8], offset: usize) -> DecodablePrimitive<'a> {
250        match self {
251            Self::U8 => DecodablePrimitive::U8(u8::from_bytes_unchecked(&mut data[offset..])),
252            Self::U16 => DecodablePrimitive::U16(u16::from_bytes_unchecked(&mut data[offset..])),
253            Self::Bool => DecodablePrimitive::Bool(bool::from_bytes_unchecked(&mut data[offset..])),
254            Self::U24 => DecodablePrimitive::U24(U24::from_bytes_unchecked(&mut data[offset..])),
255            Self::U256 => DecodablePrimitive::U256(U256::from_bytes_unchecked(&mut data[offset..])),
256            Self::Signature => {
257                DecodablePrimitive::Signature(Signature::from_bytes_unchecked(&mut data[offset..]))
258            }
259            Self::U32 => DecodablePrimitive::U32(u32::from_bytes_unchecked(&mut data[offset..])),
260            Self::U32AsRef => {
261                DecodablePrimitive::U32AsRef(U32AsRef::from_bytes_unchecked(&mut data[offset..]))
262            }
263            Self::F32 => DecodablePrimitive::F32(f32::from_bytes_unchecked(&mut data[offset..])),
264            Self::U64 => DecodablePrimitive::U64(u64::from_bytes_unchecked(&mut data[offset..])),
265            Self::B032 => DecodablePrimitive::B032(B032::from_bytes_unchecked(&mut data[offset..])),
266            Self::B0255 => {
267                DecodablePrimitive::B0255(B0255::from_bytes_unchecked(&mut data[offset..]))
268            }
269            Self::B064K => {
270                DecodablePrimitive::B064K(B064K::from_bytes_unchecked(&mut data[offset..]))
271            }
272            Self::B016M => {
273                DecodablePrimitive::B016M(B016M::from_bytes_unchecked(&mut data[offset..]))
274            }
275        }
276    }
277
278    // Decodes a primitive value from a reader stream, returning the corresponding
279    // `DecodablePrimitive`. This is useful when reading data from a file or network socket,
280    // where the data is not immediately available as a slice but must be read incrementally.
281    #[allow(clippy::wrong_self_convention)]
282    #[cfg(not(feature = "no_std"))]
283    fn from_reader<'a>(&self, reader: &mut impl Read) -> Result<DecodablePrimitive<'a>, Error> {
284        match self {
285            Self::U8 => Ok(DecodablePrimitive::U8(u8::from_reader_(reader)?)),
286            Self::U16 => Ok(DecodablePrimitive::U16(u16::from_reader_(reader)?)),
287            Self::Bool => Ok(DecodablePrimitive::Bool(bool::from_reader_(reader)?)),
288            Self::U24 => Ok(DecodablePrimitive::U24(U24::from_reader_(reader)?)),
289            Self::U256 => Ok(DecodablePrimitive::U256(U256::from_reader_(reader)?)),
290            Self::Signature => Ok(DecodablePrimitive::Signature(Signature::from_reader_(
291                reader,
292            )?)),
293            Self::U32 => Ok(DecodablePrimitive::U32(u32::from_reader_(reader)?)),
294            Self::U32AsRef => Ok(DecodablePrimitive::U32AsRef(U32AsRef::from_reader_(
295                reader,
296            )?)),
297            Self::F32 => Ok(DecodablePrimitive::F32(f32::from_reader_(reader)?)),
298            Self::U64 => Ok(DecodablePrimitive::U64(u64::from_reader_(reader)?)),
299            Self::B032 => Ok(DecodablePrimitive::B032(B032::from_reader_(reader)?)),
300            Self::B0255 => Ok(DecodablePrimitive::B0255(B0255::from_reader_(reader)?)),
301            Self::B064K => Ok(DecodablePrimitive::B064K(B064K::from_reader_(reader)?)),
302            Self::B016M => Ok(DecodablePrimitive::B016M(B016M::from_reader_(reader)?)),
303        }
304    }
305}
306
307impl GetSize for DecodablePrimitive<'_> {
308    fn get_size(&self) -> usize {
309        match self {
310            DecodablePrimitive::U8(v) => v.get_size(),
311            DecodablePrimitive::U16(v) => v.get_size(),
312            DecodablePrimitive::Bool(v) => v.get_size(),
313            DecodablePrimitive::U24(v) => v.get_size(),
314            DecodablePrimitive::U256(v) => v.get_size(),
315            DecodablePrimitive::Signature(v) => v.get_size(),
316            DecodablePrimitive::U32(v) => v.get_size(),
317            DecodablePrimitive::U32AsRef(v) => v.get_size(),
318            DecodablePrimitive::F32(v) => v.get_size(),
319            DecodablePrimitive::U64(v) => v.get_size(),
320            DecodablePrimitive::B032(v) => v.get_size(),
321            DecodablePrimitive::B0255(v) => v.get_size(),
322            DecodablePrimitive::B064K(v) => v.get_size(),
323            DecodablePrimitive::B016M(v) => v.get_size(),
324        }
325    }
326}
327
328impl FieldMarker {
329    // Implements the decoding functionality for a `FieldMarker`.
330    // Depending on whether the field is primitive or structured, this method decodes the
331    // corresponding data. If the field is a structure, it recursively decodes each nested field
332    // and returns the resulting `DecodableField`.
333    pub(crate) fn decode<'a>(&self, data: &'a mut [u8]) -> Result<DecodableField<'a>, Error> {
334        match self {
335            Self::Primitive(p) => Ok(DecodableField::Primitive(p.decode(data, 0))),
336            Self::Struct(ps) => {
337                let mut decodeds = Vec::new();
338                let mut tail = data;
339                for p in ps {
340                    let field_size = p.size_hint_(tail, 0)?;
341                    let (head, t) = tail.split_at_mut(field_size);
342                    tail = t;
343                    decodeds.push(p.decode(head)?);
344                }
345                Ok(DecodableField::Struct(decodeds))
346            }
347        }
348    }
349
350    #[allow(clippy::wrong_self_convention)]
351    #[cfg(not(feature = "no_std"))]
352    #[allow(clippy::wrong_self_convention)]
353    pub(crate) fn from_reader<'a>(
354        &self,
355        reader: &mut impl Read,
356    ) -> Result<DecodableField<'a>, Error> {
357        match self {
358            Self::Primitive(p) => Ok(DecodableField::Primitive(p.from_reader(reader)?)),
359            Self::Struct(ps) => {
360                let mut decodeds = Vec::new();
361                for p in ps {
362                    decodeds.push(p.from_reader(reader)?);
363                }
364                Ok(DecodableField::Struct(decodeds))
365            }
366        }
367    }
368}