summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.md19
-rw-r--r--Cargo.toml2
-rw-r--r--README.md6
-rw-r--r--src/deserialise/mod.rs57
-rw-r--r--src/deserialise/test.rs4
-rw-r--r--src/dstream/mod.rs (renamed from src/d_stream/mod.rs)40
-rw-r--r--src/error/mod.rs38
-rw-r--r--src/fixed_string/mod.rs18
-rw-r--r--src/lib.rs8
-rw-r--r--src/serialise/mod.rs186
-rw-r--r--src/serialise/test.rs25
-rw-r--r--src/sstream/mod.rs (renamed from src/s_stream/mod.rs)30
12 files changed, 313 insertions, 120 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 3b2df64..67c5a1d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,22 @@
+# 0.3.0
+
+* Bump minor
+* Document errors
+* Rename: `ArrayLengthMismatch` -> `ArrayTooShort`
+* Remove error `FixedStringTooShort`
+* Rename: `InvalidUtf8` -> `BadString`
+* Rework errors
+* Rename methods: `as_d_stream` -> `as_dstream`, `to_s_stream` -> `to_sstream`
+* Add `SERIALISATION_LIMIT` constant to `Serialise`
+* Make some deserialisations infallible
+* Add method `append_byte` to `SStream`
+* Add method `take_byte` to `DStream`
+* Rename `SStream` -> `Sstream`, `DStream` -> `Dstream`
+* Update readme
+* Update documentation
+* Make `Deserialise` require `Serialise`
+* Fix copyright/license notice in `"src/serialise/test.rs"`
+
# 0.2.0
* Clean up code
diff --git a/Cargo.toml b/Cargo.toml
index fe28abc..22857a6 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "bzipper"
-version = "0.2.0"
+version = "0.3.0"
authors = ["Gabriel Bjørnager Jensen"]
edition = "2021"
description = "Binary (de)serialiser."
diff --git a/README.md b/README.md
index f71b6b7..d7effbe 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,7 @@
-[`bzipper`](https://crates.io/crates/bzipper) is a binary (de)serialiser.
+[`bzipper`](https://crates.io/crates/bzipper) is a binary (de)serialiser for the Rust language.
-Contrary to [Serde](https://crates.io/crates/serde/)/[Bincode](https://crates.io/crates/bincode/), the goal of this crate 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 this crate is to serialise data with a known size limit.
+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.
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();
diff --git a/src/lib.rs b/src/lib.rs
index cfe616b..d7742ec 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -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() }
}