save_state/
lib.rs

1pub use save_state_derive::*;
2
3use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
4use paste::paste;
5use std::convert::From;
6use std::io::{
7    self, Cursor, Error as ioError, ErrorKind as ioErrorKind, Read, Result as ioResult, Write,
8};
9
10type CiboriumSerIoError = ciborium::ser::Error<io::Error>;
11type CiboriumDeIoError = ciborium::de::Error<io::Error>;
12pub type Result<T> = std::result::Result<T, Error>;
13
14pub fn serialize_into<W, T>(writer: W, value: &T) -> Result<()>
15where
16    W: std::io::Write,
17    T: serde::Serialize,
18{
19    ciborium::ser::into_writer(value, writer).map_err(|e| e.into())
20}
21
22pub fn deserialize_from<R, T>(reader: R) -> Result<T>
23where
24    R: std::io::Read,
25    T: serde::de::DeserializeOwned,
26{
27    ciborium::de::from_reader(reader).map_err(|e| e.into())
28}
29
30pub fn serialized_size<T>(value: &T) -> Result<u64>
31where
32    T: serde::Serialize,
33{
34    let mut counter = Counter::default();
35    ciborium::ser::into_writer(value, &mut counter)?;
36    Ok(counter.counter)
37}
38
39/// a simple help that implements `io::Write`, which helps get the size of
40/// a Savable object
41#[derive(Default)]
42struct Counter {
43    counter: u64,
44}
45
46impl Counter {
47    #[inline]
48    fn add(&mut self, c: usize) -> ioResult<()> {
49        // for some reason, using `checked_add` is exponentially slower, this is good
50        let (counter, overflow) = self.counter.overflowing_add(c as u64);
51        self.counter = counter;
52
53        if overflow {
54            Err(ioError::new(
55                ioErrorKind::InvalidInput,
56                "write length exceed u64 limit",
57            ))
58        } else {
59            Ok(())
60        }
61    }
62}
63
64impl Write for Counter {
65    #[inline]
66    fn write(&mut self, buf: &[u8]) -> ioResult<usize> {
67        self.add(buf.len())?;
68        Ok(buf.len())
69    }
70
71    #[inline]
72    fn write_vectored(&mut self, bufs: &[std::io::IoSlice<'_>]) -> ioResult<usize> {
73        let len = bufs.iter().map(|b| b.len()).sum();
74        self.add(len)?;
75        Ok(len)
76    }
77
78    #[inline]
79    fn write_all(&mut self, buf: &[u8]) -> ioResult<()> {
80        self.add(buf.len())?;
81        Ok(())
82    }
83
84    #[inline]
85    fn flush(&mut self) -> ioResult<()> {
86        Ok(())
87    }
88}
89
90pub trait Savable {
91    fn save<W: Write>(&self, writer: &mut W) -> Result<()>;
92    fn load<R: Read>(&mut self, reader: &mut R) -> Result<()>;
93    /// The size of the object if saved now, note that this might change, for example
94    /// due to the length of string objects or data inside the object.
95    #[inline]
96    fn save_size(&self) -> Result<u64> {
97        let mut counter = Counter::default();
98        self.save(&mut counter)?;
99        Ok(counter.counter)
100    }
101}
102
103pub fn save_object<T: Savable>(object: &T) -> Result<Vec<u8>> {
104    let mut result = Vec::new();
105    object.save(&mut result)?;
106
107    Ok(result)
108}
109
110pub fn load_object<T: Savable>(object: &mut T, data: &[u8]) -> Result<()> {
111    let mut cursor = Cursor::new(data);
112    object.load(&mut cursor)?;
113
114    let (remaining_data_len, overflow) = (data.len() as u64).overflowing_sub(cursor.position());
115    assert!(!overflow);
116
117    if remaining_data_len > 0 {
118        Err(Error::TrailingData(remaining_data_len))
119    } else {
120        Ok(())
121    }
122}
123
124#[derive(thiserror::Error, Debug)]
125pub enum Error {
126    #[error("Io Eror: {0}")]
127    IoError(ioError),
128    #[error("Cobr Serialization Error: {0}")]
129    CiboriumSerialization(CiboriumSerIoError),
130    #[error("Cobr Deserialization Error: {0}")]
131    CiboriumDeserialization(CiboriumDeIoError),
132    #[error("After loading an object, some data still remained ({0} bytes)")]
133    TrailingData(u64),
134    #[error("Enum could not be loaded correctly due to corrupted data ({0})")]
135    InvalidEnumVariant(usize),
136}
137
138impl From<ioError> for Error {
139    fn from(e: ioError) -> Self {
140        Error::IoError(e)
141    }
142}
143
144impl From<CiboriumSerIoError> for Error {
145    fn from(e: CiboriumSerIoError) -> Self {
146        Self::CiboriumSerialization(e)
147    }
148}
149
150impl From<CiboriumDeIoError> for Error {
151    fn from(e: CiboriumDeIoError) -> Self {
152        Self::CiboriumDeserialization(e)
153    }
154}
155
156macro_rules! impl_primitive {
157    ($struct_name: ident $(, $g: tt)? ) => {
158        impl Savable for $struct_name {
159            #[inline]
160            fn save<W: ::std::io::Write>(&self, writer: &mut W) -> Result<()> {
161                paste!(writer.[<write_ $struct_name>]$($g<LittleEndian>)?(*self)?);
162                Ok(())
163            }
164
165            #[inline]
166            fn load<R: ::std::io::Read>(&mut self, reader: &mut R) -> Result<()> {
167                *self = paste!(reader.[<read_ $struct_name>]$($g<LittleEndian>)?()?);
168                Ok(())
169            }
170
171            #[inline]
172            fn save_size(&self) -> Result<u64> {
173               Ok(::std::mem::size_of::<Self>() as u64)
174            }
175        }
176    };
177}
178
179// this is used here to implement some std types
180macro_rules! impl_savable_with_serde {
181    ($struct_name: ident $(<$($generics: ident),+>)?) => {
182        impl $(<$($generics: serde::Serialize + serde::de::DeserializeOwned),+>)? Savable for $struct_name $(<$($generics),+>)?{
183            #[inline]
184            fn save<W: ::std::io::Write>(&self, writer: &mut W) -> Result<()> {
185                serialize_into(writer, self)?;
186                Ok(())
187            }
188
189            #[inline]
190            fn load<R: ::std::io::Read>(&mut self, reader: &mut R) -> Result<()> {
191                let obj = deserialize_from(reader)?;
192                let _ = ::std::mem::replace(self, obj);
193                Ok(())
194            }
195        }
196    };
197}
198
199macro_rules! impl_for_tuple {
200    ($($id: tt $tuple_element: ident),+) => {
201        impl<$($tuple_element),+> Savable for ($($tuple_element),+)
202        where $($tuple_element: Savable),+
203        {
204            #[inline]
205            fn save<W: ::std::io::Write>(&self, mut writer: &mut W) -> Result<()> {
206                $(<$tuple_element as Savable>::save(&self.$id, &mut writer)?;)+
207                Ok(())
208            }
209
210            #[inline]
211            fn load<R: ::std::io::Read>(&mut self, mut reader: &mut R) -> Result<()> {
212                $(<$tuple_element as Savable>::load(&mut self.$id, &mut reader)?;)+
213                Ok(())
214            }
215        }
216    };
217}
218
219impl_primitive!(u8);
220impl_primitive!(u16, ::);
221impl_primitive!(u32, ::);
222impl_primitive!(u64, ::);
223impl_primitive!(i8);
224impl_primitive!(i16, ::);
225impl_primitive!(i32, ::);
226impl_primitive!(i64, ::);
227impl_primitive!(f32, ::);
228impl_primitive!(f64, ::);
229impl_savable_with_serde!(bool);
230impl_savable_with_serde!(char);
231impl_savable_with_serde!(String);
232impl_savable_with_serde!(Vec<T>);
233
234impl_for_tuple!(0 A0, 1 A1);
235impl_for_tuple!(0 A0, 1 A1, 2 A2);
236impl_for_tuple!(0 A0, 1 A1, 2 A2, 3 A3);
237impl_for_tuple!(0 A0, 1 A1, 2 A2, 3 A3, 4 A4);
238impl_for_tuple!(0 A0, 1 A1, 2 A2, 3 A3, 4 A4, 5 A5);
239impl_for_tuple!(0 A0, 1 A1, 2 A2, 3 A3, 4 A4, 5 A5, 6 A6);
240impl_for_tuple!(0 A0, 1 A1, 2 A2, 3 A3, 4 A4, 5 A5, 6 A6, 7 A7);
241impl_for_tuple!(0 A0, 1 A1, 2 A2, 3 A3, 4 A4, 5 A5, 6 A6, 7 A7, 8 A8);
242
243impl Savable for usize {
244    fn save<W: ::std::io::Write>(&self, writer: &mut W) -> Result<()> {
245        writer.write_u64::<LittleEndian>(*self as u64)?;
246        Ok(())
247    }
248
249    fn load<R: ::std::io::Read>(&mut self, reader: &mut R) -> Result<()> {
250        *self = reader.read_u64::<LittleEndian>()? as usize;
251        Ok(())
252    }
253
254    fn save_size(&self) -> Result<u64> {
255        Ok(::std::mem::size_of::<u64>() as u64)
256    }
257}
258
259impl Savable for isize {
260    fn save<W: ::std::io::Write>(&self, writer: &mut W) -> Result<()> {
261        writer.write_i64::<LittleEndian>(*self as i64)?;
262        Ok(())
263    }
264
265    fn load<R: ::std::io::Read>(&mut self, reader: &mut R) -> Result<()> {
266        *self = reader.read_i64::<LittleEndian>()? as isize;
267        Ok(())
268    }
269
270    fn save_size(&self) -> Result<u64> {
271        Ok(::std::mem::size_of::<i64>() as u64)
272    }
273}
274
275// TODO: wait for `min_specialization` feature and implement
276//  `u8` separatly as it would be faster
277impl<T, const N: usize> Savable for [T; N]
278where
279    T: Savable,
280{
281    fn save<W: ::std::io::Write>(&self, mut writer: &mut W) -> Result<()> {
282        for element in self {
283            element.save(&mut writer)?;
284        }
285        Ok(())
286    }
287
288    fn load<R: ::std::io::Read>(&mut self, mut reader: &mut R) -> Result<()> {
289        for element in self {
290            element.load(&mut reader)?;
291        }
292        Ok(())
293    }
294}
295
296impl<T> Savable for Option<T>
297where
298    T: Savable + Default,
299{
300    fn save<W: Write>(&self, mut writer: &mut W) -> Result<()> {
301        match self {
302            Some(s) => {
303                true.save(&mut writer)?;
304                s.save(&mut writer)?;
305            }
306            None => false.save(&mut writer)?,
307        }
308        Ok(())
309    }
310
311    fn load<R: Read>(&mut self, mut reader: &mut R) -> Result<()> {
312        let mut value = false;
313        value.load(&mut reader)?;
314
315        if value {
316            match self {
317                Some(s) => {
318                    s.load(&mut reader)?;
319                }
320                None => {
321                    let mut s = T::default();
322                    s.load(&mut reader)?;
323                    self.replace(s);
324                }
325            }
326        } else {
327            *self = None;
328        }
329
330        Ok(())
331    }
332}
333
334impl<T> Savable for std::marker::PhantomData<T> {
335    fn save<W: Write>(&self, _writer: &mut W) -> Result<()> {
336        Ok(())
337    }
338
339    fn load<R: Read>(&mut self, _reader: &mut R) -> Result<()> {
340        Ok(())
341    }
342}
343
344impl Savable for () {
345    fn save<W: Write>(&self, _writer: &mut W) -> Result<()> {
346        Ok(())
347    }
348
349    fn load<R: Read>(&mut self, _reader: &mut R) -> Result<()> {
350        Ok(())
351    }
352}