diff options
Diffstat (limited to 'bzipper/src/serialise')
-rw-r--r-- | bzipper/src/serialise/mod.rs | 300 | ||||
-rw-r--r-- | bzipper/src/serialise/test.rs | 104 | ||||
-rw-r--r-- | bzipper/src/serialise/tuple.rs | 424 |
3 files changed, 828 insertions, 0 deletions
diff --git a/bzipper/src/serialise/mod.rs b/bzipper/src/serialise/mod.rs new file mode 100644 index 0000000..9c89e09 --- /dev/null +++ b/bzipper/src/serialise/mod.rs @@ -0,0 +1,300 @@ +// Copyright 2024 Gabriel Bjørnager Jensen. +// +// This file is part of bzipper. +// +// bzipper is free software: you can redistribute +// it and/or modify it under the terms of the GNU +// Lesser General Public License as published by +// the Free Software Foundation, either version 3 +// of the License, or (at your option) any later +// version. +// +// bzipper is distributed in the hope that it will +// be useful, but WITHOUT ANY WARRANTY; without +// even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Less- +// er General Public License along with bzipper. If +// not, see <https://www.gnu.org/licenses/>. + +#[cfg(test)] +mod test; + +use crate::{Error, Result, Sstream}; + +use core::{convert::Infallible, marker::PhantomData}; + +mod tuple; + +/// Denotes a type capable of being serialised. +/// +/// It is recommended to simply derive this trait for custom types. +/// It can, however, be manually implemented: +/// +/// ``` +/// use bzipper::{Result, Serialise, Sstream}; +/// +/// struct Foo { +/// bar: u16, +/// baz: f32, +/// } +/// +/// impl Serialise for Foo { +/// const SERIALISED_SIZE: usize = u16::SERIALISED_SIZE + f32::SERIALISED_SIZE; +/// +/// fn serialise(&self, buf: &mut [u8]) -> Result<()> { +/// debug_assert_eq!(buf.len(), Self::SERIALISED_SIZE); +/// +/// // Serialise fields using chaining. +/// +/// let mut stream = Sstream::new(buf); +/// +/// stream.append(&self.bar)?; +/// stream.append(&self.baz)?; +/// +/// Ok(()) +/// } +/// } +/// ``` +/// +/// Implementors of this trait should make sure that [`SERIALISED_SIZE`](Serialise::SERIALISED_SIZE) is properly defined. +/// This value indicates the definitive size of any serialisation of the `Self` type. +pub trait Serialise: Sized { + /// The amount of bytes that result from a serialisation. + /// + /// Implementors of this trait should make sure that no serialisation (or deserialisation) uses more than the amount specified by this constant. + /// When using these traits, always assume that exactly this amount has or will be used. + const SERIALISED_SIZE: usize; + + /// Serialises `self` into a slice. + /// + /// In most cases it is wiser to chain serialisations using [`Sstream`] instead of using this method directly. + /// + /// # Errors + /// + /// If serialisation failed, e.g. by an unencodable value being provided, an error is returned. + /// + /// # Panics + /// + /// This method will usually panic if the provided slice has a length *less* than the value of `SERIALISED_SIZE`. + /// Official implementations of this trait (including those that are derived) always panic in debug mode if the provided slice has a length that is different at all. + fn serialise(&self, buf: &mut [u8]) -> Result<()>; +} + +macro_rules! impl_numeric { + ($ty:ty) => { + impl ::bzipper::Serialise for $ty { + const SERIALISED_SIZE: usize = size_of::<$ty>(); + + #[inline] + fn serialise(&self, buf: &mut [u8]) -> Result<()> { + debug_assert_eq!(buf.len(), Self::SERIALISED_SIZE); + + ::core::debug_assert_eq!(buf.len(), Self::SERIALISED_SIZE); + + let data = self.to_be_bytes(); + buf.copy_from_slice(&data); + + Ok(()) + } + } + }; +} + +macro_rules! impl_non_zero { + ($ty:ty) => { + impl ::bzipper::Serialise for ::core::num::NonZero<$ty> { + const SERIALISED_SIZE: usize = ::core::mem::size_of::<$ty>(); + + #[inline(always)] + fn serialise(&self, buf: &mut [u8]) -> Result<()> { + debug_assert_eq!(buf.len(), Self::SERIALISED_SIZE); + + self.get().serialise(buf) + } + } + }; +} + +impl<T: Serialise, const N: usize> Serialise for [T; N] { + const SERIALISED_SIZE: usize = T::SERIALISED_SIZE * N; + + fn serialise(&self, buf: &mut [u8]) -> Result<()> { + debug_assert_eq!(buf.len(), Self::SERIALISED_SIZE); + + let mut stream = Sstream::new(buf); + + for v in self { stream.append(v)? } + + Ok(()) + } +} + +impl Serialise for bool { + const SERIALISED_SIZE: usize = u8::SERIALISED_SIZE; + + #[inline(always)] + fn serialise(&self, buf: &mut [u8]) -> Result<()> { + debug_assert_eq!(buf.len(), Self::SERIALISED_SIZE); + + u8::from(*self).serialise(buf) + } +} + +impl Serialise for char { + const SERIALISED_SIZE: usize = u32::SERIALISED_SIZE; + + #[inline(always)] + fn serialise(&self, buf: &mut [u8]) -> Result<()> { + debug_assert_eq!(buf.len(), Self::SERIALISED_SIZE); + + u32::from(*self).serialise(buf) + } + +} + +// Especially useful for `Result<T, Infallible>`. +// *If* that is needed, of course. +impl Serialise for Infallible { + const SERIALISED_SIZE: usize = 0x0; + + #[inline(always)] + fn serialise(&self, _buf: &mut [u8]) -> Result<()> { unreachable!() } + +} + +impl Serialise for isize { + const SERIALISED_SIZE: usize = i32::SERIALISED_SIZE; + + #[inline] + fn serialise(&self, buf: &mut [u8]) -> Result<()> { + debug_assert_eq!(buf.len(), Self::SERIALISED_SIZE); + + let value = i32::try_from(*self) + .map_err(|_| Error::IsizeOutOfRange { value: *self })?; + + value.serialise(buf) + } +} + +impl<T: Serialise> Serialise for Option<T> { + const SERIALISED_SIZE: usize = bool::SERIALISED_SIZE + T::SERIALISED_SIZE; + + fn serialise(&self, buf: &mut [u8]) -> Result<()> { + debug_assert_eq!(buf.len(), Self::SERIALISED_SIZE); + + // The first element is of type `bool` and is + // called the "sign." It signifies whether there is + // a following element or not. The remaining bytes + // are preserved if `self` is `None`. + + let mut stream = Sstream::new(buf); + + match *self { + None => { + stream.append(&false)?; + // No need to zero-fill. + }, + + Some(ref v) => { + stream.append(&true)?; + stream.append(v)?; + }, + }; + + Ok(()) + } +} + +impl<T> Serialise for PhantomData<T> { + const SERIALISED_SIZE: usize = size_of::<Self>(); + + #[inline(always)] + fn serialise(&self, buf: &mut [u8]) -> Result<()> { + debug_assert_eq!(buf.len(), Self::SERIALISED_SIZE); + + Ok(()) + } +} + +impl<T, E> Serialise for core::result::Result<T, E> +where + T: Serialise, + E: Serialise, { + const SERIALISED_SIZE: usize = bool::SERIALISED_SIZE + if size_of::<T>() > size_of::<E>() { size_of::<T>() } else { size_of::<E>() }; + + fn serialise(&self, buf: &mut [u8]) -> Result<()> { + debug_assert_eq!(buf.len(), Self::SERIALISED_SIZE); + + let mut stream = Sstream::new(buf); + + // Remember the descriminant. + match *self { + Ok(ref v) => { + stream.append(&false)?; + stream.append(v)?; + }, + + Err(ref e) => { + stream.append(&true)?; + stream.append(e)?; + }, + }; + + Ok(()) + } +} + +impl Serialise for () { + const SERIALISED_SIZE: usize = size_of::<Self>(); + + #[inline(always)] + fn serialise(&self, buf: &mut [u8]) -> Result<()> { + debug_assert_eq!(buf.len(), Self::SERIALISED_SIZE); + + Ok(()) + } +} + +impl Serialise for usize { + const SERIALISED_SIZE: Self = u32::SERIALISED_SIZE; + + fn serialise(&self, buf: &mut [u8]) -> Result<()> { + debug_assert_eq!(buf.len(), Self::SERIALISED_SIZE); + + let value = u32::try_from(*self) + .map_err(|_| Error::UsizeOutOfRange { value: *self })?; + + value.serialise(buf) + } +} + +//impl_numeric!(f128); +//impl_numeric!(f16); +impl_numeric!(f32); +impl_numeric!(f64); +impl_numeric!(i128); +impl_numeric!(i16); +impl_numeric!(i32); +impl_numeric!(i64); +impl_numeric!(i8); +impl_numeric!(u128); +impl_numeric!(u16); +impl_numeric!(u32); +impl_numeric!(u64); +impl_numeric!(u8); + +impl_non_zero!(i128); +impl_non_zero!(i16); +impl_non_zero!(i32); +impl_non_zero!(i64); +impl_non_zero!(i8); +impl_non_zero!(isize); +impl_non_zero!(u128); +impl_non_zero!(u16); +impl_non_zero!(u32); +impl_non_zero!(u64); +impl_non_zero!(u8); +impl_non_zero!(usize); diff --git a/bzipper/src/serialise/test.rs b/bzipper/src/serialise/test.rs new file mode 100644 index 0000000..f2332a5 --- /dev/null +++ b/bzipper/src/serialise/test.rs @@ -0,0 +1,104 @@ +// Copyright 2024 Gabriel Bjørnager Jensen. +// +// This file is part of bzipper. +//test!(you can redistribut => []); +// it and/or modify it under the terms of the GNU +// Lesser General Public License as published by +// the Free Software Foundation, either version 3 +// of the License, or (at your option) any later +// version. +// +// bzipper is distributed in the hope that it will +// be useful, but WITHOUT ANY WARRANTY; without +// even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Less- +// er General Public License along with bzipper. If +// not, see <https://www.gnu.org/licenses/>. + +use crate::{FixedString, Serialise}; + +#[test] +fn test_serialise() { + #[derive(Serialise)] + struct Foo(char); + + #[derive(Serialise)] + enum Bar { + Unit, + Pretty(bool), + Teacher { initials: [char; 0x3] }, + } + + assert_eq!(Foo::SERIALISED_SIZE, 0x4); + assert_eq!(Bar::SERIALISED_SIZE, 0x10); + + macro_rules! test { + ($ty:ty: $value:expr => $data:expr) => {{ + use ::bzipper::Serialise; + + let data: [u8; <$ty as Serialise>::SERIALISED_SIZE] = $data; + + let mut buf = [0x00; <$ty as Serialise>::SERIALISED_SIZE]; + <$ty as Serialise>::serialise(&mut $value, &mut buf).unwrap(); + + assert_eq!(buf, data); + }}; + } + + test!(u8: 0x00 => [0x00]); + test!(u8: 0xFF => [0xFF]); + test!(u8: 0x7F => [0x7F]); + + test!(u16: 0x0F_7E => [0x0F, 0x7E]); + + test!(u32: 0x00_2F_87_E7 => [0x00, 0x2F, 0x87, 0xE7]); + + test!(u64: 0xF3_37_CF_8B_DB_03_2B_39 => [0xF3, 0x37, 0xCF, 0x8B, 0xDB, 0x03, 0x2B, 0x39]); + + test!(u128: 0x45_A0_15_6A_36_77_17_8A_83_2E_3C_2C_84_10_58_1A => [ + 0x45, 0xA0, 0x15, 0x6A, 0x36, 0x77, 0x17, 0x8A, + 0x83, 0x2E, 0x3C, 0x2C, 0x84, 0x10, 0x58, 0x1A, + ]); + + test!(FixedString::<0x1>: FixedString::try_from("A").unwrap() => [0x00, 0x00, 0x00, 0x41, 0x00, 0x00, 0x00, 0x01]); + + test!(FixedString::<0x9>: FixedString::try_from("l\u{00F8}gma\u{00F0}ur").unwrap() => [ + 0x00, 0x00, 0x00, 0x6C, 0x00, 0x00, 0x00, 0xF8, + 0x00, 0x00, 0x00, 0x67, 0x00, 0x00, 0x00, 0x6D, + 0x00, 0x00, 0x00, 0x61, 0x00, 0x00, 0x00, 0xF0, + 0x00, 0x00, 0x00, 0x75, 0x00, 0x00, 0x00, 0x72, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + ]); + + test!([char; 0x5]: ['\u{03B4}', '\u{0190}', '\u{03BB}', '\u{03A4}', '\u{03B1}'] => [ + 0x00, 0x00, 0x03, 0xB4, 0x00, 0x00, 0x01, 0x90, + 0x00, 0x00, 0x03, 0xBB, 0x00, 0x00, 0x03, 0xA4, + 0x00, 0x00, 0x03, 0xB1, + ]); + + test!(Result::<u16, char>: Ok(0x45_45) => [0x00, 0x45, 0x45, 0x00, 0x00]); + test!(Result::<u16, char>: Err(char::REPLACEMENT_CHARACTER) => [0x01, 0x00, 0x00, 0xFF, 0xFD]); + + test!(Option<()>: None => [0x00]); + test!(Option<()>: Some(()) => [0x01]); + + test!(Foo: Foo('\u{FDF2}') => [0x00, 0x00, 0xFD, 0xF2]); + + test!(Bar: Bar::Unit => [ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + ]); + + test!(Bar: Bar::Pretty(true) => [ + 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + ]); + + test!(Bar: Bar::Teacher { initials: ['T', 'L', '\0'] } => [ + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x54, + 0x00, 0x00, 0x00, 0x4C, 0x00, 0x00, 0x00, 0x00, + ]); +}
\ No newline at end of file diff --git a/bzipper/src/serialise/tuple.rs b/bzipper/src/serialise/tuple.rs new file mode 100644 index 0000000..feee2e2 --- /dev/null +++ b/bzipper/src/serialise/tuple.rs @@ -0,0 +1,424 @@ +// Copyright 2024 Gabriel Bjørnager Jensen. +// +// This file is part of bzipper. +// +// bzipper is free software: you can redistribute +// it and/or modify it under the terms of the GNU +// Lesser General Public License as published by +// the Free Software Foundation, either version 3 +// of the License, or (at your option) any later +// version. +// +// bzipper is distributed in the hope that it will +// be useful, but WITHOUT ANY WARRANTY; without +// even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Less- +// er General Public License along with bzipper. If +// not, see <https://www.gnu.org/licenses/>. + +use crate::{Result, Serialise, Sstream}; + +impl<T0> Serialise for (T0, ) +where + T0: Serialise, { + const SERIALISED_SIZE: usize = + T0::SERIALISED_SIZE; + + fn serialise(&self, buf: &mut [u8]) -> Result<()> { + debug_assert_eq!(buf.len(), Self::SERIALISED_SIZE); + + let mut stream = Sstream::new(buf); + + stream.append(&self.0)?; + + Ok(()) + } +} + +impl<T0, T1> Serialise for (T0, T1) +where + T0: Serialise, + T1: Serialise, { + const SERIALISED_SIZE: usize = + T0::SERIALISED_SIZE + + T1::SERIALISED_SIZE; + + fn serialise(&self, buf: &mut [u8]) -> Result<()> { + debug_assert_eq!(buf.len(), Self::SERIALISED_SIZE); + + let mut stream = Sstream::new(buf); + + stream.append(&self.0)?; + stream.append(&self.1)?; + + Ok(()) + } +} + +impl<T0, T1, T2> Serialise for (T0, T1, T2) +where + T0: Serialise, + T1: Serialise, + T2: Serialise, { + const SERIALISED_SIZE: usize = + T0::SERIALISED_SIZE + + T1::SERIALISED_SIZE + + T2::SERIALISED_SIZE; + + fn serialise(&self, buf: &mut [u8]) -> Result<()> { + debug_assert_eq!(buf.len(), Self::SERIALISED_SIZE); + + let mut stream = Sstream::new(buf); + + stream.append(&self.0)?; + stream.append(&self.1)?; + stream.append(&self.2)?; + + Ok(()) + } +} + +impl<T0, T1, T2, T3> Serialise for (T0, T1, T2, T3) +where + T0: Serialise, + T1: Serialise, + T2: Serialise, + T3: Serialise, { + const SERIALISED_SIZE: usize = + T0::SERIALISED_SIZE + + T1::SERIALISED_SIZE + + T2::SERIALISED_SIZE + + T3::SERIALISED_SIZE; + + fn serialise(&self, buf: &mut [u8]) -> Result<()> { + debug_assert_eq!(buf.len(), Self::SERIALISED_SIZE); + + let mut stream = Sstream::new(buf); + + stream.append(&self.0)?; + stream.append(&self.1)?; + stream.append(&self.2)?; + stream.append(&self.3)?; + + Ok(()) + } +} + +impl<T0, T1, T2, T3, T4> Serialise for (T0, T1, T2, T3, T4) +where + T0: Serialise, + T1: Serialise, + T2: Serialise, + T3: Serialise, + T4: Serialise, { + const SERIALISED_SIZE: usize = + T0::SERIALISED_SIZE + + T1::SERIALISED_SIZE + + T2::SERIALISED_SIZE + + T3::SERIALISED_SIZE + + T4::SERIALISED_SIZE; + + fn serialise(&self, buf: &mut [u8]) -> Result<()> { + debug_assert_eq!(buf.len(), Self::SERIALISED_SIZE); + + let mut stream = Sstream::new(buf); + + stream.append(&self.0)?; + stream.append(&self.1)?; + stream.append(&self.2)?; + stream.append(&self.3)?; + stream.append(&self.4)?; + + Ok(()) + } +} + +impl<T0, T1, T2, T3, T4, T5> Serialise for (T0, T1, T2, T3, T4, T5) +where + T0: Serialise, + T1: Serialise, + T2: Serialise, + T3: Serialise, + T4: Serialise, + T5: Serialise, { + const SERIALISED_SIZE: usize = + T0::SERIALISED_SIZE + + T1::SERIALISED_SIZE + + T2::SERIALISED_SIZE + + T3::SERIALISED_SIZE + + T4::SERIALISED_SIZE + + T5::SERIALISED_SIZE; + + fn serialise(&self, buf: &mut [u8]) -> Result<()> { + debug_assert_eq!(buf.len(), Self::SERIALISED_SIZE); + + let mut stream = Sstream::new(buf); + + stream.append(&self.0)?; + stream.append(&self.1)?; + stream.append(&self.2)?; + stream.append(&self.3)?; + stream.append(&self.4)?; + stream.append(&self.5)?; + + Ok(()) + } +} + +impl<T0, T1, T2, T3, T4, T5, T6> Serialise for (T0, T1, T2, T3, T4, T5, T6) +where + T0: Serialise, + T1: Serialise, + T2: Serialise, + T3: Serialise, + T4: Serialise, + T5: Serialise, + T6: Serialise, { + const SERIALISED_SIZE: usize = + T0::SERIALISED_SIZE + + T1::SERIALISED_SIZE + + T2::SERIALISED_SIZE + + T3::SERIALISED_SIZE + + T4::SERIALISED_SIZE + + T5::SERIALISED_SIZE + + T6::SERIALISED_SIZE; + + fn serialise(&self, buf: &mut [u8]) -> Result<()> { + debug_assert_eq!(buf.len(), Self::SERIALISED_SIZE); + + let mut stream = Sstream::new(buf); + + stream.append(&self.0)?; + stream.append(&self.1)?; + stream.append(&self.2)?; + stream.append(&self.3)?; + stream.append(&self.4)?; + stream.append(&self.5)?; + stream.append(&self.6)?; + + Ok(()) + } +} + +impl<T0, T1, T2, T3, T4, T5, T6, T7> Serialise for (T0, T1, T2, T3, T4, T5, T6, T7) +where + T0: Serialise, + T1: Serialise, + T2: Serialise, + T3: Serialise, + T4: Serialise, + T5: Serialise, + T6: Serialise, + T7: Serialise, { + const SERIALISED_SIZE: usize = + T0::SERIALISED_SIZE + + T1::SERIALISED_SIZE + + T2::SERIALISED_SIZE + + T3::SERIALISED_SIZE + + T4::SERIALISED_SIZE + + T5::SERIALISED_SIZE + + T6::SERIALISED_SIZE + + T7::SERIALISED_SIZE; + + fn serialise(&self, buf: &mut [u8]) -> Result<()> { + debug_assert_eq!(buf.len(), Self::SERIALISED_SIZE); + + let mut stream = Sstream::new(buf); + + stream.append(&self.0)?; + stream.append(&self.1)?; + stream.append(&self.2)?; + stream.append(&self.3)?; + stream.append(&self.4)?; + stream.append(&self.5)?; + stream.append(&self.6)?; + stream.append(&self.7)?; + + Ok(()) + } +} + +impl<T0, T1, T2, T3, T4, T5, T6, T7, T8> Serialise for (T0, T1, T2, T3, T4, T5, T6, T7, T8) +where + T0: Serialise, + T1: Serialise, + T2: Serialise, + T3: Serialise, + T4: Serialise, + T5: Serialise, + T6: Serialise, + T7: Serialise, + T8: Serialise, { + const SERIALISED_SIZE: usize = + T0::SERIALISED_SIZE + + T1::SERIALISED_SIZE + + T2::SERIALISED_SIZE + + T3::SERIALISED_SIZE + + T4::SERIALISED_SIZE + + T5::SERIALISED_SIZE + + T6::SERIALISED_SIZE + + T7::SERIALISED_SIZE + + T8::SERIALISED_SIZE; + + fn serialise(&self, buf: &mut [u8]) -> Result<()> { + debug_assert_eq!(buf.len(), Self::SERIALISED_SIZE); + + let mut stream = Sstream::new(buf); + + stream.append(&self.0)?; + stream.append(&self.1)?; + stream.append(&self.2)?; + stream.append(&self.3)?; + stream.append(&self.4)?; + stream.append(&self.5)?; + stream.append(&self.6)?; + stream.append(&self.7)?; + stream.append(&self.8)?; + + Ok(()) + } +} + +impl<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9> Serialise for (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9) +where + T0: Serialise, + T1: Serialise, + T2: Serialise, + T3: Serialise, + T4: Serialise, + T5: Serialise, + T6: Serialise, + T7: Serialise, + T8: Serialise, + T9: Serialise, { + const SERIALISED_SIZE: usize = + T0::SERIALISED_SIZE + + T1::SERIALISED_SIZE + + T2::SERIALISED_SIZE + + T3::SERIALISED_SIZE + + T4::SERIALISED_SIZE + + T5::SERIALISED_SIZE + + T6::SERIALISED_SIZE + + T7::SERIALISED_SIZE + + T8::SERIALISED_SIZE + + T9::SERIALISED_SIZE; + + fn serialise(&self, buf: &mut [u8]) -> Result<()> { + debug_assert_eq!(buf.len(), Self::SERIALISED_SIZE); + + let mut stream = Sstream::new(buf); + + stream.append(&self.0)?; + stream.append(&self.1)?; + stream.append(&self.2)?; + stream.append(&self.3)?; + stream.append(&self.4)?; + stream.append(&self.5)?; + stream.append(&self.6)?; + stream.append(&self.7)?; + stream.append(&self.8)?; + stream.append(&self.9)?; + + Ok(()) + } +} + +impl<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> Serialise for (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10) +where + T0: Serialise, + T1: Serialise, + T2: Serialise, + T3: Serialise, + T4: Serialise, + T5: Serialise, + T6: Serialise, + T7: Serialise, + T8: Serialise, + T9: Serialise, + T10: Serialise, { + const SERIALISED_SIZE: usize = + T0::SERIALISED_SIZE + + T1::SERIALISED_SIZE + + T2::SERIALISED_SIZE + + T3::SERIALISED_SIZE + + T4::SERIALISED_SIZE + + T5::SERIALISED_SIZE + + T6::SERIALISED_SIZE + + T7::SERIALISED_SIZE + + T8::SERIALISED_SIZE + + T9::SERIALISED_SIZE + + T10::SERIALISED_SIZE; + + fn serialise(&self, buf: &mut [u8]) -> Result<()> { + debug_assert_eq!(buf.len(), Self::SERIALISED_SIZE); + + let mut stream = Sstream::new(buf); + + stream.append(&self.0)?; + stream.append(&self.1)?; + stream.append(&self.2)?; + stream.append(&self.3)?; + stream.append(&self.4)?; + stream.append(&self.5)?; + stream.append(&self.6)?; + stream.append(&self.7)?; + stream.append(&self.8)?; + stream.append(&self.9)?; + stream.append(&self.10)?; + + Ok(()) + } +} + +impl<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11> Serialise for (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11) +where + T0: Serialise, + T1: Serialise, + T2: Serialise, + T3: Serialise, + T4: Serialise, + T5: Serialise, + T6: Serialise, + T7: Serialise, + T8: Serialise, + T9: Serialise, + T10: Serialise, + T11: Serialise, { + const SERIALISED_SIZE: usize = + T0::SERIALISED_SIZE + + T1::SERIALISED_SIZE + + T2::SERIALISED_SIZE + + T3::SERIALISED_SIZE + + T4::SERIALISED_SIZE + + T5::SERIALISED_SIZE + + T6::SERIALISED_SIZE + + T7::SERIALISED_SIZE + + T8::SERIALISED_SIZE + + T9::SERIALISED_SIZE + + T10::SERIALISED_SIZE + + T11::SERIALISED_SIZE; + + fn serialise(&self, buf: &mut [u8]) -> Result<()> { + debug_assert_eq!(buf.len(), Self::SERIALISED_SIZE); + + let mut stream = Sstream::new(buf); + + stream.append(&self.0)?; + stream.append(&self.1)?; + stream.append(&self.2)?; + stream.append(&self.3)?; + stream.append(&self.4)?; + stream.append(&self.5)?; + stream.append(&self.6)?; + stream.append(&self.7)?; + stream.append(&self.8)?; + stream.append(&self.9)?; + stream.append(&self.10)?; + stream.append(&self.11)?; + + Ok(()) + } +} |