instrs_core/
lib.rs

1#![feature(array_try_from_fn)]
2#![feature(split_array)]
3#![feature(trait_alias)]
4
5use thiserror::Error;
6
7#[derive(Debug, Error)]
8pub enum Error {
9    /// The bytecode provided is too short. This should only ever happen if the bytecode is
10    /// outdated, or something went wrong when generating it.
11    #[error("Expected {0} bytes")]
12    ExpectedBytes(u32),
13    /// Expected a value in a given range, e.g., bools must be between 0 and 1.
14    #[error("Expected a value in the range {0:?}")]
15    ExpectedRange(std::ops::RangeInclusive<u32>),
16    /// Parsing a string resulted in invalid utf8. 
17    #[error("Attempted to parse string with invalid utf8: {0:?}")]
18    InvalidUtf8(std::string::FromUtf8Error),
19    /// See [Size](crate::Size).
20    ///
21    /// This error is generated when [into_bytes](crate::Serialize::into_bytes) is called 
22    /// on a variable-length struct with >= 2^`S` items 
23    #[error("{needed_bytes} bytes are needed to store this item's length, but only {max_bytes} bytes are available. Try increasing `S`.")]
24    TooLarge {
25        needed_bytes: u32,
26        max_bytes: u32,
27    },
28    /// Encountered an invalid utf8 sequence
29    #[error("Encountered an invalid utf8 sequence")]
30    InvalidChar,
31}
32
33/// Represents a type that can be used to encode the size of a variable-length struct like
34/// [Vec] and [String]. For example, a `u8` will be cheap and efficient, but
35/// every vec in the bytecode can only be a maximum of 256 items long. 
36///
37/// ```rust
38/// assert_eq!(
39///     <Vec::<u8>>::from_bytes::<u8>(&mut [3,1,2,3].as_slice()), 
40///     Ok(vec![1,2,3])
41/// );
42/// assert_eq!(
43///     <Vec::<u8>>::from_bytes::<u16>(&mut [3,0, 1,2,3].as_slice()), 
44///     Ok(vec![1,2,3])
45/// );
46/// ```
47///
48/// *Note*: You should not use a `usize` since this makes your bytecode platform-dependent.
49pub trait Size = Serialize + TryFrom<usize> + Into<usize>;
50
51/// An item that can be Serialized into bytes. 
52///
53/// # Examples
54/// ```
55/// // `S` parameter is needed in all cases
56/// assert_eq!(u32::from_bytes::<u8>(&mut [3,0,0,0].as_slice(), Ok(3u32)));
57///
58/// // Passing more bytes than needed is not an error
59/// assert_eq!(bool::from_bytes::<u8>(&mut [1,0,0,0,0].as_slice()), Ok(true));
60///
61/// assert_eq!([char; 4]::from_bytes::<u8>(&mut [65,0,0,0, 66,0,0,0, 67,0,0,0, 68,0,0,0].as_slice()), ['A', 'B', 'C', 'D']);
62/// assert_eq!(String::from_bytes::<u8>(&mut [4, 65,66,67,68].as_slice()), String::from("ABCD"));
63/// ```
64pub trait Serialize: Sized {
65    fn from_bytes<S: Size>(b: &mut &[u8]) -> Result<Self, Error>;
66    fn into_bytes<S: Size>(&self, b: &mut Vec<u8>) -> Result<(), Error>;
67}
68
69macro_rules! impl_byte_serialize {
70    ($($t:ty),+) => {
71        $(
72            impl Serialize for $t {
73                fn from_bytes<S: Size>(b: &mut &[u8]) -> Result<Self, Error> { const SIZE: usize = std::mem::size_of::<$t>();
74
75                    if SIZE > b.len() {return Err(Error::ExpectedBytes((SIZE - b.len()) as u32))};
76
77                    let (bytes, rem) = b.split_array_ref::<SIZE>();
78                    *b = rem;
79
80                    Ok(<$t>::from_le_bytes(*bytes))
81                }
82
83                fn into_bytes<S: Size>(&self, b: &mut Vec<u8>) -> Result<(), Error> {
84                    let bytes = self.to_le_bytes();
85
86                    b.extend_from_slice(&bytes);
87
88                    Ok(())
89                }
90            }
91        )+
92    }
93}
94
95impl_byte_serialize!(u8,u16,u32,u64,u128,usize,
96                     // Using signed numbers in bytecode is stupid but I still support it because I am a nice person
97                     i8,i16,i32,i64,i128,isize,
98                     f32,f64);
99
100impl Serialize for char {
101    fn from_bytes<S: Size>(b: &mut &[u8]) -> Result<Self, Error> {
102        match char::from_u32(u32::from_bytes::<S>(b)?) {
103            Some(c) => Ok(c),
104            None => Err(Error::InvalidChar),
105        }
106    }
107
108    fn into_bytes<S: Size>(&self, b: &mut Vec<u8>) -> Result<(), Error> {
109        (*self as u32).into_bytes::<S>(b)
110    }
111}
112
113impl Serialize for bool {
114    fn from_bytes<S: Size>(b: &mut &[u8]) -> Result<Self, Error> {
115        let Some((byte, rem)) = b.split_first() else {return Err(Error::ExpectedBytes(1))};
116        *b = rem;
117
118        match byte {
119            0 => Ok(false),
120            1 => Ok(true),
121            _ => Err(Error::ExpectedRange(0..=1)),
122        } 
123    }
124
125    fn into_bytes<S: Size>(&self, b: &mut Vec<u8>) -> Result<(), Error> {
126        (*self as u8).into_bytes::<S>(b)
127    }
128}
129
130macro_rules! impl_byte_serialize_tuple {
131    ( $($i:ident $n:tt),* ) => {
132        #[allow(unused_variables)]
133        impl<$($i : Serialize),*> Serialize for ( $($i,)* ) {
134            fn from_bytes<S: Size>(b: &mut &[u8]) -> Result<Self, Error> {
135                Ok((
136                    $($i::from_bytes::<S>(b)?,)*
137                ))
138            }
139
140            fn into_bytes<S: Size>(&self, b: &mut Vec<u8>) -> Result<(), Error> {
141                $(self.$n.into_bytes::<S>(b)?;)*
142                Ok(())
143            }
144        }
145    }
146}
147
148impl_byte_serialize_tuple!();
149impl_byte_serialize_tuple!(A 0);
150impl_byte_serialize_tuple!(A 0, B 1);
151impl_byte_serialize_tuple!(A 0, B 1, C 2);
152impl_byte_serialize_tuple!(A 0, B 1, C 2, D 3);
153impl_byte_serialize_tuple!(A 0, B 1, C 2, D 3, E 4);
154impl_byte_serialize_tuple!(A 0, B 1, C 2, D 3, E 4, F 5);
155impl_byte_serialize_tuple!(A 0, B 1, C 2, D 3, E 4, F 5, G 6);
156impl_byte_serialize_tuple!(A 0, B 1, C 2, D 3, E 4, F 5, G 6, H 7);
157impl_byte_serialize_tuple!(A 0, B 1, C 2, D 3, E 4, F 5, G 6, H 7, J 8);
158impl_byte_serialize_tuple!(A 0, B 1, C 2, D 3, E 4, F 5, G 6, H 7, J 8, K 9);
159impl_byte_serialize_tuple!(A 0, B 1, C 2, D 3, E 4, F 5, G 6, H 7, J 8, K 9, L 10);
160
161
162impl<B: Serialize, const N: usize> Serialize for [B; N] {
163    fn from_bytes<S: Size>(b: &mut &[u8]) -> Result<Self, Error> {
164        std::array::try_from_fn(|_| {
165            <B>::from_bytes::<S>(b)
166        })
167    }
168
169    fn into_bytes<S: Size>(&self, b: &mut Vec<u8>) -> Result<(), Error> {
170        self.iter().try_for_each(|inner| {
171            inner.into_bytes::<S>(b)
172        })
173    }
174}
175
176fn push_len<S: Size>(len: usize, b: &mut Vec<u8>) -> Result<(), Error> {
177    //`len` is bigger than can be stored in `S`. This is much more likely than the error in
178    //`from_bytes` since many implementations may choose an `S` of u8 to prioritize speed, but run
179    //out of space at 256 items.
180
181    let len = match len.try_into() {
182        Ok(len) => len,
183        Err(_) => return Err(Error::TooLarge {
184            needed_bytes: len.ilog2(),
185            max_bytes: std::mem::size_of::<S>() as u32,
186        }),
187    };
188
189    S::into_bytes::<S>(&len, b)
190}
191
192impl<B: Serialize> Serialize for Vec<B> {
193    fn from_bytes<S: Size>(b: &mut &[u8]) -> Result<Self, Error> {
194        //The length of the vec will be too large to store on this machine's memory.
195        //In reality this should never happen since, if S > usize, the machine will fail to load
196        //the bytecode into memory.
197
198        let len = match S::from_bytes::<S>(b)?.try_into() {
199            Ok(len) => len,
200            Err(_) => return Err(Error::TooLarge {
201                needed_bytes: std::mem::size_of::<S>() as u32,
202                max_bytes: std::mem::size_of::<usize>() as u32,
203            })
204        };
205
206        let mut v = Vec::with_capacity(len);
207
208        for _ in 0..len {
209            let next = <B>::from_bytes::<S>(b)?;
210            v.push(next);
211        }
212
213        Ok(v)
214    }
215
216    fn into_bytes<S: Size>(&self, b: &mut Vec<u8>) -> Result<(), Error> {
217        push_len::<S>(self.len(), b)?;
218
219        self.iter()
220            .try_for_each(|inner| {
221                inner.into_bytes::<S>(b)
222            })
223    }
224}
225
226impl<B: Serialize> Serialize for Box<[B]> {
227    fn from_bytes<S: Size>(b: &mut &[u8]) -> Result<Self, Error> {
228        Ok(<Vec<B>>::from_bytes::<S>(b)?.into_boxed_slice())
229    }
230
231    fn into_bytes<S: Size>(&self, b: &mut Vec<u8>) -> Result<(), Error> {
232        self.iter()
233            .try_for_each(|inner| {
234                inner.into_bytes::<S>(b)
235            })
236    }
237}
238
239impl<B: Serialize> Serialize for Box<B> {
240    fn from_bytes<S: Size>(b: &mut &[u8]) -> Result<Self, Error> {
241        Ok(Box::new(B::from_bytes::<S>(b)?))
242    }
243
244    fn into_bytes<S: Size>(&self, b: &mut Vec<u8>) -> Result<(), Error> {
245        B::into_bytes::<S>(self, b)
246    }
247}
248
249impl<B: Serialize> Serialize for Option<B> {
250    fn from_bytes<S: Size>(b: &mut &[u8]) -> Result<Self, Error> {
251        let is_some = bool::from_bytes::<S>(b)?;
252
253        match is_some {
254            false => Ok(None),
255            true => Ok(Some(B::from_bytes::<S>(b)?)),
256        }
257    }
258
259    fn into_bytes<S: Size>(&self, b: &mut Vec<u8>) -> Result<(), Error> {
260        self.is_some().into_bytes::<S>(b)?;
261
262        if let Some(inner) = self {
263            inner.into_bytes::<S>(b)?;
264        }
265
266        Ok(())
267    }
268}
269
270impl Serialize for String {
271    fn from_bytes<S: Size>(b: &mut &[u8]) -> Result<Self, Error> {
272        match std::string::String::from_utf8(<Vec<u8>>::from_bytes::<S>(b)?) {
273            Ok(s) => Ok(s),
274            Err(e) => Err(Error::InvalidUtf8(e)),
275        }
276    }
277
278    fn into_bytes<S: Size>(&self, b: &mut Vec<u8>) -> Result<(), Error> {
279        self.as_str().into_bytes::<S>(b)
280    }
281}
282
283impl Serialize for &str {
284    /// This function will panic. Make sure to convert to an owned `String` instead
285    fn from_bytes<S: Size>(_b: &mut &[u8]) -> Result<Self, Error> {
286        panic!("Can't convert bytes to &'str. Try converting to an owned `String` instead")
287    }
288
289    fn into_bytes<S: Size>(&self, b: &mut Vec<u8>) -> Result<(), Error> {
290        push_len::<S>(self.len(), b)?;
291        b.extend_from_slice(self.as_bytes());
292
293        Ok(())
294    }
295}