diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/buffer/mod.rs | 172 | ||||
-rw-r--r-- | src/deserialise/mod.rs | 512 | ||||
-rw-r--r-- | src/deserialise/test.rs | 81 | ||||
-rw-r--r-- | src/dstream/mod.rs | 86 | ||||
-rw-r--r-- | src/error/mod.rs | 112 | ||||
-rw-r--r-- | src/fixed_string/mod.rs | 298 | ||||
-rw-r--r-- | src/fixed_string/test.rs | 43 | ||||
-rw-r--r-- | src/fixed_string_iter/mod.rs | 43 | ||||
-rw-r--r-- | src/lib.rs | 123 | ||||
-rw-r--r-- | src/serialise/mod.rs | 676 | ||||
-rw-r--r-- | src/serialise/test.rs | 72 | ||||
-rw-r--r-- | src/sstream/mod.rs | 103 |
12 files changed, 0 insertions, 2321 deletions
diff --git a/src/buffer/mod.rs b/src/buffer/mod.rs deleted file mode 100644 index 3ce47bd..0000000 --- a/src/buffer/mod.rs +++ /dev/null @@ -1,172 +0,0 @@ -// 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 impl<T: Serialise>ied warranty of MERCHANTABILITY<T> 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::{Deserialise, Dstream, Serialise, Sstream}; - -use alloc::vec; -use alloc::boxed::Box; -use core::fmt::{Debug, Formatter}; -use core::marker::PhantomData; - -/// Container type for (de)serialisations. -/// -/// The purpose of this type is to easily hold a buffer than can fit any serialisation of a given type (hence the generic). -/// -/// Do note that the internal buffer does not guarantee the state of any padding bytes that occur as a result of different serialisation sizes. -/// Deserialisations, however, are not affected by these. -#[derive(Clone, Eq, PartialEq)] -pub struct Buffer<T> { - data: Box<[u8]>, - len: usize, - - _phantom: PhantomData<T>, -} - -impl<T> Buffer<T> { - /// Sets the internal length of the buffer without checks. - /// - /// For a safe alternative, see [`set_len`](Self::set_len). - /// - /// # Safety - /// - /// The new length must **not** exceed [`T::SERIALISE_LIMIT`](Serialise::SERIALISE_LIMIT). - #[inline(always)] - pub unsafe fn set_len_unchecked(&mut self, len: usize) { - self.len = len; - } - - /// Returns a slice of the internal buffer. - /// - /// This only includes bytes written by the last serialisation, or as set by [`set_len`](Self::set_len). - #[inline(always)] - #[must_use] - pub fn as_slice(&self) -> &[u8] { &self.data[0x0..self.len] } - - /// Returns a mutable slice of the entire internal buffer. - /// - /// This is in contrast to [`as_slice`](Self::as_slice), which only yields the last serialisation. - /// - /// The length of bytes written to this slice should be set using [`set_len`](Self::set_len). - #[inline(always)] - #[must_use] - pub fn as_mut_slice(&mut self) -> &mut [u8] { self.data.as_mut() } -} - -impl<T: Serialise> Buffer<T> { - /// Constructs a new, empty buffer. - /// - /// The internal buffer is allocated on the heap instantly with the size [`T::SERIALISE_LIMIT`](Serialise::SERIALISE_LIMIT). - #[inline(always)] - #[must_use] - pub fn new() -> Self { Self { - data: vec![Default::default(); T::SERIALISE_LIMIT].into(), - len: 0x0, - - _phantom: PhantomData - } } - - /// Sets the length of the current serialisation. - /// - /// This is specifically meant for cases where the buffer is set externally, as is the case for networking: - /// - /// ``` - /// use bzipper::{Buffer, FixedString}; - /// use std::net::{SocketAddr, UdpSocket}; - /// use std::str::FromStr; - /// - /// let destination = SocketAddr::from_str("127.0.0.1:37279")?; - /// - /// let sender = UdpSocket::bind("0.0.0.0:0")?; - /// let reciever = UdpSocket::bind(destination)?; - /// - /// // Create a buffer for holding a fixed string. - /// let mut buffer = Buffer::<FixedString<0x10>>::new(); - /// - /// // Serialise and write the string: - /// buffer.write(&FixedString::new("Hello there!")?); - /// sender.send_to(buffer.as_ref(), destination); - /// - /// // Recieve and deserialise the string: - /// let (count, _source) = reciever.recv_from(buffer.as_mut_slice())?; - /// buffer.set_len(count); - /// - /// assert_eq!(buffer.read()?, "Hello there!"); - /// - /// # Ok::<(), Box<dyn std::error::Error>>(()) - /// ``` - /// - /// # Panics - /// - /// Panics if `len` is larger than [`T::SERIALISE_LIMIT`](Serialise::SERIALISE_LIMIT). - /// See [`set_len_unchecked`](Self::set_len_unchecked). - #[inline] - pub fn set_len(&mut self, len: usize) { - assert!(len <= T::SERIALISE_LIMIT); - self.len = len; - } -} - -impl<T: Serialise> Buffer<T> { - /// Serialises into the buffer. - /// - /// The result of [`serialise`](Serialise::serialise) is used as the length. - /// - /// # Panics - /// - /// Panics if the amount of written bytes exceeds [`SERIALISE_LIMIT`](Serialise::SERIALISE_LIMIT). - /// This *should*, in theory, not occur, as the internal buffer can only fit up to this limit, making all writes past this limit fail. - #[allow(clippy::panic_in_result_fn)] - pub fn write(&mut self, value: &T) -> Result<(), <T as Serialise>::Error> { - let mut stream = Sstream::new(&mut self.data); - - let count = value.serialise(&mut stream)?; - assert!(count <= T::SERIALISE_LIMIT); - - self.len = count; - Ok(()) - } -} - -impl<T: Deserialise> Buffer<T> { - /// Deserialises the contained buffer. - /// - /// Only bytes from the last serialisation, or as set by [`set_len`](Self::set_len), are used. - pub fn read(&self) -> Result<T, <T as Deserialise>::Error> { - let mut stream = Dstream::new(self.as_ref()); - T::deserialise(&mut stream) - } -} - -impl<T> AsRef<[u8]> for Buffer<T> { - #[inline(always)] - fn as_ref(&self) -> &[u8] { self.as_slice() } -} - -impl<T> Debug for Buffer<T> { - fn fmt(&self, f: &mut Formatter) -> core::fmt::Result { - self.data.fmt(f) - } -} - -impl<T: Serialise> Default for Buffer<T> { - #[inline(always)] - fn default() -> Self { Self::new() } -} diff --git a/src/deserialise/mod.rs b/src/deserialise/mod.rs deleted file mode 100644 index eaebe2b..0000000 --- a/src/deserialise/mod.rs +++ /dev/null @@ -1,512 +0,0 @@ -// 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, Dstream}; - -use alloc::boxed::Box; -use core::convert::Infallible; -use core::error::Error as StdError; -use core::mem::{MaybeUninit, size_of}; -use core::num::NonZero; -use core::ptr::read; - -/// Types capable of being deserialised. -pub trait Deserialise: Sized { - /// The error of deserialisation. - /// - /// Use [`Infallible`] if **all** deserialisations are infallible, as is the case of zero-length types. - type Error; - - /// Deserialises the byte stream to an object. - /// - /// This function should **not** take more bytes than specified by [`T::SERIALISE_LIMIT`](crate::Serialise::SERIALISE_LIMIT). - /// Doing so is considered a logic error. - /// - /// # Errors - /// - /// If deserialisation failed, e.g. by an invalid value being found, an error is returned. - fn deserialise(stream: &mut Dstream) -> Result<Self, Self::Error>; -} - -macro_rules! impl_float { - ($type:ty) => { - impl Deserialise for $type { - type Error = Error; - - fn deserialise(stream: &mut Dstream) -> Result<Self, Self::Error> { - let data = stream - .take(size_of::<Self>())? - .try_into() - .unwrap(); - - Ok(Self::from_be_bytes(data)) - } - } - }; -} - -macro_rules! impl_int { - ($type:ty) => { - impl Deserialise for $type { - type Error = Error; - - fn deserialise(stream: &mut Dstream) -> Result<Self, Self::Error> { - let data = stream - .take(size_of::<Self>())? - .try_into() - .unwrap(); - - Ok(Self::from_be_bytes(data)) - } - } - }; -} - -macro_rules! impl_non_zero { - ($type:ty) => { - impl Deserialise for NonZero<$type> { - type Error = Error; - - fn deserialise(stream: &mut Dstream) -> Result<Self, Self::Error> { - let value = <$type>::deserialise(stream)?; - - NonZero::new(value) - .ok_or(Error::NullInteger) - } - } - }; -} - -impl<T0, T1> Deserialise for (T0, T1) -where - T0: Deserialise<Error: StdError + 'static>, - T1: Deserialise<Error: StdError + 'static>, { - type Error = Box<dyn StdError>; - - fn deserialise(stream: &mut Dstream) -> Result<Self, Self::Error> { - Ok(( - Deserialise::deserialise(stream)?, - Deserialise::deserialise(stream)?, - )) - } -} - -impl<T0, T1, T2> Deserialise for (T0, T1, T2) -where - T0: Deserialise<Error: StdError + 'static>, - T1: Deserialise<Error: StdError + 'static>, - T2: Deserialise<Error: StdError + 'static>, { - type Error = Box<dyn StdError>; - - fn deserialise(stream: &mut Dstream) -> Result<Self, Self::Error> { - Ok(( - Deserialise::deserialise(stream)?, - Deserialise::deserialise(stream)?, - Deserialise::deserialise(stream)?, - )) - } -} - -impl<T0, T1, T2, T3> Deserialise for (T0, T1, T2, T3) -where - T0: Deserialise<Error: StdError + 'static>, - T1: Deserialise<Error: StdError + 'static>, - T2: Deserialise<Error: StdError + 'static>, - T3: Deserialise<Error: StdError + 'static>, { - type Error = Box<dyn StdError>; - - fn deserialise(stream: &mut Dstream) -> Result<Self, Self::Error> { - Ok(( - Deserialise::deserialise(stream)?, - Deserialise::deserialise(stream)?, - Deserialise::deserialise(stream)?, - Deserialise::deserialise(stream)?, - )) - } -} - -impl<T0, T1, T2, T3, T4> Deserialise for (T0, T1, T2, T3, T4) -where - T0: Deserialise<Error: StdError + 'static>, - T1: Deserialise<Error: StdError + 'static>, - T2: Deserialise<Error: StdError + 'static>, - T3: Deserialise<Error: StdError + 'static>, - T4: Deserialise<Error: StdError + 'static>, { - type Error = Box<dyn StdError>; - - fn deserialise(stream: &mut Dstream) -> Result<Self, Self::Error> { - Ok(( - Deserialise::deserialise(stream)?, - Deserialise::deserialise(stream)?, - Deserialise::deserialise(stream)?, - Deserialise::deserialise(stream)?, - Deserialise::deserialise(stream)?, - )) - } -} - -impl<T0, T1, T2, T3, T4, T5> Deserialise for (T0, T1, T2, T3, T4, T5) -where - T0: Deserialise<Error: StdError + 'static>, - T1: Deserialise<Error: StdError + 'static>, - T2: Deserialise<Error: StdError + 'static>, - T3: Deserialise<Error: StdError + 'static>, - T4: Deserialise<Error: StdError + 'static>, - T5: Deserialise<Error: StdError + 'static>, { - type Error = Box<dyn StdError>; - - fn deserialise(stream: &mut Dstream) -> Result<Self, Self::Error> { - Ok(( - Deserialise::deserialise(stream)?, - Deserialise::deserialise(stream)?, - Deserialise::deserialise(stream)?, - Deserialise::deserialise(stream)?, - Deserialise::deserialise(stream)?, - Deserialise::deserialise(stream)?, - )) - } -} - -impl<T0, T1, T2, T3, T4, T5, T6> Deserialise for (T0, T1, T2, T3, T4, T5, T6) -where - T0: Deserialise<Error: StdError + 'static>, - T1: Deserialise<Error: StdError + 'static>, - T2: Deserialise<Error: StdError + 'static>, - T3: Deserialise<Error: StdError + 'static>, - T4: Deserialise<Error: StdError + 'static>, - T5: Deserialise<Error: StdError + 'static>, - T6: Deserialise<Error: StdError + 'static>, { - type Error = Box<dyn StdError>; - - fn deserialise(stream: &mut Dstream) -> Result<Self, Self::Error> { - Ok(( - Deserialise::deserialise(stream)?, - Deserialise::deserialise(stream)?, - Deserialise::deserialise(stream)?, - Deserialise::deserialise(stream)?, - Deserialise::deserialise(stream)?, - Deserialise::deserialise(stream)?, - Deserialise::deserialise(stream)?, - )) - } -} - -impl<T0, T1, T2, T3, T4, T5, T6, T7> Deserialise for (T0, T1, T2, T3, T4, T5, T6, T7) -where - T0: Deserialise<Error: StdError + 'static>, - T1: Deserialise<Error: StdError + 'static>, - T2: Deserialise<Error: StdError + 'static>, - T3: Deserialise<Error: StdError + 'static>, - T4: Deserialise<Error: StdError + 'static>, - T5: Deserialise<Error: StdError + 'static>, - T6: Deserialise<Error: StdError + 'static>, - T7: Deserialise<Error: StdError + 'static>, { - type Error = Box<dyn StdError>; - - fn deserialise(stream: &mut Dstream) -> Result<Self, Self::Error> { - Ok(( - Deserialise::deserialise(stream)?, - Deserialise::deserialise(stream)?, - Deserialise::deserialise(stream)?, - Deserialise::deserialise(stream)?, - Deserialise::deserialise(stream)?, - Deserialise::deserialise(stream)?, - Deserialise::deserialise(stream)?, - Deserialise::deserialise(stream)?, - )) - } -} - -impl<T0, T1, T2, T3, T4, T5, T6, T7, T8> Deserialise for (T0, T1, T2, T3, T4, T5, T6, T7, T8) -where - T0: Deserialise<Error: StdError + 'static>, - T1: Deserialise<Error: StdError + 'static>, - T2: Deserialise<Error: StdError + 'static>, - T3: Deserialise<Error: StdError + 'static>, - T4: Deserialise<Error: StdError + 'static>, - T5: Deserialise<Error: StdError + 'static>, - T6: Deserialise<Error: StdError + 'static>, - T7: Deserialise<Error: StdError + 'static>, - T8: Deserialise<Error: StdError + 'static>, { - type Error = Box<dyn StdError>; - - fn deserialise(stream: &mut Dstream) -> Result<Self, Self::Error> { - Ok(( - Deserialise::deserialise(stream)?, - Deserialise::deserialise(stream)?, - Deserialise::deserialise(stream)?, - Deserialise::deserialise(stream)?, - Deserialise::deserialise(stream)?, - Deserialise::deserialise(stream)?, - Deserialise::deserialise(stream)?, - Deserialise::deserialise(stream)?, - Deserialise::deserialise(stream)?, - )) - } -} - -impl<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9> Deserialise for (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9) -where - T0: Deserialise<Error: StdError + 'static>, - T1: Deserialise<Error: StdError + 'static>, - T2: Deserialise<Error: StdError + 'static>, - T3: Deserialise<Error: StdError + 'static>, - T4: Deserialise<Error: StdError + 'static>, - T5: Deserialise<Error: StdError + 'static>, - T6: Deserialise<Error: StdError + 'static>, - T7: Deserialise<Error: StdError + 'static>, - T8: Deserialise<Error: StdError + 'static>, - T9: Deserialise<Error: StdError + 'static>, { - type Error = Box<dyn StdError>; - - fn deserialise(stream: &mut Dstream) -> Result<Self, Self::Error> { - Ok(( - Deserialise::deserialise(stream)?, - Deserialise::deserialise(stream)?, - Deserialise::deserialise(stream)?, - Deserialise::deserialise(stream)?, - Deserialise::deserialise(stream)?, - Deserialise::deserialise(stream)?, - Deserialise::deserialise(stream)?, - Deserialise::deserialise(stream)?, - Deserialise::deserialise(stream)?, - Deserialise::deserialise(stream)?, - )) - } -} - -impl<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> Deserialise for (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10) -where - T0: Deserialise<Error: StdError + 'static>, - T1: Deserialise<Error: StdError + 'static>, - T2: Deserialise<Error: StdError + 'static>, - T3: Deserialise<Error: StdError + 'static>, - T4: Deserialise<Error: StdError + 'static>, - T5: Deserialise<Error: StdError + 'static>, - T6: Deserialise<Error: StdError + 'static>, - T7: Deserialise<Error: StdError + 'static>, - T8: Deserialise<Error: StdError + 'static>, - T9: Deserialise<Error: StdError + 'static>, - T10: Deserialise<Error: StdError + 'static>, { - type Error = Box<dyn StdError>; - - fn deserialise(stream: &mut Dstream) -> Result<Self, Self::Error> { - Ok(( - Deserialise::deserialise(stream)?, - Deserialise::deserialise(stream)?, - Deserialise::deserialise(stream)?, - Deserialise::deserialise(stream)?, - Deserialise::deserialise(stream)?, - Deserialise::deserialise(stream)?, - Deserialise::deserialise(stream)?, - Deserialise::deserialise(stream)?, - Deserialise::deserialise(stream)?, - Deserialise::deserialise(stream)?, - Deserialise::deserialise(stream)?, - )) - } -} - -impl<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11> Deserialise for (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11) -where - T0: Deserialise<Error: StdError + 'static>, - T1: Deserialise<Error: StdError + 'static>, - T2: Deserialise<Error: StdError + 'static>, - T3: Deserialise<Error: StdError + 'static>, - T4: Deserialise<Error: StdError + 'static>, - T5: Deserialise<Error: StdError + 'static>, - T6: Deserialise<Error: StdError + 'static>, - T7: Deserialise<Error: StdError + 'static>, - T8: Deserialise<Error: StdError + 'static>, - T9: Deserialise<Error: StdError + 'static>, - T10: Deserialise<Error: StdError + 'static>, - T11: Deserialise<Error: StdError + 'static>, { - type Error = Box<dyn StdError>; - - fn deserialise(stream: &mut Dstream) -> Result<Self, Self::Error> { - Ok(( - Deserialise::deserialise(stream)?, - Deserialise::deserialise(stream)?, - Deserialise::deserialise(stream)?, - Deserialise::deserialise(stream)?, - Deserialise::deserialise(stream)?, - Deserialise::deserialise(stream)?, - Deserialise::deserialise(stream)?, - Deserialise::deserialise(stream)?, - Deserialise::deserialise(stream)?, - Deserialise::deserialise(stream)?, - Deserialise::deserialise(stream)?, - Deserialise::deserialise(stream)?, - )) - } -} - -impl<T, const N: usize> Deserialise for [T; N] -where - T: Default + Deserialise<Error: StdError + 'static>, { - type Error = Box<dyn StdError>; - - fn deserialise(stream: &mut Dstream) -> Result<Self, Self::Error> { - let len = usize::deserialise(stream)?; - - if len != N { return Err(Box::new(Error::ArrayTooShort { req: len, len: N })) }; - - let mut buf: [MaybeUninit<T>; N] = unsafe { MaybeUninit::uninit().assume_init() }; - - // Deserialise t - for item in buf.iter_mut().take(len) { - item.write(Deserialise::deserialise(stream)?); - } - - for item in buf.iter_mut().skip(len) { - item.write(Default::default()); - } - - // This should be safe as `MaybeUninit<T>` is - // transparent to `T`. The original buffer is - // NOT dropped automatically, so we can just - // forget about it from this point on. - let buf = unsafe { read(core::ptr::from_ref(&buf).cast::<[T; N]>()) }; - Ok(buf) - } -} - -impl Deserialise for () { - type Error = Infallible; - - fn deserialise(_stream: &mut Dstream) -> Result<Self, Self::Error> { Ok(()) } -} - -impl Deserialise for bool { - type Error = Error; - - fn deserialise(stream: &mut Dstream) -> Result<Self, Self::Error> { - let value = u8::deserialise(stream)?; - - match value { - 0x00 => Ok(false), - 0x01 => Ok(true), - _ => Err(Error::InvalidBoolean { value }) - } - } -} - -impl Deserialise for char { - type Error = Error; - - fn deserialise(stream: &mut Dstream) -> Result<Self, Self::Error> { - let value = u32::deserialise(stream)?; - - Self::from_u32(value) - .ok_or(Error::InvalidCodePoint { value }) - } -} - -impl Deserialise for Infallible { - type Error = Self; - - fn deserialise(_stream: &mut Dstream) -> Result<Self, Self::Error> { unreachable!() } -} - -impl Deserialise for isize { - type Error = Error; - - fn deserialise(stream: &mut Dstream) -> Result<Self, Self::Error> { - let value = i16::deserialise(stream)? - .into(); - - Ok(value) - } -} - -impl<T: Deserialise<Error: StdError + 'static>> Deserialise for Option<T> { - type Error = Box<dyn StdError>; - - fn deserialise(stream: &mut Dstream) -> Result<Self, Self::Error> { - let sign = bool::deserialise(stream)?; - - if sign { - Ok(Some(T::deserialise(stream)?)) - } else { - Ok(None) - } - } -} - -impl<T: Deserialise, E: Deserialise> Deserialise for Result<T, E> -where - <T as Deserialise>::Error: StdError + 'static, - <E as Deserialise>::Error: StdError + 'static, { - type Error = Box<dyn StdError>; - - fn deserialise(stream: &mut Dstream) -> Result<Self, Self::Error> { - let sign = bool::deserialise(stream)?; - - let value = if sign { - Err(E::deserialise(stream)?) - } else { - Ok(T::deserialise(stream)?) - }; - - Ok(value) - } -} - -impl Deserialise for usize { - type Error = Error; - - fn deserialise(stream: &mut Dstream) -> Result<Self, Self::Error> { - let value = u16::deserialise(stream)? - .into(); - - Ok(value) - } -} - -impl_float!(f32); -impl_float!(f64); - -impl_int!(i128); -impl_int!(i16); -impl_int!(i32); -impl_int!(i64); -impl_int!(i8); -impl_int!(u128); -impl_int!(u16); -impl_int!(u32); -impl_int!(u64); -impl_int!(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/src/deserialise/test.rs b/src/deserialise/test.rs deleted file mode 100644 index e398b4d..0000000 --- a/src/deserialise/test.rs +++ /dev/null @@ -1,81 +0,0 @@ -// 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::{Deserialise, Dstream, FixedString}; - -#[test] -fn test_deserialise() { - let data = [ - 0x00, 0xFF, 0xFF, 0x0F, 0xEF, 0x1F, 0xDF, 0x2F, - 0xCF, 0x3F, 0xBF, 0x4F, 0xAF, 0x5F, 0x9F, 0x6F, - 0x8F, 0x7F, 0x00, 0x09, 0x6D, 0xC3, 0xA1, 0x6E, - 0x61, 0xC3, 0xB0, 0x75, 0x72, 0x00, 0x05, 0x00, - 0x00, 0x03, 0xBB, 0x00, 0x00, 0x03, 0x91, 0x00, - 0x00, 0x03, 0xBC, 0x00, 0x00, 0x03, 0x94, 0x00, - 0x00, 0x03, 0xB1, 0x01, 0x00, 0x00, 0x01, 0x80, - ]; - - let mut stream = Dstream::new(&data); - - assert_eq!( - u8::deserialise(&mut stream).unwrap(), - 0x00, - ); - assert_eq!( - u8::deserialise(&mut stream).unwrap(), - 0xFF, - ); - - assert_eq!( - u128::deserialise(&mut stream).unwrap(), - 0xFF_0F_EF_1F_DF_2F_CF_3F_BF_4F_AF_5F_9F_6F_8F_7F, - ); - - assert_eq!( - FixedString::<0x10>::deserialise(&mut stream).unwrap(), - "m\u{00E1}na\u{00F0}ur", - ); - - assert_eq!( - <[char; 0x5]>::deserialise(&mut stream).unwrap(), - ['\u{03BB}', '\u{0391}', '\u{03BC}', '\u{0394}', '\u{03B1}'], - ); - - assert_eq!( - Option::<()>::deserialise(&mut stream).unwrap(), - Some(()), - ); - - assert_eq!( - Option::<()>::deserialise(&mut stream).unwrap(), - None, - ); - - assert_eq!( - Result::<(), i8>::deserialise(&mut stream).unwrap(), - Ok(()), - ); - - assert_eq!( - Result::<(), i8>::deserialise(&mut stream).unwrap(), - Err(i8::MIN), - ); -} diff --git a/src/dstream/mod.rs b/src/dstream/mod.rs deleted file mode 100644 index ca7f619..0000000 --- a/src/dstream/mod.rs +++ /dev/null @@ -1,86 +0,0 @@ -// 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::{Error, Result}; - -use core::fmt::{Debug, Formatter}; - -/// Byte stream for deserialisation. -/// -/// This type borrows a byte slice (hence [`new`](Dstream::new)), keeping track internally of the used bytes. -#[derive(Clone)] -pub struct Dstream<'a> { - data: &'a [u8], - len: usize, -} - -impl<'a> Dstream<'a> { - /// Constructs a new byte stream. - #[inline(always)] - #[must_use] - pub fn new<T: AsRef<[u8]> + ?Sized>(buf: &'a T) -> Self { Self { - data: buf.as_ref(), - len: buf.as_ref().len(), - } } - - /// Takes bytes from the stream. - /// - /// # Errors - /// - /// If the internal buffer doesn't hold at least the requested amount of bytes, an [`EndOfStream`](Error::EndOfStream) error is returned. - pub fn take(&mut self, req: usize) -> Result<&[u8]> { - let rem = self.len; - - if rem < req { return Err(Error::EndOfStream { req, rem } ) } - - let start = self.data.len() - rem; - let stop = start + req; - - self.len -= req; - Ok(&self.data[start..stop]) - } - - /// Takes a single byte from the stream. - /// - /// # Errors - /// - /// If the internal buffer doesn't hold at least the requested amount of bytes, an [`EndOfStream`](Error::EndOfStream) error is returned. - pub fn take_byte(&mut self) -> Result<u8> { - const LEN: usize = 0x1; - - if self.len < LEN { return Err(Error::EndOfStream { req: LEN, rem: self.len } ) } - - self.len -= LEN; - - let index = self.data.len() - self.len; - Ok(self.data[index]) - } -} - -impl Debug for Dstream<'_> { - fn fmt(&self, f: &mut Formatter) -> core::fmt::Result { - self.data.fmt(f) - } -} - -impl<'a, T: AsRef<[u8]>> From<&'a T> for Dstream<'a> { - fn from(value: &'a T) -> Self { Self::new(value) } -} diff --git a/src/error/mod.rs b/src/error/mod.rs deleted file mode 100644 index 30e4c1e..0000000 --- a/src/error/mod.rs +++ /dev/null @@ -1,112 +0,0 @@ -// 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 core::error::Error as StdError; -use core::fmt::{Display, Formatter}; -use core::str::Utf8Error; - -/// Mapping of [`core::result::Result`]. -pub type Result<T> = core::result::Result<T, Error>; - -/// Denotes an error. -/// -/// These variants are used when deserialisation fails. -/// Serialisations are assumed infallible. -#[derive(Debug)] -pub enum Error { - /// An array could not hold the requested amount of elements. - ArrayTooShort { req: usize, len: usize }, - - /// A string encountered an invalid UTF-8 sequence. - BadString { source: Utf8Error }, - - /// Bytes were requested on an empty stream. - EndOfStream { req: usize, rem: usize }, - - /// A boolean encountered a value outside (0) and (1). - InvalidBoolean { value: u8 }, - - /// An invalid code point was encountered. - /// - /// This includes surrogate points in the inclusive range `U+D800` to `U+DFFF`, as well as values larger than `U+10FFFF`. - InvalidCodePoint { value: u32 }, - - /// An `isize` value couldn't fit into (16) bits. - IsizeOutOfRange { value: isize }, - - /// A non-zero integer encountered the value (0). - NullInteger, - - /// A `usize` value couldn't fit into (16) bits. - UsizeOutOfRange { value: usize }, -} - -impl Display for Error { - fn fmt(&self, f: &mut Formatter) -> core::fmt::Result { - use Error::*; - - match *self { - ArrayTooShort { req, len } => { - write!(f, "array of ({len}) element(s) cannot hold ({req})") - }, - - BadString { ref source } =>{ - write!(f, "unable to parse utf8: \"{source}\"") - }, - - EndOfStream { req, rem } => { - write!(f, "({req}) byte(s) were requested but only ({rem}) byte(s) were left") - }, - - InvalidBoolean { value } => { - write!(f, "expected boolean but got {value:#02X}") - }, - - InvalidCodePoint { value } => { - write!(f, "code point U+{value:04X} is not valid") - }, - - IsizeOutOfRange { value } => { - write!(f, "signed size value ({value}) cannot be serialised: must be in the range ({}) to ({})", i16::MIN, i16::MAX) - }, - - NullInteger => { - write!(f, "expected non-zero integer but got (0)") - }, - - UsizeOutOfRange { value } => { - write!(f, "unsigned size value ({value}) cannot be serialised: must be at most ({})", u16::MAX) - }, - } - } -} - -impl StdError for Error { - fn source(&self) -> Option<&(dyn StdError + 'static)> { - use Error::*; - - match *self { - BadString { ref source } => Some(source), - - _ => None, - } - } -} diff --git a/src/fixed_string/mod.rs b/src/fixed_string/mod.rs deleted file mode 100644 index b0342d3..0000000 --- a/src/fixed_string/mod.rs +++ /dev/null @@ -1,298 +0,0 @@ -// 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::{ - Deserialise, - Dstream, - Error, - FixedStringIter, - Serialise, - Sstream, -}; - -use alloc::string::String; -use core::cmp::Ordering; -use core::fmt::{Debug, Display, Formatter}; -use core::ops::{Index, IndexMut}; -use core::str::FromStr; - -/// Owned string with maximum size. -/// -/// This is in contrast to [String], which has no size limit is practice, and [str], which is unsized. -#[derive(Clone)] -pub struct FixedString<const N: usize> { - buf: [char; N], - len: usize, -} - -impl<const N: usize> FixedString<N> { - /// Constructs a new fixed string. - /// - /// The contents of the provided string are copied into the internal buffer. - /// All residual characters are instanced as U+0000 `NULL`. - /// - /// # Errors - /// - /// If the given string `s` cannot fit into `N` characters, an [`ArrayTooShort`](Error::ArrayTooShort) error is returned. - pub fn new(s: &str) -> Result<Self, Error> { - let mut buf = ['\0'; N]; - let len = s.chars().count(); - - for (i, c) in s.chars().enumerate() { - if i >= N { return Err(Error::ArrayTooShort { req: len, len: N }) } - - buf[i] = c; - } - - Ok(Self { buf, len }) - } - - /// Returns the length of the string. - /// - /// This does not necessarily equal the value of `N`, as the internal buffer is not required to be used fully. - #[inline(always)] - #[must_use] - pub const fn len(&self) -> usize { self.len } - - /// Checks if the string is empty, i.e. `self.len() == 0x0`. - #[inline(always)] - #[must_use] - pub const fn is_empty(&self) -> bool { self.len == 0x0 } - - /// Borrows the character at the specified index. - /// - /// If no element exists at that position, [`None`] is returned instead. - #[inline] - #[must_use] - pub const fn get(&self, index: usize) -> Option<&char> { - if index >= self.len { - None - } else { - Some(&self.buf[index]) - } - } - - /// Mutably borrows the character at the specified index. - /// - /// If no element exists at that position, [`None`] is returned instead. - #[inline] - #[must_use] - pub fn get_mut(&mut self, index: usize) -> Option<&mut char> { - if index >= self.len { - None - } else { - Some(&mut self.buf[index]) - } - } - - /// Returns an iterator to the contained characters. - #[inline(always)] - pub fn iter(&self) -> core::slice::Iter<'_, char> { self.buf[0x0..self.len].iter() } - - /// Returns a mutable iterator to the contained characters. - #[inline(always)] - pub fn iter_mut(&mut self) -> core::slice::IterMut<'_, char> { self.buf[0x0..self.len].iter_mut() } -} - -impl<const N: usize> Debug for FixedString<N> { - fn fmt(&self, f: &mut Formatter) -> core::fmt::Result { - write!(f, "\"")?; - for c in self { write!(f, "{}", c.escape_debug())? } - write!(f, "\"")?; - - Ok(()) - } -} - -impl<const N: usize> Deserialise for FixedString<N> { - type Error = Error; - - fn deserialise(stream: &mut Dstream) -> Result<Self, Self::Error> { - let len = usize::deserialise(stream)?; - let data = stream.take(len)?; - - let s = core::str::from_utf8(data) - .map_err(|e| Error::BadString { source: e })?; - - let len = s.chars().count(); - - if len > N { - return Err(Error::ArrayTooShort { req: len, len: N }); - } - - let mut buf = ['\0'; N]; - for (i, c) in s.chars().enumerate() { - buf[i] = c; - } - - Ok(Self { buf, len }) - } -} - -impl<const N: usize> Default for FixedString<N> { - #[inline(always)] - fn default() -> Self { Self { - buf: ['\0'; N], - len: 0x0, - } } -} - -impl<const N: usize> Display for FixedString<N> { - fn fmt(&self, f: &mut Formatter) -> core::fmt::Result { - for c in self { write!(f, "{c}")? } - - Ok(()) - } -} - -impl<const N: usize> Eq for FixedString<N> { } - -impl<const N: usize> From<[char; N]> for FixedString<N> { - fn from(value: [char; N]) -> Self { Self { - buf: value, - len: N, - } } -} - -impl<const N: usize> FromStr for FixedString<N> { - type Err = Error; - - fn from_str(s: &str) -> Result<Self, Error> { Self::new(s) } -} - -impl<const N: usize> Index<usize> for FixedString<N> { - type Output = char; - - fn index(&self, index: usize) -> &Self::Output { self.get(index).unwrap() } -} - -impl<const N: usize> IndexMut<usize> for FixedString<N> { - fn index_mut(&mut self, index: usize) -> &mut Self::Output { self.get_mut(index).unwrap() } -} - -impl<const N: usize> IntoIterator for FixedString<N> { - type Item = char; - - type IntoIter = FixedStringIter<N>; - - fn into_iter(self) -> Self::IntoIter { - FixedStringIter { - buf: self.buf, - len: self.len, - - pos: Some(0x0), - } - } -} - -impl<'a, const N: usize> IntoIterator for &'a FixedString<N> { - type Item = &'a char; - - type IntoIter = core::slice::Iter<'a, char>; - - fn into_iter(self) -> Self::IntoIter { self.iter() } -} - -impl<'a, const N: usize> IntoIterator for &'a mut FixedString<N> { - type Item = &'a mut char; - - type IntoIter = core::slice::IterMut<'a, char>; - - fn into_iter(self) -> Self::IntoIter { self.iter_mut() } -} - -impl<const N: usize> Ord for FixedString<N> { - fn cmp(&self, other: &Self) -> Ordering { self.partial_cmp(other).unwrap() } -} - -impl<const N: usize, const M: usize> PartialEq<FixedString<M>> for FixedString<N> { - fn eq(&self, other: &FixedString<M>) -> bool { - if self.len() != other.len() { return false }; - - for i in 0x0..self.len() { - if self.buf[i] != other.buf[i] { return false }; - } - - true - } -} - -impl<const N: usize> PartialEq<&str> for FixedString<N> { - fn eq(&self, other: &&str) -> bool { - for (i, c) in other.chars().enumerate() { - if self.buf.get(i) != Some(&c) { return false }; - } - - true - } -} - -impl<const N: usize, const M: usize> PartialOrd<FixedString<M>> for FixedString<N> { - fn partial_cmp(&self, other: &FixedString<M>) -> Option<Ordering> { - let len = self.len().max(other.len()); - - for i in 0x0..len { - let lc = self.get(i); - let rc = other.get(i); - - match (lc, rc) { - (None, None) => return Some(Ordering::Equal), - (Some(_), None) => return Some(Ordering::Greater), - (None, Some(_)) => return Some(Ordering::Less), - - (Some(lc), Some(rc)) => { - let ordering = lc.cmp(rc); - - if ordering != Ordering::Equal { return Some(ordering) }; - } - } - } - - Some(Ordering::Equal) - } -} - -impl<const N: usize> Serialise for FixedString<N> { - type Error = Error; - - const SERIALISE_LIMIT: usize = N * 0x4; - - fn serialise(&self, stream: &mut Sstream) -> Result<usize, Self::Error> { - let mut count = 0x0; - - let s: String = self.iter().collect(); - - count += s.len().serialise(stream)?; - count += stream.add(&s.into_bytes())?; - - Ok(count) - } -} - -impl<const N: usize> TryFrom<&str> for FixedString<N> { - type Error = Error; - - #[inline(always)] - fn try_from(value: &str) -> Result<Self, Self::Error> { Self::new(value) } -} diff --git a/src/fixed_string/test.rs b/src/fixed_string/test.rs deleted file mode 100644 index 1599efc..0000000 --- a/src/fixed_string/test.rs +++ /dev/null @@ -1,43 +0,0 @@ -// 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::FixedString; - -use core::cmp::Ordering; - -#[test] -fn test_fixed_string() { - let str0 = FixedString::<0xC>::new("Hello there!").unwrap(); - let str1 = FixedString::<0xE>::new("MEIN_GRO\u{1E9E}_GOTT").unwrap(); - let str2 = FixedString::<0x5>::new("Hello").unwrap(); - - assert_eq!(str0.partial_cmp(&str0), Some(Ordering::Equal)); - assert_eq!(str0.partial_cmp(&str1), Some(Ordering::Less)); - assert_eq!(str0.partial_cmp(&str2), Some(Ordering::Greater)); - - assert_eq!(str1.partial_cmp(&str0), Some(Ordering::Greater)); - assert_eq!(str1.partial_cmp(&str1), Some(Ordering::Equal)); - assert_eq!(str1.partial_cmp(&str2), Some(Ordering::Greater)); - - assert_eq!(str2.partial_cmp(&str0), Some(Ordering::Less)); - assert_eq!(str2.partial_cmp(&str1), Some(Ordering::Less)); - assert_eq!(str2.partial_cmp(&str2), Some(Ordering::Equal)); -} diff --git a/src/fixed_string_iter/mod.rs b/src/fixed_string_iter/mod.rs deleted file mode 100644 index 088f61f..0000000 --- a/src/fixed_string_iter/mod.rs +++ /dev/null @@ -1,43 +0,0 @@ -// 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/>. - -/// Iterator to a fixed string. -pub struct FixedStringIter<const N: usize> { - pub(in crate) buf: [char; N], - pub(in crate) len: usize, - - pub(in crate) pos: Option<usize>, -} - -impl<const N: usize> Iterator for FixedStringIter<N> { - type Item = char; - - fn next(&mut self) -> Option<Self::Item> { - let pos = self.pos.as_mut()?; - - if *pos >= self.len { return None }; - - let item = self.buf[*pos]; - *pos += 0x1; - - Some(item) - } -} diff --git a/src/lib.rs b/src/lib.rs deleted file mode 100644 index 4355f75..0000000 --- a/src/lib.rs +++ /dev/null @@ -1,123 +0,0 @@ -// 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/>. - -#![doc(html_logo_url = "https://gitlab.com/bjoernager/bzipper/-/raw/master/doc-icon.svg?ref_type=heads")] - -//! Binary (de)serialisation. -//! -//! Contrary to [Serde](https://crates.io/crates/serde/)/[Bincode](https://crates.io/crates/bincode/), the goal of `bzipper` is to serialise with a known size constraint. -//! Therefore, this crate may be more suited for networking or other cases where a fixed-sized buffer is needed. -//! -//! Keep in mind that this project is still work-in-progress. -//! -//! This crate does not require any dependencies at the moment. -//! It is also compatible with `no_std`. -//! -//! # Data model -//! -//! Most primitive types serialise losslessly, with the exception being [`usize`] and [`isize`]. -//! These serialise as [`u16`] and [`i16`], respectively, for portability reasons. -//! -//! Unsized types, such as [`str`] and [slices](slice), are not supported. -//! Instead, [arrays](array) should be used. -//! For strings, the [`FixedString`] type is also provided. -//! -//! # Usage -//! -//! This crate revolves around the [`Serialise`] and [`Deserialise`] traits, both of which work around streams (more specifically, [d-streams](Dstream) and [s-streams](Sstream)). -//! -//! Many core types come implemented with `bzipper`, including primitives as well as some standard library types such as [`Option`] and [`Result`](core::result::Result). -//! -//! ## Serialisation -//! -//! To serialise an object implementing `Serialise`, simply allocate a so-called "s-stream" (short for *serialisation stream*) with the [`Sstream`] type: -//! -//! ``` -//! let mut buf: [u8; 16] = Default::default(); -//! -//! let mut stream = bzipper::Sstream::new(&mut buf); -//! ``` -//! -//! The resulting stream is immutable in the sense that it cannot grow its buffer, altough it does keep track of the buffer's state. -//! -//! A byte sequence can be added to our new stream by passing the stream to a call to the [`serialise`](Serialise::serialise) method: -//! -//! ``` -//! use bzipper::Serialise; -//! -//! let mut buf: [u8; 2] = Default::default(); -//! let mut stream = bzipper::Sstream::new(&mut buf); -//! -//! 0x4554_u16.serialise(&mut stream).unwrap(); -//! ``` -//! -//! The ammount of bytes used by the serialiser (that is, the ammount of bytes written to the stream) is indicated by its return value (i.e. it has the type `Result<usize, Serialise::Error>`). -//! -//! Whilst the *maximum* ammount of bytes is specified by the [`SERIALISE_LIMIT`](Serialise::SERIALISE_LIMIT) constant, this can in cases be lower (for example with [`None`] variants which are always encoded as a single, null byte). -//! -//! When serialising primitives, the resulting byte stream is in big endian (a.k.a. network endian). -//! It is recommended for implementors to adhere to this convention as well. -//! -//! After serialisation, the s-stream records the new write-to position of the buffer. This allows for *chaining* of serialisations, which can prove useful when implementing the trait for custom types. -//! -//! ## Deserialisation -//! -//! As with serialisation, deserialisation uses streams (just with the [`Dstream`] type; short for *deserialisation stream*): -//! -//! ``` -//! let data = [0x45, 0x54]; -//! -//! let mut stream = bzipper::Dstream::new(&data); -//! ``` -//! -//! Using these streams is also just as simple as with s-streams: -//! -//! ``` -//! use bzipper::Deserialise; -//! -//! let data = [0x45, 0x54]; -//! let mut stream = bzipper::Dstream::new(&data); -//! -//! assert_eq!(u16::deserialise(&mut stream).unwrap(), 0x4554); -//! ``` -//! -//! When chaining serialisations, keep in mind that appropriate deserialisations should come in **reverse order** (streams function similarly to stacks in this sense). - -#![no_std] - -extern crate alloc; - -macro_rules! use_mod { - ($vis:vis $name:ident) => { - mod $name; - $vis use $name::*; - }; -} -pub(in crate) use use_mod; - -use_mod!(pub buffer); -use_mod!(pub deserialise); -use_mod!(pub dstream); -use_mod!(pub error); -use_mod!(pub fixed_string); -use_mod!(pub fixed_string_iter); -use_mod!(pub serialise); -use_mod!(pub sstream); diff --git a/src/serialise/mod.rs b/src/serialise/mod.rs deleted file mode 100644 index 16c8313..0000000 --- a/src/serialise/mod.rs +++ /dev/null @@ -1,676 +0,0 @@ -// 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, Sstream}; - -use alloc::boxed::Box; -use core::convert::Infallible; -use core::error::Error as StdError; -use core::mem::size_of; -use core::num::NonZero; - -/// Types capable of being serialised. -pub trait Serialise: Sized { - /// The error of serialisation. - /// - /// Use [`Infallible`] if **all** deserialisations are infallible, as is the case of zero-length types (such as [the unit type](unit)). - type Error; - - /// The maximum amount of bytes that can result from serialisation. - /// - /// Until derive macros are implemented, this value should be set to the sum of the members' own size limits (if chaining is used, that is): - /// - /// ``` - /// use bzipper::{Serialise, Sstream}; - /// - /// struct Foo { - /// bar: u16, - /// baz: f32, - /// } - /// - /// impl Serialise for Foo { - /// type Error = bzipper::Error; - /// - /// const SERIALISE_LIMIT: usize = u16::SERIALISE_LIMIT + f32::SERIALISE_LIMIT; - /// - /// fn serialise(&self, stream: &mut Sstream) -> Result<usize, Self::Error> { - /// let mut count = 0x0; - /// - /// // Serialise fields using chaining. - /// count += self.bar.serialise(stream)?; - /// count += self.baz.serialise(stream)?; - /// - /// Ok(count) - /// } - /// } - /// ``` - /// - /// In the future, dervice macros will make manual chaining redundant. - const SERIALISE_LIMIT: usize; - - /// Serialises `self` into a byte stream. - /// - /// The number of bytes written is returned. - /// This should **not** exceed [`SERIALISE_LIMIT`](Serialise::SERIALISE_LIMIT), and doing so is considered a logic error. - fn serialise(&self, stream: &mut Sstream) -> Result<usize, Self::Error>; -} - -macro_rules! impl_float { - ($type:ty) => { - impl Serialise for $type { - type Error = Error; - - const SERIALISE_LIMIT: usize = size_of::<$type>(); - - fn serialise(&self, stream: &mut Sstream) -> Result<usize, Self::Error> { - let data = self.to_be_bytes(); - stream.add(&data)?; - - Ok(data.len()) - } - } - }; -} - -macro_rules! impl_int { - ($type:ty) => { - impl Serialise for $type { - type Error = Error; - - const SERIALISE_LIMIT: usize = size_of::<$type>(); - - fn serialise(&self, stream: &mut Sstream) -> Result<usize, Self::Error> { - let data = self.to_be_bytes(); - stream.add(&data)?; - - Ok(data.len()) - } - } - }; -} - -macro_rules! impl_non_zero { - ($type:ty) => { - impl Serialise for NonZero<$type> { - type Error = <$type as Serialise>::Error; - - const SERIALISE_LIMIT: usize = size_of::<$type>(); - - fn serialise(&self, stream: &mut Sstream) -> Result<usize, Self::Error> { - self.get().serialise(stream) - } - } - }; -} - -impl<T0, T1> Serialise for (T0, T1) -where - T0: Serialise<Error: StdError + 'static>, - T1: Serialise<Error: StdError + 'static>, { - type Error = Box<dyn StdError>; - - const SERIALISE_LIMIT: usize = - T0::SERIALISE_LIMIT - + T1::SERIALISE_LIMIT; - - fn serialise(&self, stream: &mut Sstream) -> Result<usize, Self::Error> { - let mut count = 0x0; - - count += self.0.serialise(stream)?; - count += self.1.serialise(stream)?; - - Ok(count) - } -} - -impl<T0, T1, T2> Serialise for (T0, T1, T2) -where - T0: Serialise<Error: StdError + 'static>, - T1: Serialise<Error: StdError + 'static>, - T2: Serialise<Error: StdError + 'static>, { - type Error = Box<dyn StdError>; - - const SERIALISE_LIMIT: usize = - T0::SERIALISE_LIMIT - + T1::SERIALISE_LIMIT - + T2::SERIALISE_LIMIT; - - fn serialise(&self, stream: &mut Sstream) -> Result<usize, Self::Error> { - let mut count = 0x0; - - count += self.0.serialise(stream)?; - count += self.1.serialise(stream)?; - count += self.2.serialise(stream)?; - - Ok(count) - } -} - -impl<T0, T1, T2, T3> Serialise for (T0, T1, T2, T3) -where - T0: Serialise<Error: StdError + 'static>, - T1: Serialise<Error: StdError + 'static>, - T2: Serialise<Error: StdError + 'static>, - T3: Serialise<Error: StdError + 'static>, { - type Error = Box<dyn StdError>; - - const SERIALISE_LIMIT: usize = - T0::SERIALISE_LIMIT - + T1::SERIALISE_LIMIT - + T2::SERIALISE_LIMIT - + T3::SERIALISE_LIMIT; - - fn serialise(&self, stream: &mut Sstream) -> Result<usize, Self::Error> { - let mut count = 0x0; - - count += self.0.serialise(stream)?; - count += self.1.serialise(stream)?; - count += self.2.serialise(stream)?; - count += self.3.serialise(stream)?; - - Ok(count) - } -} - -impl<T0, T1, T2, T3, T4> Serialise for (T0, T1, T2, T3, T4) -where - T0: Serialise<Error: StdError + 'static>, - T1: Serialise<Error: StdError + 'static>, - T2: Serialise<Error: StdError + 'static>, - T3: Serialise<Error: StdError + 'static>, - T4: Serialise<Error: StdError + 'static>, { - type Error = Box<dyn StdError>; - - const SERIALISE_LIMIT: usize = - T0::SERIALISE_LIMIT - + T1::SERIALISE_LIMIT - + T2::SERIALISE_LIMIT - + T3::SERIALISE_LIMIT - + T4::SERIALISE_LIMIT; - - fn serialise(&self, stream: &mut Sstream) -> Result<usize, Self::Error> { - let mut count = 0x0; - - count += self.0.serialise(stream)?; - count += self.1.serialise(stream)?; - count += self.2.serialise(stream)?; - count += self.3.serialise(stream)?; - count += self.4.serialise(stream)?; - - Ok(count) - } -} - -impl<T0, T1, T2, T3, T4, T5> Serialise for (T0, T1, T2, T3, T4, T5) -where - T0: Serialise<Error: StdError + 'static>, - T1: Serialise<Error: StdError + 'static>, - T2: Serialise<Error: StdError + 'static>, - T3: Serialise<Error: StdError + 'static>, - T4: Serialise<Error: StdError + 'static>, - T5: Serialise<Error: StdError + 'static>, { - type Error = Box<dyn StdError>; - - const SERIALISE_LIMIT: usize = - T0::SERIALISE_LIMIT - + T1::SERIALISE_LIMIT - + T2::SERIALISE_LIMIT - + T3::SERIALISE_LIMIT - + T4::SERIALISE_LIMIT - + T5::SERIALISE_LIMIT; - - fn serialise(&self, stream: &mut Sstream) -> Result<usize, Self::Error> { - let mut count = 0x0; - - count += self.0.serialise(stream)?; - count += self.1.serialise(stream)?; - count += self.2.serialise(stream)?; - count += self.3.serialise(stream)?; - count += self.4.serialise(stream)?; - count += self.5.serialise(stream)?; - - Ok(count) - } -} - -impl<T0, T1, T2, T3, T4, T5, T6> Serialise for (T0, T1, T2, T3, T4, T5, T6) -where - T0: Serialise<Error: StdError + 'static>, - T1: Serialise<Error: StdError + 'static>, - T2: Serialise<Error: StdError + 'static>, - T3: Serialise<Error: StdError + 'static>, - T4: Serialise<Error: StdError + 'static>, - T5: Serialise<Error: StdError + 'static>, - T6: Serialise<Error: StdError + 'static>, { - type Error = Box<dyn StdError>; - - const SERIALISE_LIMIT: usize = - T0::SERIALISE_LIMIT - + T1::SERIALISE_LIMIT - + T2::SERIALISE_LIMIT - + T3::SERIALISE_LIMIT - + T4::SERIALISE_LIMIT - + T5::SERIALISE_LIMIT - + T6::SERIALISE_LIMIT; - - fn serialise(&self, stream: &mut Sstream) -> Result<usize, Self::Error> { - let mut count = 0x0; - - count += self.0.serialise(stream)?; - count += self.1.serialise(stream)?; - count += self.2.serialise(stream)?; - count += self.3.serialise(stream)?; - count += self.4.serialise(stream)?; - count += self.5.serialise(stream)?; - count += self.6.serialise(stream)?; - - Ok(count) - } -} - -impl<T0, T1, T2, T3, T4, T5, T6, T7> Serialise for (T0, T1, T2, T3, T4, T5, T6, T7) -where - T0: Serialise<Error: StdError + 'static>, - T1: Serialise<Error: StdError + 'static>, - T2: Serialise<Error: StdError + 'static>, - T3: Serialise<Error: StdError + 'static>, - T4: Serialise<Error: StdError + 'static>, - T5: Serialise<Error: StdError + 'static>, - T6: Serialise<Error: StdError + 'static>, - T7: Serialise<Error: StdError + 'static>, { - type Error = Box<dyn StdError>; - - const SERIALISE_LIMIT: usize = - T0::SERIALISE_LIMIT - + T1::SERIALISE_LIMIT - + T2::SERIALISE_LIMIT - + T3::SERIALISE_LIMIT - + T4::SERIALISE_LIMIT - + T5::SERIALISE_LIMIT - + T6::SERIALISE_LIMIT - + T7::SERIALISE_LIMIT; - - fn serialise(&self, stream: &mut Sstream) -> Result<usize, Self::Error> { - let mut count = 0x0; - - count += self.0.serialise(stream)?; - count += self.1.serialise(stream)?; - count += self.2.serialise(stream)?; - count += self.3.serialise(stream)?; - count += self.4.serialise(stream)?; - count += self.5.serialise(stream)?; - count += self.6.serialise(stream)?; - count += self.7.serialise(stream)?; - - Ok(count) - } -} - -impl<T0, T1, T2, T3, T4, T5, T6, T7, T8> Serialise for (T0, T1, T2, T3, T4, T5, T6, T7, T8) -where - T0: Serialise<Error: StdError + 'static>, - T1: Serialise<Error: StdError + 'static>, - T2: Serialise<Error: StdError + 'static>, - T3: Serialise<Error: StdError + 'static>, - T4: Serialise<Error: StdError + 'static>, - T5: Serialise<Error: StdError + 'static>, - T6: Serialise<Error: StdError + 'static>, - T7: Serialise<Error: StdError + 'static>, - T8: Serialise<Error: StdError + 'static>, { - type Error = Box<dyn StdError>; - - const SERIALISE_LIMIT: usize = - T0::SERIALISE_LIMIT - + T1::SERIALISE_LIMIT - + T2::SERIALISE_LIMIT - + T3::SERIALISE_LIMIT - + T4::SERIALISE_LIMIT - + T5::SERIALISE_LIMIT - + T6::SERIALISE_LIMIT - + T7::SERIALISE_LIMIT - + T8::SERIALISE_LIMIT; - - fn serialise(&self, stream: &mut Sstream) -> Result<usize, Self::Error> { - let mut count = 0x0; - - count += self.0.serialise(stream)?; - count += self.1.serialise(stream)?; - count += self.2.serialise(stream)?; - count += self.3.serialise(stream)?; - count += self.4.serialise(stream)?; - count += self.5.serialise(stream)?; - count += self.6.serialise(stream)?; - count += self.7.serialise(stream)?; - count += self.8.serialise(stream)?; - - Ok(count) - } -} - -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<Error: StdError + 'static>, - T1: Serialise<Error: StdError + 'static>, - T2: Serialise<Error: StdError + 'static>, - T3: Serialise<Error: StdError + 'static>, - T4: Serialise<Error: StdError + 'static>, - T5: Serialise<Error: StdError + 'static>, - T6: Serialise<Error: StdError + 'static>, - T7: Serialise<Error: StdError + 'static>, - T8: Serialise<Error: StdError + 'static>, - T9: Serialise<Error: StdError + 'static>, { - type Error = Box<dyn StdError>; - - const SERIALISE_LIMIT: usize = - T0::SERIALISE_LIMIT - + T1::SERIALISE_LIMIT - + T2::SERIALISE_LIMIT - + T3::SERIALISE_LIMIT - + T4::SERIALISE_LIMIT - + T5::SERIALISE_LIMIT - + T6::SERIALISE_LIMIT - + T7::SERIALISE_LIMIT - + T8::SERIALISE_LIMIT - + T9::SERIALISE_LIMIT; - - fn serialise(&self, stream: &mut Sstream) -> Result<usize, Self::Error> { - let mut count = 0x0; - - count += self.0.serialise(stream)?; - count += self.1.serialise(stream)?; - count += self.2.serialise(stream)?; - count += self.3.serialise(stream)?; - count += self.4.serialise(stream)?; - count += self.5.serialise(stream)?; - count += self.6.serialise(stream)?; - count += self.7.serialise(stream)?; - count += self.8.serialise(stream)?; - count += self.9.serialise(stream)?; - - Ok(count) - } -} - -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<Error: StdError + 'static>, - T1: Serialise<Error: StdError + 'static>, - T2: Serialise<Error: StdError + 'static>, - T3: Serialise<Error: StdError + 'static>, - T4: Serialise<Error: StdError + 'static>, - T5: Serialise<Error: StdError + 'static>, - T6: Serialise<Error: StdError + 'static>, - T7: Serialise<Error: StdError + 'static>, - T8: Serialise<Error: StdError + 'static>, - T9: Serialise<Error: StdError + 'static>, - T10: Serialise<Error: StdError + 'static>, { - type Error = Box<dyn StdError>; - - const SERIALISE_LIMIT: usize = - T0::SERIALISE_LIMIT - + T1::SERIALISE_LIMIT - + T2::SERIALISE_LIMIT - + T3::SERIALISE_LIMIT - + T4::SERIALISE_LIMIT - + T5::SERIALISE_LIMIT - + T6::SERIALISE_LIMIT - + T7::SERIALISE_LIMIT - + T8::SERIALISE_LIMIT - + T9::SERIALISE_LIMIT - + T10::SERIALISE_LIMIT; - - fn serialise(&self, stream: &mut Sstream) -> Result<usize, Self::Error> { - let mut count = 0x0; - - count += self.0.serialise(stream)?; - count += self.1.serialise(stream)?; - count += self.2.serialise(stream)?; - count += self.3.serialise(stream)?; - count += self.4.serialise(stream)?; - count += self.5.serialise(stream)?; - count += self.6.serialise(stream)?; - count += self.7.serialise(stream)?; - count += self.8.serialise(stream)?; - count += self.9.serialise(stream)?; - count += self.10.serialise(stream)?; - - Ok(count) - } -} - -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<Error: StdError + 'static>, - T1: Serialise<Error: StdError + 'static>, - T2: Serialise<Error: StdError + 'static>, - T3: Serialise<Error: StdError + 'static>, - T4: Serialise<Error: StdError + 'static>, - T5: Serialise<Error: StdError + 'static>, - T6: Serialise<Error: StdError + 'static>, - T7: Serialise<Error: StdError + 'static>, - T8: Serialise<Error: StdError + 'static>, - T9: Serialise<Error: StdError + 'static>, - T10: Serialise<Error: StdError + 'static>, - T11: Serialise<Error: StdError + 'static>, { - type Error = Box<dyn StdError>; - - const SERIALISE_LIMIT: usize = - T0::SERIALISE_LIMIT - + T1::SERIALISE_LIMIT - + T2::SERIALISE_LIMIT - + T3::SERIALISE_LIMIT - + T4::SERIALISE_LIMIT - + T5::SERIALISE_LIMIT - + T6::SERIALISE_LIMIT - + T7::SERIALISE_LIMIT - + T8::SERIALISE_LIMIT - + T9::SERIALISE_LIMIT - + T10::SERIALISE_LIMIT - + T11::SERIALISE_LIMIT; - - fn serialise(&self, stream: &mut Sstream) -> Result<usize, Self::Error> { - let mut count = 0x0; - - count += self.0.serialise(stream)?; - count += self.1.serialise(stream)?; - count += self.2.serialise(stream)?; - count += self.3.serialise(stream)?; - count += self.4.serialise(stream)?; - count += self.5.serialise(stream)?; - count += self.6.serialise(stream)?; - count += self.7.serialise(stream)?; - count += self.8.serialise(stream)?; - count += self.9.serialise(stream)?; - count += self.10.serialise(stream)?; - count += self.11.serialise(stream)?; - - Ok(count) - } -} - -impl<T: Serialise<Error: StdError + 'static>, const N: usize> Serialise for [T; N] { - type Error = Box<dyn StdError>; - - const SERIALISE_LIMIT: usize = T::SERIALISE_LIMIT * N; - - fn serialise(&self, stream: &mut Sstream) -> Result<usize, Self::Error> { - let mut count = 0x0; - - self.len().serialise(stream)?; - for v in self { count += v.serialise(stream)? } - - Ok(count) - } -} - -impl Serialise for () { - type Error = Infallible; - - const SERIALISE_LIMIT: usize = size_of::<Self>(); - - #[inline(always)] - fn serialise(&self, mut _stream: &mut Sstream) -> Result<usize, Self::Error> { - Ok(Self::SERIALISE_LIMIT) - } -} - -impl Serialise for bool { - type Error = Error; - - const SERIALISE_LIMIT: usize = size_of::<Self>(); - - fn serialise(&self, stream: &mut Sstream) -> Result<usize, Self::Error> { - u8::from(*self).serialise(stream) - } -} - -impl Serialise for char { - type Error = Error; - - const SERIALISE_LIMIT: usize = size_of::<Self>(); - - fn serialise(&self, stream: &mut Sstream) -> Result<usize, Self::Error> { - u32::from(*self).serialise(stream) - } -} - -// Especially useful for `Result<T, Infallible>`. -impl Serialise for Infallible { - type Error = Self; - - const SERIALISE_LIMIT: usize = size_of::<Self>(); - - fn serialise(&self, mut _stream: &mut Sstream) -> Result<usize, Self::Error> { unreachable!() } -} - -impl Serialise for isize { - type Error = Error; - - const SERIALISE_LIMIT: usize = size_of::<i16>(); - - fn serialise(&self, stream: &mut Sstream) -> Result<usize, Self::Error> { - let value = i16::try_from(*self) - .map_err(|_| Error::IsizeOutOfRange { value: *self })?; - - value.serialise(stream) - } -} - -impl<T: Serialise<Error: StdError + 'static>> Serialise for Option<T> { - type Error = Box<dyn StdError>; - - const SERIALISE_LIMIT: usize = T::SERIALISE_LIMIT + 0x1; - - fn serialise(&self, stream: &mut Sstream) -> Result<usize, Self::Error> { - let mut count = 0x0; - - match *self { - None => { - count += false.serialise(stream)?; - // No need to zero-fill. - }, - - Some(ref v) => { - count += true.serialise(stream)?; - count += v.serialise(stream)?; - }, - }; - - Ok(count) - } -} - -impl<T, E> Serialise for core::result::Result<T, E> -where - T: Serialise<Error: StdError + 'static>, - E: Serialise<Error: StdError + 'static>, { - type Error = Box<dyn StdError>; - - const SERIALISE_LIMIT: usize = const { - if size_of::<T>() > size_of::<T>() { - size_of::<T>() - } else { - size_of::<E>() - } - }; - - fn serialise(&self, stream: &mut Sstream) -> Result<usize, Self::Error> { - // Remember the descriminant. - let mut count = 0x0; - - match *self { - Ok(ref v) => { - count += false.serialise(stream)?; - count += v.serialise(stream)?; - }, - - Err(ref e) => { - count += true.serialise(stream)?; - count += e.serialise(stream)?; - }, - }; - - Ok(count) - } -} - -impl Serialise for usize { - type Error = Error; - - const SERIALISE_LIMIT: Self = size_of::<u16>(); - - fn serialise(&self, stream: &mut Sstream) -> Result<usize, Self::Error> { - let value = u16::try_from(*self) - .map_err(|_| Error::UsizeOutOfRange { value: *self })?; - - value.serialise(stream) - } -} - -impl_float!(f32); -impl_float!(f64); - -impl_int!(i128); -impl_int!(i16); -impl_int!(i32); -impl_int!(i64); -impl_int!(i8); -impl_int!(u128); -impl_int!(u16); -impl_int!(u32); -impl_int!(u64); -impl_int!(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/src/serialise/test.rs b/src/serialise/test.rs deleted file mode 100644 index 43f2b9f..0000000 --- a/src/serialise/test.rs +++ /dev/null @@ -1,72 +0,0 @@ -// 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::{FixedString, Serialise, Sstream}; - -use alloc::boxed::Box; -use alloc::vec; - -#[test] -fn test_serialise() { - let mut buf = vec![0x00; 0x50]; - let mut stream = Sstream::new(&mut buf); - - 0x00_u8.serialise(&mut stream).unwrap(); - 0xFF_u8.serialise(&mut stream).unwrap(); - 0x7F_u8.serialise(&mut stream).unwrap(); - - 0x0F_7E_u16.serialise(&mut stream).unwrap(); - - 0x00_2F_87_E7_u32.serialise(&mut stream).unwrap(); - - 0xF3_37_CF_8B_DB_03_2B_39_u64.serialise(&mut stream).unwrap(); - - 0x45_A0_15_6A_36_77_17_8A_83_2E_3C_2C_84_10_58_1A_u128.serialise(&mut stream).unwrap(); - - FixedString::<0x1>::new("A").unwrap().serialise(&mut stream).unwrap(); - FixedString::<0x8>::new("l\u{00F8}gma\u{00F0}ur").unwrap().serialise(&mut stream).unwrap(); - - ['\u{03B4}', '\u{0190}', '\u{03BB}', '\u{03A4}', '\u{03B1}'].serialise(&mut stream).unwrap(); - - Ok::<u16, char>(0x45_45).serialise(&mut stream).unwrap(); - Err::<u16, char>(char::REPLACEMENT_CHARACTER).serialise(&mut stream).unwrap(); - - None::<()>.serialise(&mut stream).unwrap(); - Some::<()>(()).serialise(&mut stream).unwrap(); - - let data: Box<[u8]> = buf.into(); - - assert_eq!( - data.as_ref(), - [ - 0x00, 0xFF, 0x7F, 0x0F, 0x7E, 0x00, 0x2F, 0x87, - 0xE7, 0xF3, 0x37, 0xCF, 0x8B, 0xDB, 0x03, 0x2B, - 0x39, 0x45, 0xA0, 0x15, 0x6A, 0x36, 0x77, 0x17, - 0x8A, 0x83, 0x2E, 0x3C, 0x2C, 0x84, 0x10, 0x58, - 0x1A, 0x00, 0x01, 0x41, 0x00, 0x0A, 0x6C, 0xC3, - 0xB8, 0x67, 0x6D, 0x61, 0xC3, 0xB0, 0x75, 0x72, - 0x00, 0x05, 0x00, 0x00, 0x03, 0xB4, 0x00, 0x00, - 0x01, 0x90, 0x00, 0x00, 0x03, 0xBB, 0x00, 0x00, - 0x03, 0xA4, 0x00, 0x00, 0x03, 0xB1, 0x00, 0x45, - 0x45, 0x01, 0x00, 0x00, 0xFF, 0xFD, 0x00, 0x01, - ], - ); -}
\ No newline at end of file diff --git a/src/sstream/mod.rs b/src/sstream/mod.rs deleted file mode 100644 index 83536d0..0000000 --- a/src/sstream/mod.rs +++ /dev/null @@ -1,103 +0,0 @@ -// 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::{Error, Result}; - -use core::fmt::{Debug, Formatter}; - -/// Byte stream for serialisation. -/// -/// This type borrows a byte slice (hence [`new`](Sstream::new)), keeping track internally of the used bytes. -#[derive(Eq, PartialEq)] -pub struct Sstream<'a> { - data: &'a mut [u8], - len: usize -} - -impl<'a> Sstream<'a> { - /// Constructs a new byte stream. - /// - /// If the borrowed slice already contains data, this may overwritten by subsequent serialisations. - #[inline(always)] - #[must_use] - pub fn new(data: &'a mut [u8]) -> Self { Self { data, len: 0x0 } } - - /// Extends the byte stream. - /// - /// # Errors - /// - /// If the stream cannot hold the requested bytes, an [`EndOfStream`](Error::EndOfStream) instance is returned. - pub fn add(&mut self, extra: &[u8]) -> Result<usize> { - let rem = self.data.len() - self.len; - let req = extra.len(); - - if rem.checked_sub(req).is_none() { - return Err(Error::EndOfStream { req, rem }); - } - - let start = self.len; - let stop = self.len + req; - - self.len += req; - self.data[start..stop].copy_from_slice(extra); - - Ok(req) - } - - /// Extends the byte stream by a single byte. - /// - /// # Errors - /// - /// If the stream cannot hold the byte, an [`EndOfStream`](Error::EndOfStream) instance is returned. - pub fn add_byte(&mut self, extra: u8) -> Result<usize> { - self.add(&[extra]) - } - - /// Yields the length of the stream. - /// - /// That is, the amount of bytes written so far. - #[inline(always)] - #[must_use] - pub const fn len(&self) -> usize { self.len } - - /// Tests if the stream is empty. - #[inline(always)] - #[must_use] - pub const fn is_empty(&self) -> bool { self.len == 0x0 } - - /// Returns a slice to the stream contents. - /// - /// This includes all previously written bytes. - #[inline(always)] - #[must_use] - pub fn as_slice(&self) -> &[u8] { &self.data[0x0..self.len] } -} - -impl AsRef<[u8]> for Sstream<'_> { - #[inline(always)] - fn as_ref(&self) -> &[u8] { self.as_slice() } -} - -impl Debug for Sstream<'_> { - fn fmt(&self, f: &mut Formatter) -> core::fmt::Result { - self.data.fmt(f) - } -} |