diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/deserialise/mod.rs | 57 | ||||
-rw-r--r-- | src/deserialise/test.rs | 4 | ||||
-rw-r--r-- | src/dstream/mod.rs (renamed from src/d_stream/mod.rs) | 40 | ||||
-rw-r--r-- | src/error/mod.rs | 38 | ||||
-rw-r--r-- | src/fixed_string/mod.rs | 18 | ||||
-rw-r--r-- | src/lib.rs | 8 | ||||
-rw-r--r-- | src/serialise/mod.rs | 186 | ||||
-rw-r--r-- | src/serialise/test.rs | 25 | ||||
-rw-r--r-- | src/sstream/mod.rs (renamed from src/s_stream/mod.rs) | 30 |
9 files changed, 290 insertions, 116 deletions
diff --git a/src/deserialise/mod.rs b/src/deserialise/mod.rs index fff89e2..59e2b69 100644 --- a/src/deserialise/mod.rs +++ b/src/deserialise/mod.rs @@ -22,7 +22,7 @@ #[cfg(test)] mod test; -use crate::{DStream, Error}; +use crate::{Dstream, Error, Serialise}; use std::convert::Infallible; use std::error::Error as StdError; @@ -30,15 +30,18 @@ use std::mem::size_of; use std::num::NonZero; /// Denotes a type capable of being deserialised. -pub trait Deserialise: Sized { +pub trait Deserialise: Serialise + Sized { type Error; /// Deserialises the byte stream to an object. /// + /// This function should not take *more* bytes than specified by [`SERIALISE_LIMIT`](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>; + fn deserialise(stream: &mut Dstream) -> Result<Self, Self::Error>; } macro_rules! impl_float { @@ -46,7 +49,7 @@ macro_rules! impl_float { impl Deserialise for $type { type Error = Error; - fn deserialise(stream: &mut DStream) -> Result<Self, Self::Error> { + fn deserialise(stream: &mut Dstream) -> Result<Self, Self::Error> { let data = stream .take(size_of::<Self>())? .try_into() @@ -63,7 +66,7 @@ macro_rules! impl_int { impl Deserialise for $type { type Error = Error; - fn deserialise(stream: &mut DStream) -> Result<Self, Self::Error> { + fn deserialise(stream: &mut Dstream) -> Result<Self, Self::Error> { let data = stream .take(size_of::<Self>())? .try_into() @@ -76,7 +79,7 @@ macro_rules! impl_int { impl Deserialise for NonZero<$type> { type Error = Error; - fn deserialise(stream: &mut DStream) -> Result<Self, Self::Error> { + fn deserialise(stream: &mut Dstream) -> Result<Self, Self::Error> { let value = <$type>::deserialise(stream)?; NonZero::new(value) @@ -92,7 +95,7 @@ where T1: Deserialise<Error: StdError + 'static>, { type Error = Box<dyn StdError>; - fn deserialise(stream: &mut DStream) -> Result<Self, Self::Error> { + fn deserialise(stream: &mut Dstream) -> Result<Self, Self::Error> { Ok(( Deserialise::deserialise(stream)?, Deserialise::deserialise(stream)?, @@ -107,7 +110,7 @@ where T2: Deserialise<Error: StdError + 'static>, { type Error = Box<dyn StdError>; - fn deserialise(stream: &mut DStream) -> Result<Self, Self::Error> { + fn deserialise(stream: &mut Dstream) -> Result<Self, Self::Error> { Ok(( Deserialise::deserialise(stream)?, Deserialise::deserialise(stream)?, @@ -124,7 +127,7 @@ where T3: Deserialise<Error: StdError + 'static>, { type Error = Box<dyn StdError>; - fn deserialise(stream: &mut DStream) -> Result<Self, Self::Error> { + fn deserialise(stream: &mut Dstream) -> Result<Self, Self::Error> { Ok(( Deserialise::deserialise(stream)?, Deserialise::deserialise(stream)?, @@ -143,7 +146,7 @@ where T4: Deserialise<Error: StdError + 'static>, { type Error = Box<dyn StdError>; - fn deserialise(stream: &mut DStream) -> Result<Self, Self::Error> { + fn deserialise(stream: &mut Dstream) -> Result<Self, Self::Error> { Ok(( Deserialise::deserialise(stream)?, Deserialise::deserialise(stream)?, @@ -164,7 +167,7 @@ where T5: Deserialise<Error: StdError + 'static>, { type Error = Box<dyn StdError>; - fn deserialise(stream: &mut DStream) -> Result<Self, Self::Error> { + fn deserialise(stream: &mut Dstream) -> Result<Self, Self::Error> { Ok(( Deserialise::deserialise(stream)?, Deserialise::deserialise(stream)?, @@ -187,7 +190,7 @@ where T6: Deserialise<Error: StdError + 'static>, { type Error = Box<dyn StdError>; - fn deserialise(stream: &mut DStream) -> Result<Self, Self::Error> { + fn deserialise(stream: &mut Dstream) -> Result<Self, Self::Error> { Ok(( Deserialise::deserialise(stream)?, Deserialise::deserialise(stream)?, @@ -212,7 +215,7 @@ where T7: Deserialise<Error: StdError + 'static>, { type Error = Box<dyn StdError>; - fn deserialise(stream: &mut DStream) -> Result<Self, Self::Error> { + fn deserialise(stream: &mut Dstream) -> Result<Self, Self::Error> { Ok(( Deserialise::deserialise(stream)?, Deserialise::deserialise(stream)?, @@ -239,7 +242,7 @@ where T8: Deserialise<Error: StdError + 'static>, { type Error = Box<dyn StdError>; - fn deserialise(stream: &mut DStream) -> Result<Self, Self::Error> { + fn deserialise(stream: &mut Dstream) -> Result<Self, Self::Error> { Ok(( Deserialise::deserialise(stream)?, Deserialise::deserialise(stream)?, @@ -268,7 +271,7 @@ where T9: Deserialise<Error: StdError + 'static>, { type Error = Box<dyn StdError>; - fn deserialise(stream: &mut DStream) -> Result<Self, Self::Error> { + fn deserialise(stream: &mut Dstream) -> Result<Self, Self::Error> { Ok(( Deserialise::deserialise(stream)?, Deserialise::deserialise(stream)?, @@ -299,7 +302,7 @@ where T10: Deserialise<Error: StdError + 'static>, { type Error = Box<dyn StdError>; - fn deserialise(stream: &mut DStream) -> Result<Self, Self::Error> { + fn deserialise(stream: &mut Dstream) -> Result<Self, Self::Error> { Ok(( Deserialise::deserialise(stream)?, Deserialise::deserialise(stream)?, @@ -332,7 +335,7 @@ where T11: Deserialise<Error: StdError + 'static>, { type Error = Box<dyn StdError>; - fn deserialise(stream: &mut DStream) -> Result<Self, Self::Error> { + fn deserialise(stream: &mut Dstream) -> Result<Self, Self::Error> { Ok(( Deserialise::deserialise(stream)?, Deserialise::deserialise(stream)?, @@ -353,9 +356,9 @@ where impl<T: Deserialise<Error: StdError + 'static>, const N: usize> Deserialise for [T; N] { type Error = Box<dyn StdError>; - fn deserialise(stream: &mut DStream) -> Result<Self, Self::Error> { + fn deserialise(stream: &mut Dstream) -> Result<Self, Self::Error> { let len = usize::try_from(u64::deserialise(stream)?).unwrap(); - if len != N { return Err(Box::new(Error::ArrayLengthMismatch { len, ok_len: N })) }; + if len != N { return Err(Box::new(Error::ArrayTooShort { req: len, len: N })) }; let mut buf = Vec::with_capacity(len); for _ in 0x0..len { buf.push(Deserialise::deserialise(stream)?); } @@ -367,15 +370,15 @@ impl<T: Deserialise<Error: StdError + 'static>, const N: usize> Deserialise for } impl Deserialise for () { - type Error = Error; + type Error = Infallible; - fn deserialise(_stream: &mut DStream) -> Result<Self, Self::Error> { Ok(()) } + 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> { + fn deserialise(stream: &mut Dstream) -> Result<Self, Self::Error> { let value = u8::deserialise(stream)?; match value { @@ -389,7 +392,7 @@ impl Deserialise for bool { impl Deserialise for char { type Error = Error; - fn deserialise(stream: &mut DStream) -> Result<Self, Self::Error> { + fn deserialise(stream: &mut Dstream) -> Result<Self, Self::Error> { let value = u32::deserialise(stream)?; Self::from_u32(value) @@ -398,15 +401,15 @@ impl Deserialise for char { } impl Deserialise for Infallible { - type Error = Error; + type Error = Self; - fn deserialise(_stream: &mut DStream) -> Result<Self, Self::Error> { unreachable!() } + fn deserialise(_stream: &mut Dstream) -> Result<Self, Self::Error> { unreachable!() } } impl<T: Deserialise<Error: StdError + 'static>> Deserialise for Option<T> { type Error = Box<dyn StdError>; - fn deserialise(stream: &mut DStream) -> Result<Self, Self::Error> { + fn deserialise(stream: &mut Dstream) -> Result<Self, Self::Error> { let sign = bool::deserialise(stream)?; if sign { @@ -423,7 +426,7 @@ where <E as Deserialise>::Error: StdError + 'static, { type Error = Box<dyn StdError>; - fn deserialise(stream: &mut DStream) -> Result<Self, Self::Error> { + fn deserialise(stream: &mut Dstream) -> Result<Self, Self::Error> { let sign = bool::deserialise(stream)?; let value = if sign { diff --git a/src/deserialise/test.rs b/src/deserialise/test.rs index 394ed64..27acfda 100644 --- a/src/deserialise/test.rs +++ b/src/deserialise/test.rs @@ -19,7 +19,7 @@ // er General Public License along with bzipper. If // not, see <https://www.gnu.org/licenses/>. -use crate::{Deserialise, DStream, FixedString}; +use crate::{Deserialise, Dstream, FixedString}; #[test] fn test_deserialise() { @@ -35,7 +35,7 @@ fn test_deserialise() { 0x00, 0x00, 0x01, 0x80, ]; - let mut stream = DStream::from(&data); + let mut stream = Dstream::from(&data); assert_eq!( u8::deserialise(&mut stream).unwrap(), diff --git a/src/d_stream/mod.rs b/src/dstream/mod.rs index 088d751..a9cfa89 100644 --- a/src/d_stream/mod.rs +++ b/src/dstream/mod.rs @@ -19,20 +19,22 @@ // er General Public License along with bzipper. If // not, see <https://www.gnu.org/licenses/>. -use crate::{Error, Result, SStream}; +use crate::{Error, Result, Sstream}; use std::fmt::{Debug, Formatter}; /// Byte stream for deserialisation. /// -/// This type borrows a byte slice (hence [`new`](DStream::new)), keeping track internally of the used bytes. +/// This type borrows a byte slice (hence [`new`](Dstream::new)), keeping track internally of the used bytes. +/// +/// The stream may be converted to an [`Sstream`] using [`to_sstream`](Dstream::to_sstream). #[derive(Clone)] -pub struct DStream<'a> { +pub struct Dstream<'a> { data: &'a [u8], len: usize, } -impl<'a> DStream<'a> { +impl<'a> Dstream<'a> { /// Constructs a new byte stream. #[inline(always)] #[must_use] @@ -47,7 +49,7 @@ impl<'a> DStream<'a> { /// /// If the internal buffer doesn't hold at least the requested ammount of bytes, an [`EndOfDStream`](Error::EndOfDStream) error is returned. pub fn take(&mut self, len: usize) -> Result<&[u8]> { - if self.len < len { return Err(Error::EndOfDStream { len: self.len, ok_len: len } ) } + if self.len < len { return Err(Error::EndOfDStream { req: len, rem: self.len } ) } let start = self.data.len() - self.len; let stop = start + len; @@ -57,6 +59,22 @@ impl<'a> DStream<'a> { Ok(&self.data[start..stop]) } + /// Takes a single byte from the stream. + /// + /// # Errors + /// + /// If the internal buffer doesn't hold at least the requested ammount of bytes, an [`EndOfDStream`](Error::EndOfDStream) error is returned. + pub fn take_byte(&mut self) -> Result<u8> { + const LEN: usize = 0x1; + + if self.len < LEN { return Err(Error::EndOfDStream { req: LEN, rem: self.len } ) } + + self.len -= LEN; + + let index = self.data.len() - self.len; + Ok(self.data[index]) + } + /// Takes a slice of the remaining data. #[must_use] pub fn as_slice(&self) -> &[u8] { @@ -66,17 +84,17 @@ impl<'a> DStream<'a> { &self.data[start..stop] } - /// Converts the stream to a `SStream` object. + /// Converts the stream to a `Sstream` object. /// /// The returned object owns a copy of the remaining data. #[inline(always)] #[must_use] - pub fn to_s_stream(&self) -> SStream { - SStream(self.as_slice().to_vec()) + pub fn to_sstream(&self) -> Sstream { + Sstream(self.as_slice().to_vec()) } } -impl Debug for DStream<'_> { +impl Debug for Dstream<'_> { fn fmt(&self, f: &mut Formatter) -> std::fmt::Result { write!(f, "[")?; @@ -88,10 +106,10 @@ impl Debug for DStream<'_> { } } -impl<'a> From<&'a [u8]> for DStream<'a> { +impl<'a> From<&'a [u8]> for Dstream<'a> { fn from(value: &'a [u8]) -> Self { Self::new(value) } } -impl<'a, const N: usize> From<&'a [u8; N]> for DStream<'a> { +impl<'a, const N: usize> From<&'a [u8; N]> for Dstream<'a> { fn from(value: &'a [u8; N]) -> Self { Self::new(value) } } diff --git a/src/error/mod.rs b/src/error/mod.rs index 6eb6c15..d4df6ed 100644 --- a/src/error/mod.rs +++ b/src/error/mod.rs @@ -19,8 +19,6 @@ // er General Public License along with bzipper. If // not, see <https://www.gnu.org/licenses/>. -//! Error handling. - use std::error::Error as StdError; use std::fmt::{Display, Formatter}; use std::str::Utf8Error; @@ -30,22 +28,28 @@ pub type Result<T> = std::result::Result<T, Error>; /// Denotes an error. /// -/// These variants are used when a deserialisation fails. +/// These variants are used when deserialisation fails. /// Serialisations are assumed infallible. #[derive(Debug)] pub enum Error { - ArrayLengthMismatch { len: usize, ok_len: usize }, + /// An array could not hold the requested ammount of elements. + ArrayTooShort { req: usize, len: usize }, - EndOfDStream { len: usize, ok_len: usize }, + /// A string encountered an invalid UTF-8 sequence. + BadString { source: Utf8Error }, - FixedStringTooShort { len: usize, s: String }, + /// Bytes were requested on an empty stream. + EndOfDStream { 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 }, - InvalidUtf8 { source: Utf8Error }, - + /// A non-zero integer encountered the value (0). NullInteger, } @@ -54,16 +58,16 @@ impl Display for Error { use Error::*; match *self { - ArrayLengthMismatch { len, ok_len } => { - write!(f, "expected array of length ({ok_len}) but got ({len}) elements") + ArrayTooShort { req, len } => { + write!(f, "array of ({len}) element(s) cannot hold ({req})") }, - EndOfDStream { len, ok_len } => { - write!(f, "({ok_len}) byte(s) were requested but only ({len}) byte(s) were left") + BadString { ref source } =>{ + write!(f, "unable to parse utf8: \"{source}\"") }, - FixedStringTooShort { len, ref s } => { - write!(f, "fixed string with `N = {len}` cannot hold {s:?}") + EndOfDStream { req, rem } => { + write!(f, "({req}) byte(s) were requested but only ({rem}) byte(s) were left") }, InvalidBoolean { value } => { @@ -74,10 +78,6 @@ impl Display for Error { write!(f, "code point U+{value:04X} is not valid") }, - InvalidUtf8 { ref source } =>{ - write!(f, "unable to parse utf8: \"{source}\"") - }, - NullInteger => { write!(f, "expected non-zero integer but got (0)") }, @@ -90,7 +90,7 @@ impl StdError for Error { use Error::*; match *self { - InvalidUtf8 { ref source } => Some(source), + BadString { ref source } => Some(source), _ => None, } diff --git a/src/fixed_string/mod.rs b/src/fixed_string/mod.rs index e755c29..14226a1 100644 --- a/src/fixed_string/mod.rs +++ b/src/fixed_string/mod.rs @@ -24,11 +24,11 @@ mod test; use crate::{ Deserialise, - DStream, + Dstream, Error, FixedStringIter, Serialise, - SStream, + Sstream, }; use std::cmp::Ordering; @@ -53,13 +53,13 @@ impl<const N: usize> FixedString<N> { /// /// # Errors /// - /// If the given string `s` cannot fit into `N` characters, a [`FixedStringTooShort`](Error::FixedStringTooShort) error is returned. + /// 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::FixedStringTooShort { len: N, s: s.to_owned() }) } + if i >= N { return Err(Error::ArrayTooShort { req: len, len: N }) } buf[i] = c; } @@ -127,16 +127,16 @@ impl<const N: usize> Debug for FixedString<N> { impl<const N: usize> Deserialise for FixedString<N> { type Error = Error; - fn deserialise(stream: &mut DStream) -> Result<Self, Self::Error> { + fn deserialise(stream: &mut Dstream) -> Result<Self, Self::Error> { let len = usize::try_from(u64::deserialise(stream)?).unwrap(); let data = stream.take(len)?; let s = std::str::from_utf8(data) - .map_err(|e| Error::InvalidUtf8 { source: e })?; + .map_err(|e| Error::BadString { source: e })?; let len = s.chars().count(); if len > N { - return Err(Error::FixedStringTooShort { len, s: s.to_owned() }); + return Err(Error::ArrayTooShort { req: len, len: N }); } let mut buf = ['\0'; N]; @@ -272,7 +272,9 @@ impl<const N: usize, const M: usize> PartialOrd<FixedString<M>> for FixedString< } impl<const N: usize> Serialise for FixedString<N> { - fn serialise(&self, stream: &mut SStream) { + const SERIALISE_LIMIT: usize = 0x4 * N; + + fn serialise(&self, stream: &mut Sstream) { let s: String = self.iter().collect(); let len = u64::try_from(s.len()).unwrap(); @@ -21,8 +21,8 @@ //! Binary (de)serialisation. //! -//! Contrary to [Serde](https://crates.io/crates/serde/)/[Bincode](https://crates.io/crates/bincode/), the goal of `bzipper` is to serialise data without inflating the resulting binary sequence. -//! As such, one may consider this crate to be more low-level. +//! 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. //! @@ -36,10 +36,10 @@ macro_rules! use_mod { } pub(in crate) use use_mod; -use_mod!(pub d_stream); 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 s_stream); use_mod!(pub serialise); +use_mod!(pub sstream); diff --git a/src/serialise/mod.rs b/src/serialise/mod.rs index b8f6dba..98c1417 100644 --- a/src/serialise/mod.rs +++ b/src/serialise/mod.rs @@ -22,7 +22,7 @@ #[cfg(test)] mod test; -use crate::SStream; +use crate::Sstream; use std::convert::Infallible; use std::mem::size_of; @@ -30,17 +30,22 @@ use std::num::NonZero; /// Denotes a type capable of being serialised. pub trait Serialise: Sized { + /// The maximum ammount of bytes that can result from serialisation. + const SERIALISE_LIMIT: usize; + /// Serialises `self` into a byte stream. /// - /// One may assume that the resulting stream has at most the same ammount of bytes as before serialisation. - /// Therefore, not observing this rule is a logic error. - fn serialise(&self, stream: &mut SStream); + /// This function should not append *more* bytes than specified in [`SERIALISE_LIMIT`](Serialise::SERIALISE_LIMIT). + /// Doing so is considered a logic error. + fn serialise(&self, stream: &mut Sstream); } macro_rules! impl_float { ($type:ty) => { impl Serialise for $type { - fn serialise(&self, stream: &mut SStream) { + const SERIALISE_LIMIT: usize = size_of::<$type>(); + + fn serialise(&self, stream: &mut Sstream) { stream.append(&self.to_be_bytes()) } } @@ -50,13 +55,17 @@ macro_rules! impl_float { macro_rules! impl_int { ($type:ty) => { impl Serialise for $type { - fn serialise(&self, stream: &mut SStream) { + const SERIALISE_LIMIT: usize = size_of::<$type>(); + + fn serialise(&self, stream: &mut Sstream) { stream.append(&self.to_be_bytes()) } } impl Serialise for NonZero<$type> { - fn serialise(&self, stream: &mut SStream) { + const SERIALISE_LIMIT: usize = size_of::<$type>(); + + fn serialise(&self, stream: &mut Sstream) { self.get().serialise(stream) } } @@ -67,7 +76,11 @@ impl<T0, T1> Serialise for (T0, T1) where T0: Serialise, T1: Serialise, { - fn serialise(&self, stream: &mut SStream) { + const SERIALISE_LIMIT: usize = + T0::SERIALISE_LIMIT + + T1::SERIALISE_LIMIT; + + fn serialise(&self, stream: &mut Sstream) { self.0.serialise(stream); self.1.serialise(stream); } @@ -78,7 +91,12 @@ where T0: Serialise, T1: Serialise, T2: Serialise, { - fn serialise(&self, stream: &mut SStream) { + const SERIALISE_LIMIT: usize = + T0::SERIALISE_LIMIT + + T1::SERIALISE_LIMIT + + T2::SERIALISE_LIMIT; + + fn serialise(&self, stream: &mut Sstream) { self.0.serialise(stream); self.1.serialise(stream); self.2.serialise(stream); @@ -91,7 +109,13 @@ where T1: Serialise, T2: Serialise, T3: Serialise, { - fn serialise(&self, stream: &mut SStream) { + const SERIALISE_LIMIT: usize = + T0::SERIALISE_LIMIT + + T1::SERIALISE_LIMIT + + T2::SERIALISE_LIMIT + + T3::SERIALISE_LIMIT; + + fn serialise(&self, stream: &mut Sstream) { self.0.serialise(stream); self.1.serialise(stream); self.2.serialise(stream); @@ -106,7 +130,14 @@ where T2: Serialise, T3: Serialise, T4: Serialise, { - fn serialise(&self, stream: &mut SStream) { + 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) { self.0.serialise(stream); self.1.serialise(stream); self.2.serialise(stream); @@ -123,7 +154,15 @@ where T3: Serialise, T4: Serialise, T5: Serialise, { - fn serialise(&self, stream: &mut SStream) { + 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) { self.0.serialise(stream); self.1.serialise(stream); self.2.serialise(stream); @@ -142,7 +181,16 @@ where T4: Serialise, T5: Serialise, T6: Serialise, { - fn serialise(&self, stream: &mut SStream) { + 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) { self.0.serialise(stream); self.1.serialise(stream); self.2.serialise(stream); @@ -163,7 +211,17 @@ where T5: Serialise, T6: Serialise, T7: Serialise, { - fn serialise(&self, stream: &mut SStream) { + 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) { self.0.serialise(stream); self.1.serialise(stream); self.2.serialise(stream); @@ -186,7 +244,18 @@ where T6: Serialise, T7: Serialise, T8: Serialise, { - fn serialise(&self, stream: &mut SStream) { + 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) { self.0.serialise(stream); self.1.serialise(stream); self.2.serialise(stream); @@ -211,7 +280,19 @@ where T7: Serialise, T8: Serialise, T9: Serialise, { - fn serialise(&self, stream: &mut SStream) { + 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) { self.0.serialise(stream); self.1.serialise(stream); self.2.serialise(stream); @@ -238,7 +319,20 @@ where T8: Serialise, T9: Serialise, T10: Serialise, { - fn serialise(&self, stream: &mut SStream) { + 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) { self.0.serialise(stream); self.1.serialise(stream); self.2.serialise(stream); @@ -267,7 +361,21 @@ where T9: Serialise, T10: Serialise, T11: Serialise, { - fn serialise(&self, stream: &mut SStream) { + 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) { self.0.serialise(stream); self.1.serialise(stream); self.2.serialise(stream); @@ -284,7 +392,9 @@ where } impl<T: Serialise, const N: usize> Serialise for [T; N] { - fn serialise(&self, stream: &mut SStream) { + const SERIALISE_LIMIT: usize = T::SERIALISE_LIMIT * N; + + fn serialise(&self, stream: &mut Sstream) { u64::try_from(self.len()).unwrap().serialise(stream); for v in self { v.serialise(stream) } @@ -292,35 +402,45 @@ impl<T: Serialise, const N: usize> Serialise for [T; N] { } impl Serialise for () { - fn serialise(&self, _stream: &mut SStream) { } + const SERIALISE_LIMIT: usize = size_of::<Self>(); + + fn serialise(&self, _stream: &mut Sstream) { } } impl Serialise for bool { - fn serialise(&self, stream: &mut SStream) { + const SERIALISE_LIMIT: usize = size_of::<Self>(); + + fn serialise(&self, stream: &mut Sstream) { u8::from(*self).serialise(stream) } } impl Serialise for char { - fn serialise(&self, stream: &mut SStream) { + const SERIALISE_LIMIT: usize = size_of::<Self>(); + + fn serialise(&self, stream: &mut Sstream) { u32::from(*self).serialise(stream) } } impl Serialise for Infallible { - fn serialise(&self, _stream: &mut SStream) { unreachable!() } + const SERIALISE_LIMIT: usize = size_of::<Self>(); + + fn serialise(&self, _stream: &mut Sstream) { unreachable!() } } impl<T: Serialise> Serialise for Option<T> { - fn serialise(&self, stream: &mut SStream) { + const SERIALISE_LIMIT: usize = T::SERIALISE_LIMIT + 0x1; + + fn serialise(&self, stream: &mut Sstream) { match *self { None => { - stream.append(&[0x00]); + stream.append_byte(0x00); stream.append(&vec![0x00; size_of::<T>()]); }, Some(ref v) => { - stream.append(&[0x01]); + stream.append_byte(0x01); v.serialise(stream); }, }; @@ -328,15 +448,23 @@ impl<T: Serialise> Serialise for Option<T> { } impl<T: Serialise, E: Serialise> Serialise for Result<T, E> { - fn serialise(&self, stream: &mut SStream) { + 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) { match *self { Ok(ref v) => { - stream.append(&[0x00]); + stream.append_byte(0x00); v.serialise(stream); }, Err(ref e) => { - stream.append(&[0x01]); + stream.append_byte(0x01); e.serialise(stream); }, }; diff --git a/src/serialise/test.rs b/src/serialise/test.rs index e0a0004..245c2c3 100644 --- a/src/serialise/test.rs +++ b/src/serialise/test.rs @@ -1,10 +1,29 @@ -// Copyright 2022-2024 Gabriel Bjørnager Jensen. +// 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, SStream, Serialise}; +use crate::{FixedString, Serialise, Sstream}; #[test] fn test_serialise() { - let mut stream = SStream::new(); + let mut stream = Sstream::new(); 0x00_u8.serialise(&mut stream); 0xFF_u8.serialise(&mut stream); diff --git a/src/s_stream/mod.rs b/src/sstream/mod.rs index 454adb8..f28875a 100644 --- a/src/s_stream/mod.rs +++ b/src/sstream/mod.rs @@ -19,7 +19,7 @@ // er General Public License along with bzipper. If // not, see <https://www.gnu.org/licenses/>. -use crate::{DStream, Serialise}; +use crate::{Dstream, Serialise}; use std::fmt::{Debug, Formatter}; use std::mem::size_of; @@ -27,36 +27,40 @@ use std::mem::size_of; /// Byte stream for serialisation. /// /// The bytes themselves are contained by the type. -/// The stream can +/// The stream may be converted to [`Dstream`] using [`as_dstream`](Sstream::as_dstream) #[derive(Clone, Eq, PartialEq)] -pub struct SStream(pub(in crate) Vec<u8>); +pub struct Sstream(pub(in crate) Vec<u8>); -impl SStream { +impl Sstream { /// Constructs a new, empty byte stream. #[inline(always)] #[must_use] pub const fn new() -> Self { Self(Vec::new()) } /// Extends the byte stream. - #[inline(always)] pub fn append(&mut self, extra: &[u8]) { self.0.extend(extra); } - /// Converts the stream to a `DStream` object. + /// Extends the byte stream by a single byte. + pub fn append_byte(&mut self, extra: u8) { + self.0.push(extra); + } + + /// Converts the stream to a `Dstream` object. /// /// The returned object references the original stream. #[inline(always)] #[must_use] - pub fn as_d_stream(&self) -> DStream { DStream::new(&self.0) } + pub fn as_dstream(&self) -> Dstream { Dstream::new(&self.0) } } -impl AsRef<[u8]> for SStream { +impl AsRef<[u8]> for Sstream { #[inline(always)] fn as_ref(&self) -> &[u8] { self.0.as_ref() } } -impl Debug for SStream { +impl Debug for Sstream { fn fmt(&self, f: &mut Formatter) -> std::fmt::Result { write!(f, "[")?; @@ -68,12 +72,12 @@ impl Debug for SStream { } } -impl Default for SStream { +impl Default for Sstream { #[inline(always)] fn default() -> Self { Self::new() } } -impl<T: Serialise> From<&T> for SStream { +impl<T: Serialise> From<&T> for Sstream { fn from(value: &T) -> Self { let mut stream = Self(Vec::with_capacity(size_of::<T>())); value.serialise(&mut stream); @@ -82,7 +86,7 @@ impl<T: Serialise> From<&T> for SStream { } } -impl From<SStream> for Box<[u8]> { +impl From<Sstream> for Box<[u8]> { #[inline(always)] - fn from(value: SStream) -> Self { value.0.into_boxed_slice() } + fn from(value: Sstream) -> Self { value.0.into_boxed_slice() } } |