Skip to main content

lutra_bin/
decode.rs

1use crate::{string, vec};
2
3use crate::{Layout, ReaderExt, Result, reader};
4
5pub trait Decode: Sized + Layout {
6    fn decode(buffer: &[u8]) -> Result<Self>;
7}
8impl Decode for bool {
9    fn decode(r: &[u8]) -> Result<Self> {
10        let [v] = r.read_const::<1>();
11        Ok(v != 0)
12    }
13}
14
15impl Decode for i8 {
16    fn decode(r: &[u8]) -> Result<Self> {
17        Ok(i8::from_le_bytes(r.read_const()))
18    }
19}
20impl Decode for i16 {
21    fn decode(r: &[u8]) -> Result<Self> {
22        Ok(i16::from_le_bytes(r.read_const()))
23    }
24}
25impl Decode for i32 {
26    fn decode(r: &[u8]) -> Result<Self> {
27        Ok(i32::from_le_bytes(r.read_const()))
28    }
29}
30impl Decode for i64 {
31    fn decode(r: &[u8]) -> Result<Self> {
32        Ok(i64::from_le_bytes(r.read_const()))
33    }
34}
35impl Decode for u8 {
36    fn decode(r: &[u8]) -> Result<Self> {
37        Ok(u8::from_le_bytes(r.read_const()))
38    }
39}
40impl Decode for u16 {
41    fn decode(r: &[u8]) -> Result<Self> {
42        Ok(u16::from_le_bytes(r.read_const()))
43    }
44}
45impl Decode for u32 {
46    fn decode(r: &[u8]) -> Result<Self> {
47        Ok(u32::from_le_bytes(r.read_const()))
48    }
49}
50impl Decode for u64 {
51    fn decode(r: &[u8]) -> Result<Self> {
52        Ok(u64::from_le_bytes(r.read_const()))
53    }
54}
55impl Decode for f32 {
56    fn decode(r: &[u8]) -> Result<Self> {
57        Ok(f32::from_le_bytes(r.read_const()))
58    }
59}
60impl Decode for f64 {
61    fn decode(r: &[u8]) -> Result<Self> {
62        Ok(f64::from_le_bytes(r.read_const()))
63    }
64}
65
66impl Decode for string::String {
67    fn decode(r: &[u8]) -> Result<Self> {
68        let (offset, len) = reader::ArrayReader::<&[u8]>::read_head(r);
69
70        let buf = r.skip(offset).read_n(len).to_vec();
71        Ok(string::String::from_utf8(buf).unwrap())
72    }
73}
74impl<E: Decode> Decode for vec::Vec<E> {
75    fn decode(r: &[u8]) -> Result<Self> {
76        let (offset, len) = reader::ArrayReader::<&[u8]>::read_head(r);
77        let mut buf = r.skip(offset);
78
79        let mut out = vec::Vec::with_capacity(len);
80        let item_head_bytes = E::head_size().div_ceil(8);
81        for _ in 0..len {
82            out.push(E::decode(buf)?);
83            buf = buf.skip(item_head_bytes);
84        }
85        Ok(out)
86    }
87}
88impl<E: Decode> Decode for Option<E> {
89    fn decode(buf: &[u8]) -> Result<Self> {
90        let [tag] = buf.read_const::<1>();
91        if tag == 0 {
92            Ok(None)
93        } else {
94            let buf = buf.skip(1);
95            let inner_head_size = E::head_size();
96            let has_ptr = inner_head_size > 32;
97
98            Ok(Some(if has_ptr {
99                let offset = u32::from_le_bytes(buf.read_const::<4>()) as usize;
100                E::decode(buf.skip(offset))?
101            } else {
102                E::decode(buf)?
103            }))
104        }
105    }
106}
107impl Decode for () {
108    fn decode(_buf: &[u8]) -> Result<Self> {
109        Ok(())
110    }
111}
112
113pub fn decode_enum_head(mut data: &[u8], tag_bytes: u8, has_ptr: bool) -> (u64, &[u8]) {
114    use crate::ReaderExt;
115    use bytes::Buf;
116
117    let mut tag = vec![0; 8];
118    data.copy_to_slice(&mut tag[0..tag_bytes as usize]);
119    let tag = u64::from_le_bytes(tag.try_into().unwrap()) as u64;
120
121    if has_ptr {
122        // read ptr and dereference
123        let offset = u32::from_le_bytes(data.read_const::<4>());
124        data = data.skip(offset as usize);
125    } else {
126        // inner is right after the tag
127    }
128
129    (tag, data)
130}