summaryrefslogtreecommitdiff
path: root/bzipper/src/serialise
diff options
context:
space:
mode:
Diffstat (limited to 'bzipper/src/serialise')
-rw-r--r--bzipper/src/serialise/mod.rs300
-rw-r--r--bzipper/src/serialise/test.rs104
-rw-r--r--bzipper/src/serialise/tuple.rs424
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(())
+ }
+}