binary_codec_sv2/codec/
decodable.rs

1use crate::{
2    codec::{GetSize, SizeHint},
3    datatypes::{
4        ShortTxId, Signature, Sv2DataType, U32AsRef, B016M, B0255, B032, B064K, U24, U256,
5    },
6    Error,
7};
8use alloc::vec::Vec;
9use std::convert::TryFrom;
10#[cfg(not(feature = "no_std"))]
11use std::io::{Cursor, Read};
12
13/// Implmented by all the decodable structure, it can be derived for every structure composed only
14/// by primitives or other Decodable.
15pub trait Decodable<'a>: Sized {
16    fn get_structure(data: &[u8]) -> Result<Vec<FieldMarker>, Error>;
17
18    fn from_decoded_fields(data: Vec<DecodableField<'a>>) -> Result<Self, Error>;
19
20    fn from_bytes(data: &'a mut [u8]) -> Result<Self, Error> {
21        let structure = Self::get_structure(data)?;
22        let mut fields = Vec::new();
23        let mut tail = data;
24
25        for field in structure {
26            let field_size = field.size_hint_(tail, 0)?;
27            if field_size > tail.len() {
28                return Err(Error::DecodableConversionError);
29            }
30            let (head, t) = tail.split_at_mut(field_size);
31            tail = t;
32            fields.push(field.decode(head)?);
33        }
34        Self::from_decoded_fields(fields)
35    }
36
37    #[cfg(not(feature = "no_std"))]
38    fn from_reader(reader: &mut impl Read) -> Result<Self, Error> {
39        let mut data = Vec::new();
40        reader.read_to_end(&mut data)?;
41
42        let structure = Self::get_structure(&data[..])?;
43
44        let mut fields = Vec::new();
45        let mut reader = Cursor::new(data);
46
47        for field in structure {
48            fields.push(field.from_reader(&mut reader)?);
49        }
50        Self::from_decoded_fields(fields)
51    }
52}
53
54/// Passed to a decoder to define the structure of the data to be decoded
55#[derive(Debug, Clone, Copy)]
56pub enum PrimitiveMarker {
57    U8,
58    U16,
59    Bool,
60    U24,
61    U256,
62    ShortTxId,
63    Signature,
64    U32,
65    U32AsRef,
66    F32,
67    U64,
68    B032,
69    B0255,
70    B064K,
71    B016M,
72}
73
74/// Passed to a decoder to define the structure of the data to be decoded
75#[derive(Debug, Clone)]
76pub enum FieldMarker {
77    Primitive(PrimitiveMarker),
78    Struct(Vec<FieldMarker>),
79}
80pub trait GetMarker {
81    fn get_marker() -> FieldMarker;
82}
83
84/// Used to contrustuct primitives is returned by the decoder
85#[derive(Debug)]
86pub enum DecodablePrimitive<'a> {
87    U8(u8),
88    U16(u16),
89    Bool(bool),
90    U24(U24),
91    U256(U256<'a>),
92    ShortTxId(ShortTxId<'a>),
93    Signature(Signature<'a>),
94    U32(u32),
95    U32AsRef(U32AsRef<'a>),
96    F32(f32),
97    U64(u64),
98    B032(B032<'a>),
99    B0255(B0255<'a>),
100    B064K(B064K<'a>),
101    B016M(B016M<'a>),
102}
103
104/// Used to contrustuct messages is returned by the decoder
105#[derive(Debug)]
106pub enum DecodableField<'a> {
107    Primitive(DecodablePrimitive<'a>),
108    Struct(Vec<DecodableField<'a>>),
109}
110
111impl SizeHint for PrimitiveMarker {
112    // PrimitiveMarker need introspection to return a size hint. This method is not implementeable
113    fn size_hint(_data: &[u8], _offset: usize) -> Result<usize, Error> {
114        unimplemented!()
115    }
116
117    fn size_hint_(&self, data: &[u8], offset: usize) -> Result<usize, Error> {
118        match self {
119            Self::U8 => u8::size_hint(data, offset),
120            Self::U16 => u16::size_hint(data, offset),
121            Self::Bool => bool::size_hint(data, offset),
122            Self::U24 => U24::size_hint(data, offset),
123            Self::U256 => U256::size_hint(data, offset),
124            Self::ShortTxId => ShortTxId::size_hint(data, offset),
125            Self::Signature => Signature::size_hint(data, offset),
126            Self::U32 => u32::size_hint(data, offset),
127            Self::U32AsRef => U32AsRef::size_hint(data, offset),
128            Self::F32 => f32::size_hint(data, offset),
129            Self::U64 => u64::size_hint(data, offset),
130            Self::B032 => B032::size_hint(data, offset),
131            Self::B0255 => B0255::size_hint(data, offset),
132            Self::B064K => B064K::size_hint(data, offset),
133            Self::B016M => B016M::size_hint(data, offset),
134        }
135    }
136}
137
138impl SizeHint for FieldMarker {
139    // FieldMarker need introspection to return a size hint. This method is not implementeable
140    fn size_hint(_data: &[u8], _offset: usize) -> Result<usize, Error> {
141        unimplemented!()
142    }
143
144    fn size_hint_(&self, data: &[u8], offset: usize) -> Result<usize, Error> {
145        match self {
146            Self::Primitive(p) => p.size_hint_(data, offset),
147            Self::Struct(ps) => {
148                let mut size = 0;
149                for p in ps {
150                    size += p.size_hint_(data, offset + size)?;
151                }
152                Ok(size)
153            }
154        }
155    }
156}
157
158impl SizeHint for Vec<FieldMarker> {
159    // FieldMarker need introspection to return a size hint. This method is not implementeable
160    fn size_hint(_data: &[u8], _offset: usize) -> Result<usize, Error> {
161        unimplemented!()
162    }
163
164    fn size_hint_(&self, data: &[u8], offset: usize) -> Result<usize, Error> {
165        let mut size = 0;
166        for field in self {
167            let field_size = field.size_hint_(data, offset + size)?;
168            size += field_size;
169        }
170        Ok(size)
171    }
172}
173
174impl From<PrimitiveMarker> for FieldMarker {
175    fn from(v: PrimitiveMarker) -> Self {
176        FieldMarker::Primitive(v)
177    }
178}
179
180impl TryFrom<Vec<FieldMarker>> for FieldMarker {
181    type Error = crate::Error;
182
183    fn try_from(mut v: Vec<FieldMarker>) -> Result<Self, crate::Error> {
184        match v.len() {
185            // It shouldn't be possible to call this function with a void Vec but for safety
186            // reasons it is implemented with TryFrom and not From if needed should be possible
187            // to use From and just panic
188            0 => Err(crate::Error::VoidFieldMarker),
189            // This is always safe: if v.len is 1 pop can not fail
190            1 => Ok(v.pop().unwrap()),
191            _ => Ok(FieldMarker::Struct(v)),
192        }
193    }
194}
195
196impl<'a> From<DecodableField<'a>> for Vec<DecodableField<'a>> {
197    fn from(v: DecodableField<'a>) -> Self {
198        match v {
199            DecodableField::Primitive(p) => vec![DecodableField::Primitive(p)],
200            DecodableField::Struct(ps) => ps,
201        }
202    }
203}
204
205impl PrimitiveMarker {
206    fn decode<'a>(&self, data: &'a mut [u8], offset: usize) -> DecodablePrimitive<'a> {
207        match self {
208            Self::U8 => DecodablePrimitive::U8(u8::from_bytes_unchecked(&mut data[offset..])),
209            Self::U16 => DecodablePrimitive::U16(u16::from_bytes_unchecked(&mut data[offset..])),
210            Self::Bool => DecodablePrimitive::Bool(bool::from_bytes_unchecked(&mut data[offset..])),
211            Self::U24 => DecodablePrimitive::U24(U24::from_bytes_unchecked(&mut data[offset..])),
212            Self::U256 => DecodablePrimitive::U256(U256::from_bytes_unchecked(&mut data[offset..])),
213            Self::ShortTxId => {
214                DecodablePrimitive::ShortTxId(ShortTxId::from_bytes_unchecked(&mut data[offset..]))
215            }
216            Self::Signature => {
217                DecodablePrimitive::Signature(Signature::from_bytes_unchecked(&mut data[offset..]))
218            }
219            Self::U32 => DecodablePrimitive::U32(u32::from_bytes_unchecked(&mut data[offset..])),
220            Self::U32AsRef => {
221                DecodablePrimitive::U32AsRef(U32AsRef::from_bytes_unchecked(&mut data[offset..]))
222            }
223            Self::F32 => DecodablePrimitive::F32(f32::from_bytes_unchecked(&mut data[offset..])),
224            Self::U64 => DecodablePrimitive::U64(u64::from_bytes_unchecked(&mut data[offset..])),
225            Self::B032 => DecodablePrimitive::B032(B032::from_bytes_unchecked(&mut data[offset..])),
226            Self::B0255 => {
227                DecodablePrimitive::B0255(B0255::from_bytes_unchecked(&mut data[offset..]))
228            }
229            Self::B064K => {
230                DecodablePrimitive::B064K(B064K::from_bytes_unchecked(&mut data[offset..]))
231            }
232            Self::B016M => {
233                DecodablePrimitive::B016M(B016M::from_bytes_unchecked(&mut data[offset..]))
234            }
235        }
236    }
237
238    #[allow(clippy::wrong_self_convention)]
239    #[cfg(not(feature = "no_std"))]
240    #[allow(clippy::wrong_self_convention)]
241    fn from_reader<'a>(&self, reader: &mut impl Read) -> Result<DecodablePrimitive<'a>, Error> {
242        match self {
243            Self::U8 => Ok(DecodablePrimitive::U8(u8::from_reader_(reader)?)),
244            Self::U16 => Ok(DecodablePrimitive::U16(u16::from_reader_(reader)?)),
245            Self::Bool => Ok(DecodablePrimitive::Bool(bool::from_reader_(reader)?)),
246            Self::U24 => Ok(DecodablePrimitive::U24(U24::from_reader_(reader)?)),
247            Self::U256 => Ok(DecodablePrimitive::U256(U256::from_reader_(reader)?)),
248            Self::ShortTxId => Ok(DecodablePrimitive::ShortTxId(ShortTxId::from_reader_(
249                reader,
250            )?)),
251            Self::Signature => Ok(DecodablePrimitive::Signature(Signature::from_reader_(
252                reader,
253            )?)),
254            Self::U32 => Ok(DecodablePrimitive::U32(u32::from_reader_(reader)?)),
255            Self::U32AsRef => Ok(DecodablePrimitive::U32AsRef(U32AsRef::from_reader_(
256                reader,
257            )?)),
258            Self::F32 => Ok(DecodablePrimitive::F32(f32::from_reader_(reader)?)),
259            Self::U64 => Ok(DecodablePrimitive::U64(u64::from_reader_(reader)?)),
260            Self::B032 => Ok(DecodablePrimitive::B032(B032::from_reader_(reader)?)),
261            Self::B0255 => Ok(DecodablePrimitive::B0255(B0255::from_reader_(reader)?)),
262            Self::B064K => Ok(DecodablePrimitive::B064K(B064K::from_reader_(reader)?)),
263            Self::B016M => Ok(DecodablePrimitive::B016M(B016M::from_reader_(reader)?)),
264        }
265    }
266}
267
268impl<'a> GetSize for DecodablePrimitive<'a> {
269    fn get_size(&self) -> usize {
270        match self {
271            DecodablePrimitive::U8(v) => v.get_size(),
272            DecodablePrimitive::U16(v) => v.get_size(),
273            DecodablePrimitive::Bool(v) => v.get_size(),
274            DecodablePrimitive::U24(v) => v.get_size(),
275            DecodablePrimitive::U256(v) => v.get_size(),
276            DecodablePrimitive::ShortTxId(v) => v.get_size(),
277            DecodablePrimitive::Signature(v) => v.get_size(),
278            DecodablePrimitive::U32(v) => v.get_size(),
279            DecodablePrimitive::U32AsRef(v) => v.get_size(),
280            DecodablePrimitive::F32(v) => v.get_size(),
281            DecodablePrimitive::U64(v) => v.get_size(),
282            DecodablePrimitive::B032(v) => v.get_size(),
283            DecodablePrimitive::B0255(v) => v.get_size(),
284            DecodablePrimitive::B064K(v) => v.get_size(),
285            DecodablePrimitive::B016M(v) => v.get_size(),
286        }
287    }
288}
289
290impl FieldMarker {
291    pub(crate) fn decode<'a>(&self, data: &'a mut [u8]) -> Result<DecodableField<'a>, Error> {
292        match self {
293            Self::Primitive(p) => Ok(DecodableField::Primitive(p.decode(data, 0))),
294            Self::Struct(ps) => {
295                let mut decodeds = Vec::new();
296                let mut tail = data;
297                for p in ps {
298                    let field_size = p.size_hint_(tail, 0)?;
299                    let (head, t) = tail.split_at_mut(field_size);
300                    tail = t;
301                    decodeds.push(p.decode(head)?);
302                }
303                Ok(DecodableField::Struct(decodeds))
304            }
305        }
306    }
307
308    #[allow(clippy::wrong_self_convention)]
309    #[cfg(not(feature = "no_std"))]
310    #[allow(clippy::wrong_self_convention)]
311    pub(crate) fn from_reader<'a>(
312        &self,
313        reader: &mut impl Read,
314    ) -> Result<DecodableField<'a>, Error> {
315        match self {
316            Self::Primitive(p) => Ok(DecodableField::Primitive(p.from_reader(reader)?)),
317            Self::Struct(ps) => {
318                let mut decodeds = Vec::new();
319                for p in ps {
320                    decodeds.push(p.from_reader(reader)?);
321                }
322                Ok(DecodableField::Struct(decodeds))
323            }
324        }
325    }
326}