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";
This commit is contained in:
parent
05123b9cd8
commit
093f6f013b
12 changed files with 313 additions and 120 deletions
19
CHANGELOG.md
19
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
|
# 0.2.0
|
||||||
|
|
||||||
* Clean up code
|
* Clean up code
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "bzipper"
|
name = "bzipper"
|
||||||
version = "0.2.0"
|
version = "0.3.0"
|
||||||
authors = ["Gabriel Bjørnager Jensen"]
|
authors = ["Gabriel Bjørnager Jensen"]
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
description = "Binary (de)serialiser."
|
description = "Binary (de)serialiser."
|
||||||
|
|
|
@ -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.
|
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.
|
||||||
As such, one may consider this crate to be more low-level.
|
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.
|
Keep in mind that this project is still work-in-progress.
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test;
|
mod test;
|
||||||
|
|
||||||
use crate::{DStream, Error};
|
use crate::{Dstream, Error, Serialise};
|
||||||
|
|
||||||
use std::convert::Infallible;
|
use std::convert::Infallible;
|
||||||
use std::error::Error as StdError;
|
use std::error::Error as StdError;
|
||||||
|
@ -30,15 +30,18 @@ use std::mem::size_of;
|
||||||
use std::num::NonZero;
|
use std::num::NonZero;
|
||||||
|
|
||||||
/// Denotes a type capable of being deserialised.
|
/// Denotes a type capable of being deserialised.
|
||||||
pub trait Deserialise: Sized {
|
pub trait Deserialise: Serialise + Sized {
|
||||||
type Error;
|
type Error;
|
||||||
|
|
||||||
/// Deserialises the byte stream to an object.
|
/// 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
|
/// # Errors
|
||||||
///
|
///
|
||||||
/// If deserialisation failed, e.g. by an invalid value being found, an error is returned.
|
/// 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 {
|
macro_rules! impl_float {
|
||||||
|
@ -46,7 +49,7 @@ macro_rules! impl_float {
|
||||||
impl Deserialise for $type {
|
impl Deserialise for $type {
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
|
|
||||||
fn deserialise(stream: &mut DStream) -> Result<Self, Self::Error> {
|
fn deserialise(stream: &mut Dstream) -> Result<Self, Self::Error> {
|
||||||
let data = stream
|
let data = stream
|
||||||
.take(size_of::<Self>())?
|
.take(size_of::<Self>())?
|
||||||
.try_into()
|
.try_into()
|
||||||
|
@ -63,7 +66,7 @@ macro_rules! impl_int {
|
||||||
impl Deserialise for $type {
|
impl Deserialise for $type {
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
|
|
||||||
fn deserialise(stream: &mut DStream) -> Result<Self, Self::Error> {
|
fn deserialise(stream: &mut Dstream) -> Result<Self, Self::Error> {
|
||||||
let data = stream
|
let data = stream
|
||||||
.take(size_of::<Self>())?
|
.take(size_of::<Self>())?
|
||||||
.try_into()
|
.try_into()
|
||||||
|
@ -76,7 +79,7 @@ macro_rules! impl_int {
|
||||||
impl Deserialise for NonZero<$type> {
|
impl Deserialise for NonZero<$type> {
|
||||||
type Error = Error;
|
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)?;
|
let value = <$type>::deserialise(stream)?;
|
||||||
|
|
||||||
NonZero::new(value)
|
NonZero::new(value)
|
||||||
|
@ -92,7 +95,7 @@ where
|
||||||
T1: Deserialise<Error: StdError + 'static>, {
|
T1: Deserialise<Error: StdError + 'static>, {
|
||||||
type Error = Box<dyn StdError>;
|
type Error = Box<dyn StdError>;
|
||||||
|
|
||||||
fn deserialise(stream: &mut DStream) -> Result<Self, Self::Error> {
|
fn deserialise(stream: &mut Dstream) -> Result<Self, Self::Error> {
|
||||||
Ok((
|
Ok((
|
||||||
Deserialise::deserialise(stream)?,
|
Deserialise::deserialise(stream)?,
|
||||||
Deserialise::deserialise(stream)?,
|
Deserialise::deserialise(stream)?,
|
||||||
|
@ -107,7 +110,7 @@ where
|
||||||
T2: Deserialise<Error: StdError + 'static>, {
|
T2: Deserialise<Error: StdError + 'static>, {
|
||||||
type Error = Box<dyn StdError>;
|
type Error = Box<dyn StdError>;
|
||||||
|
|
||||||
fn deserialise(stream: &mut DStream) -> Result<Self, Self::Error> {
|
fn deserialise(stream: &mut Dstream) -> Result<Self, Self::Error> {
|
||||||
Ok((
|
Ok((
|
||||||
Deserialise::deserialise(stream)?,
|
Deserialise::deserialise(stream)?,
|
||||||
Deserialise::deserialise(stream)?,
|
Deserialise::deserialise(stream)?,
|
||||||
|
@ -124,7 +127,7 @@ where
|
||||||
T3: Deserialise<Error: StdError + 'static>, {
|
T3: Deserialise<Error: StdError + 'static>, {
|
||||||
type Error = Box<dyn StdError>;
|
type Error = Box<dyn StdError>;
|
||||||
|
|
||||||
fn deserialise(stream: &mut DStream) -> Result<Self, Self::Error> {
|
fn deserialise(stream: &mut Dstream) -> Result<Self, Self::Error> {
|
||||||
Ok((
|
Ok((
|
||||||
Deserialise::deserialise(stream)?,
|
Deserialise::deserialise(stream)?,
|
||||||
Deserialise::deserialise(stream)?,
|
Deserialise::deserialise(stream)?,
|
||||||
|
@ -143,7 +146,7 @@ where
|
||||||
T4: Deserialise<Error: StdError + 'static>, {
|
T4: Deserialise<Error: StdError + 'static>, {
|
||||||
type Error = Box<dyn StdError>;
|
type Error = Box<dyn StdError>;
|
||||||
|
|
||||||
fn deserialise(stream: &mut DStream) -> Result<Self, Self::Error> {
|
fn deserialise(stream: &mut Dstream) -> Result<Self, Self::Error> {
|
||||||
Ok((
|
Ok((
|
||||||
Deserialise::deserialise(stream)?,
|
Deserialise::deserialise(stream)?,
|
||||||
Deserialise::deserialise(stream)?,
|
Deserialise::deserialise(stream)?,
|
||||||
|
@ -164,7 +167,7 @@ where
|
||||||
T5: Deserialise<Error: StdError + 'static>, {
|
T5: Deserialise<Error: StdError + 'static>, {
|
||||||
type Error = Box<dyn StdError>;
|
type Error = Box<dyn StdError>;
|
||||||
|
|
||||||
fn deserialise(stream: &mut DStream) -> Result<Self, Self::Error> {
|
fn deserialise(stream: &mut Dstream) -> Result<Self, Self::Error> {
|
||||||
Ok((
|
Ok((
|
||||||
Deserialise::deserialise(stream)?,
|
Deserialise::deserialise(stream)?,
|
||||||
Deserialise::deserialise(stream)?,
|
Deserialise::deserialise(stream)?,
|
||||||
|
@ -187,7 +190,7 @@ where
|
||||||
T6: Deserialise<Error: StdError + 'static>, {
|
T6: Deserialise<Error: StdError + 'static>, {
|
||||||
type Error = Box<dyn StdError>;
|
type Error = Box<dyn StdError>;
|
||||||
|
|
||||||
fn deserialise(stream: &mut DStream) -> Result<Self, Self::Error> {
|
fn deserialise(stream: &mut Dstream) -> Result<Self, Self::Error> {
|
||||||
Ok((
|
Ok((
|
||||||
Deserialise::deserialise(stream)?,
|
Deserialise::deserialise(stream)?,
|
||||||
Deserialise::deserialise(stream)?,
|
Deserialise::deserialise(stream)?,
|
||||||
|
@ -212,7 +215,7 @@ where
|
||||||
T7: Deserialise<Error: StdError + 'static>, {
|
T7: Deserialise<Error: StdError + 'static>, {
|
||||||
type Error = Box<dyn StdError>;
|
type Error = Box<dyn StdError>;
|
||||||
|
|
||||||
fn deserialise(stream: &mut DStream) -> Result<Self, Self::Error> {
|
fn deserialise(stream: &mut Dstream) -> Result<Self, Self::Error> {
|
||||||
Ok((
|
Ok((
|
||||||
Deserialise::deserialise(stream)?,
|
Deserialise::deserialise(stream)?,
|
||||||
Deserialise::deserialise(stream)?,
|
Deserialise::deserialise(stream)?,
|
||||||
|
@ -239,7 +242,7 @@ where
|
||||||
T8: Deserialise<Error: StdError + 'static>, {
|
T8: Deserialise<Error: StdError + 'static>, {
|
||||||
type Error = Box<dyn StdError>;
|
type Error = Box<dyn StdError>;
|
||||||
|
|
||||||
fn deserialise(stream: &mut DStream) -> Result<Self, Self::Error> {
|
fn deserialise(stream: &mut Dstream) -> Result<Self, Self::Error> {
|
||||||
Ok((
|
Ok((
|
||||||
Deserialise::deserialise(stream)?,
|
Deserialise::deserialise(stream)?,
|
||||||
Deserialise::deserialise(stream)?,
|
Deserialise::deserialise(stream)?,
|
||||||
|
@ -268,7 +271,7 @@ where
|
||||||
T9: Deserialise<Error: StdError + 'static>, {
|
T9: Deserialise<Error: StdError + 'static>, {
|
||||||
type Error = Box<dyn StdError>;
|
type Error = Box<dyn StdError>;
|
||||||
|
|
||||||
fn deserialise(stream: &mut DStream) -> Result<Self, Self::Error> {
|
fn deserialise(stream: &mut Dstream) -> Result<Self, Self::Error> {
|
||||||
Ok((
|
Ok((
|
||||||
Deserialise::deserialise(stream)?,
|
Deserialise::deserialise(stream)?,
|
||||||
Deserialise::deserialise(stream)?,
|
Deserialise::deserialise(stream)?,
|
||||||
|
@ -299,7 +302,7 @@ where
|
||||||
T10: Deserialise<Error: StdError + 'static>, {
|
T10: Deserialise<Error: StdError + 'static>, {
|
||||||
type Error = Box<dyn StdError>;
|
type Error = Box<dyn StdError>;
|
||||||
|
|
||||||
fn deserialise(stream: &mut DStream) -> Result<Self, Self::Error> {
|
fn deserialise(stream: &mut Dstream) -> Result<Self, Self::Error> {
|
||||||
Ok((
|
Ok((
|
||||||
Deserialise::deserialise(stream)?,
|
Deserialise::deserialise(stream)?,
|
||||||
Deserialise::deserialise(stream)?,
|
Deserialise::deserialise(stream)?,
|
||||||
|
@ -332,7 +335,7 @@ where
|
||||||
T11: Deserialise<Error: StdError + 'static>, {
|
T11: Deserialise<Error: StdError + 'static>, {
|
||||||
type Error = Box<dyn StdError>;
|
type Error = Box<dyn StdError>;
|
||||||
|
|
||||||
fn deserialise(stream: &mut DStream) -> Result<Self, Self::Error> {
|
fn deserialise(stream: &mut Dstream) -> Result<Self, Self::Error> {
|
||||||
Ok((
|
Ok((
|
||||||
Deserialise::deserialise(stream)?,
|
Deserialise::deserialise(stream)?,
|
||||||
Deserialise::deserialise(stream)?,
|
Deserialise::deserialise(stream)?,
|
||||||
|
@ -353,9 +356,9 @@ where
|
||||||
impl<T: Deserialise<Error: StdError + 'static>, const N: usize> Deserialise for [T; N] {
|
impl<T: Deserialise<Error: StdError + 'static>, const N: usize> Deserialise for [T; N] {
|
||||||
type Error = Box<dyn StdError>;
|
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();
|
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);
|
let mut buf = Vec::with_capacity(len);
|
||||||
for _ in 0x0..len { buf.push(Deserialise::deserialise(stream)?); }
|
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 () {
|
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 {
|
impl Deserialise for bool {
|
||||||
type Error = Error;
|
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)?;
|
let value = u8::deserialise(stream)?;
|
||||||
|
|
||||||
match value {
|
match value {
|
||||||
|
@ -389,7 +392,7 @@ impl Deserialise for bool {
|
||||||
impl Deserialise for char {
|
impl Deserialise for char {
|
||||||
type Error = Error;
|
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)?;
|
let value = u32::deserialise(stream)?;
|
||||||
|
|
||||||
Self::from_u32(value)
|
Self::from_u32(value)
|
||||||
|
@ -398,15 +401,15 @@ impl Deserialise for char {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Deserialise for Infallible {
|
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> {
|
impl<T: Deserialise<Error: StdError + 'static>> Deserialise for Option<T> {
|
||||||
type Error = Box<dyn StdError>;
|
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 sign = bool::deserialise(stream)?;
|
||||||
|
|
||||||
if sign {
|
if sign {
|
||||||
|
@ -423,7 +426,7 @@ where
|
||||||
<E as Deserialise>::Error: StdError + 'static, {
|
<E as Deserialise>::Error: StdError + 'static, {
|
||||||
type Error = Box<dyn StdError>;
|
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 sign = bool::deserialise(stream)?;
|
||||||
|
|
||||||
let value = if sign {
|
let value = if sign {
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
// er General Public License along with bzipper. If
|
// er General Public License along with bzipper. If
|
||||||
// not, see <https://www.gnu.org/licenses/>.
|
// not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
use crate::{Deserialise, DStream, FixedString};
|
use crate::{Deserialise, Dstream, FixedString};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_deserialise() {
|
fn test_deserialise() {
|
||||||
|
@ -35,7 +35,7 @@ fn test_deserialise() {
|
||||||
0x00, 0x00, 0x01, 0x80,
|
0x00, 0x00, 0x01, 0x80,
|
||||||
];
|
];
|
||||||
|
|
||||||
let mut stream = DStream::from(&data);
|
let mut stream = Dstream::from(&data);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
u8::deserialise(&mut stream).unwrap(),
|
u8::deserialise(&mut stream).unwrap(),
|
||||||
|
|
|
@ -19,20 +19,22 @@
|
||||||
// er General Public License along with bzipper. If
|
// er General Public License along with bzipper. If
|
||||||
// not, see <https://www.gnu.org/licenses/>.
|
// not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
use crate::{Error, Result, SStream};
|
use crate::{Error, Result, Sstream};
|
||||||
|
|
||||||
use std::fmt::{Debug, Formatter};
|
use std::fmt::{Debug, Formatter};
|
||||||
|
|
||||||
/// Byte stream for deserialisation.
|
/// 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)]
|
#[derive(Clone)]
|
||||||
pub struct DStream<'a> {
|
pub struct Dstream<'a> {
|
||||||
data: &'a [u8],
|
data: &'a [u8],
|
||||||
len: usize,
|
len: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> DStream<'a> {
|
impl<'a> Dstream<'a> {
|
||||||
/// Constructs a new byte stream.
|
/// Constructs a new byte stream.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
#[must_use]
|
#[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.
|
/// 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]> {
|
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 start = self.data.len() - self.len;
|
||||||
let stop = start + len;
|
let stop = start + len;
|
||||||
|
@ -57,6 +59,22 @@ impl<'a> DStream<'a> {
|
||||||
Ok(&self.data[start..stop])
|
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.
|
/// Takes a slice of the remaining data.
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn as_slice(&self) -> &[u8] {
|
pub fn as_slice(&self) -> &[u8] {
|
||||||
|
@ -66,17 +84,17 @@ impl<'a> DStream<'a> {
|
||||||
&self.data[start..stop]
|
&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.
|
/// The returned object owns a copy of the remaining data.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn to_s_stream(&self) -> SStream {
|
pub fn to_sstream(&self) -> Sstream {
|
||||||
SStream(self.as_slice().to_vec())
|
Sstream(self.as_slice().to_vec())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Debug for DStream<'_> {
|
impl Debug for Dstream<'_> {
|
||||||
fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
|
fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
|
||||||
write!(f, "[")?;
|
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) }
|
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) }
|
fn from(value: &'a [u8; N]) -> Self { Self::new(value) }
|
||||||
}
|
}
|
|
@ -19,8 +19,6 @@
|
||||||
// er General Public License along with bzipper. If
|
// er General Public License along with bzipper. If
|
||||||
// not, see <https://www.gnu.org/licenses/>.
|
// not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
//! Error handling.
|
|
||||||
|
|
||||||
use std::error::Error as StdError;
|
use std::error::Error as StdError;
|
||||||
use std::fmt::{Display, Formatter};
|
use std::fmt::{Display, Formatter};
|
||||||
use std::str::Utf8Error;
|
use std::str::Utf8Error;
|
||||||
|
@ -30,22 +28,28 @@ pub type Result<T> = std::result::Result<T, Error>;
|
||||||
|
|
||||||
/// Denotes an error.
|
/// Denotes an error.
|
||||||
///
|
///
|
||||||
/// These variants are used when a deserialisation fails.
|
/// These variants are used when deserialisation fails.
|
||||||
/// Serialisations are assumed infallible.
|
/// Serialisations are assumed infallible.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum Error {
|
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 },
|
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 },
|
InvalidCodePoint { value: u32 },
|
||||||
|
|
||||||
InvalidUtf8 { source: Utf8Error },
|
/// A non-zero integer encountered the value (0).
|
||||||
|
|
||||||
NullInteger,
|
NullInteger,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,16 +58,16 @@ impl Display for Error {
|
||||||
use Error::*;
|
use Error::*;
|
||||||
|
|
||||||
match *self {
|
match *self {
|
||||||
ArrayLengthMismatch { len, ok_len } => {
|
ArrayTooShort { req, len } => {
|
||||||
write!(f, "expected array of length ({ok_len}) but got ({len}) elements")
|
write!(f, "array of ({len}) element(s) cannot hold ({req})")
|
||||||
},
|
},
|
||||||
|
|
||||||
EndOfDStream { len, ok_len } => {
|
BadString { ref source } =>{
|
||||||
write!(f, "({ok_len}) byte(s) were requested but only ({len}) byte(s) were left")
|
write!(f, "unable to parse utf8: \"{source}\"")
|
||||||
},
|
},
|
||||||
|
|
||||||
FixedStringTooShort { len, ref s } => {
|
EndOfDStream { req, rem } => {
|
||||||
write!(f, "fixed string with `N = {len}` cannot hold {s:?}")
|
write!(f, "({req}) byte(s) were requested but only ({rem}) byte(s) were left")
|
||||||
},
|
},
|
||||||
|
|
||||||
InvalidBoolean { value } => {
|
InvalidBoolean { value } => {
|
||||||
|
@ -74,10 +78,6 @@ impl Display for Error {
|
||||||
write!(f, "code point U+{value:04X} is not valid")
|
write!(f, "code point U+{value:04X} is not valid")
|
||||||
},
|
},
|
||||||
|
|
||||||
InvalidUtf8 { ref source } =>{
|
|
||||||
write!(f, "unable to parse utf8: \"{source}\"")
|
|
||||||
},
|
|
||||||
|
|
||||||
NullInteger => {
|
NullInteger => {
|
||||||
write!(f, "expected non-zero integer but got (0)")
|
write!(f, "expected non-zero integer but got (0)")
|
||||||
},
|
},
|
||||||
|
@ -90,7 +90,7 @@ impl StdError for Error {
|
||||||
use Error::*;
|
use Error::*;
|
||||||
|
|
||||||
match *self {
|
match *self {
|
||||||
InvalidUtf8 { ref source } => Some(source),
|
BadString { ref source } => Some(source),
|
||||||
|
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,11 +24,11 @@ mod test;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
Deserialise,
|
Deserialise,
|
||||||
DStream,
|
Dstream,
|
||||||
Error,
|
Error,
|
||||||
FixedStringIter,
|
FixedStringIter,
|
||||||
Serialise,
|
Serialise,
|
||||||
SStream,
|
Sstream,
|
||||||
};
|
};
|
||||||
|
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
|
@ -53,13 +53,13 @@ impl<const N: usize> FixedString<N> {
|
||||||
///
|
///
|
||||||
/// # Errors
|
/// # 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> {
|
pub fn new(s: &str) -> Result<Self, Error> {
|
||||||
let mut buf = ['\0'; N];
|
let mut buf = ['\0'; N];
|
||||||
let len = s.chars().count();
|
let len = s.chars().count();
|
||||||
|
|
||||||
for (i, c) in s.chars().enumerate() {
|
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;
|
buf[i] = c;
|
||||||
}
|
}
|
||||||
|
@ -127,16 +127,16 @@ impl<const N: usize> Debug for FixedString<N> {
|
||||||
impl<const N: usize> Deserialise for FixedString<N> {
|
impl<const N: usize> Deserialise for FixedString<N> {
|
||||||
type Error = Error;
|
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 len = usize::try_from(u64::deserialise(stream)?).unwrap();
|
||||||
|
|
||||||
let data = stream.take(len)?;
|
let data = stream.take(len)?;
|
||||||
let s = std::str::from_utf8(data)
|
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();
|
let len = s.chars().count();
|
||||||
if len > N {
|
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];
|
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> {
|
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 s: String = self.iter().collect();
|
||||||
|
|
||||||
let len = u64::try_from(s.len()).unwrap();
|
let len = u64::try_from(s.len()).unwrap();
|
||||||
|
|
|
@ -21,8 +21,8 @@
|
||||||
|
|
||||||
//! Binary (de)serialisation.
|
//! 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.
|
//! 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.
|
||||||
//! As such, one may consider this crate to be more low-level.
|
//! 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.
|
//! 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;
|
pub(in crate) use use_mod;
|
||||||
|
|
||||||
use_mod!(pub d_stream);
|
|
||||||
use_mod!(pub deserialise);
|
use_mod!(pub deserialise);
|
||||||
|
use_mod!(pub dstream);
|
||||||
use_mod!(pub error);
|
use_mod!(pub error);
|
||||||
use_mod!(pub fixed_string);
|
use_mod!(pub fixed_string);
|
||||||
use_mod!(pub fixed_string_iter);
|
use_mod!(pub fixed_string_iter);
|
||||||
use_mod!(pub s_stream);
|
|
||||||
use_mod!(pub serialise);
|
use_mod!(pub serialise);
|
||||||
|
use_mod!(pub sstream);
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test;
|
mod test;
|
||||||
|
|
||||||
use crate::SStream;
|
use crate::Sstream;
|
||||||
|
|
||||||
use std::convert::Infallible;
|
use std::convert::Infallible;
|
||||||
use std::mem::size_of;
|
use std::mem::size_of;
|
||||||
|
@ -30,17 +30,22 @@ use std::num::NonZero;
|
||||||
|
|
||||||
/// Denotes a type capable of being serialised.
|
/// Denotes a type capable of being serialised.
|
||||||
pub trait Serialise: Sized {
|
pub trait Serialise: Sized {
|
||||||
|
/// The maximum ammount of bytes that can result from serialisation.
|
||||||
|
const SERIALISE_LIMIT: usize;
|
||||||
|
|
||||||
/// Serialises `self` into a byte stream.
|
/// Serialises `self` into a byte stream.
|
||||||
///
|
///
|
||||||
/// One may assume that the resulting stream has at most the same ammount of bytes as before serialisation.
|
/// This function should not append *more* bytes than specified in [`SERIALISE_LIMIT`](Serialise::SERIALISE_LIMIT).
|
||||||
/// Therefore, not observing this rule is a logic error.
|
/// Doing so is considered a logic error.
|
||||||
fn serialise(&self, stream: &mut SStream);
|
fn serialise(&self, stream: &mut Sstream);
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! impl_float {
|
macro_rules! impl_float {
|
||||||
($type:ty) => {
|
($type:ty) => {
|
||||||
impl Serialise for $type {
|
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())
|
stream.append(&self.to_be_bytes())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -50,13 +55,17 @@ macro_rules! impl_float {
|
||||||
macro_rules! impl_int {
|
macro_rules! impl_int {
|
||||||
($type:ty) => {
|
($type:ty) => {
|
||||||
impl Serialise for $type {
|
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())
|
stream.append(&self.to_be_bytes())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Serialise for NonZero<$type> {
|
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)
|
self.get().serialise(stream)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -67,7 +76,11 @@ impl<T0, T1> Serialise for (T0, T1)
|
||||||
where
|
where
|
||||||
T0: Serialise,
|
T0: Serialise,
|
||||||
T1: 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.0.serialise(stream);
|
||||||
self.1.serialise(stream);
|
self.1.serialise(stream);
|
||||||
}
|
}
|
||||||
|
@ -78,7 +91,12 @@ where
|
||||||
T0: Serialise,
|
T0: Serialise,
|
||||||
T1: Serialise,
|
T1: Serialise,
|
||||||
T2: 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.0.serialise(stream);
|
||||||
self.1.serialise(stream);
|
self.1.serialise(stream);
|
||||||
self.2.serialise(stream);
|
self.2.serialise(stream);
|
||||||
|
@ -91,7 +109,13 @@ where
|
||||||
T1: Serialise,
|
T1: Serialise,
|
||||||
T2: Serialise,
|
T2: Serialise,
|
||||||
T3: 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.0.serialise(stream);
|
||||||
self.1.serialise(stream);
|
self.1.serialise(stream);
|
||||||
self.2.serialise(stream);
|
self.2.serialise(stream);
|
||||||
|
@ -106,7 +130,14 @@ where
|
||||||
T2: Serialise,
|
T2: Serialise,
|
||||||
T3: Serialise,
|
T3: Serialise,
|
||||||
T4: 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.0.serialise(stream);
|
||||||
self.1.serialise(stream);
|
self.1.serialise(stream);
|
||||||
self.2.serialise(stream);
|
self.2.serialise(stream);
|
||||||
|
@ -123,7 +154,15 @@ where
|
||||||
T3: Serialise,
|
T3: Serialise,
|
||||||
T4: Serialise,
|
T4: Serialise,
|
||||||
T5: 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.0.serialise(stream);
|
||||||
self.1.serialise(stream);
|
self.1.serialise(stream);
|
||||||
self.2.serialise(stream);
|
self.2.serialise(stream);
|
||||||
|
@ -142,7 +181,16 @@ where
|
||||||
T4: Serialise,
|
T4: Serialise,
|
||||||
T5: Serialise,
|
T5: Serialise,
|
||||||
T6: 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.0.serialise(stream);
|
||||||
self.1.serialise(stream);
|
self.1.serialise(stream);
|
||||||
self.2.serialise(stream);
|
self.2.serialise(stream);
|
||||||
|
@ -163,7 +211,17 @@ where
|
||||||
T5: Serialise,
|
T5: Serialise,
|
||||||
T6: Serialise,
|
T6: Serialise,
|
||||||
T7: 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.0.serialise(stream);
|
||||||
self.1.serialise(stream);
|
self.1.serialise(stream);
|
||||||
self.2.serialise(stream);
|
self.2.serialise(stream);
|
||||||
|
@ -186,7 +244,18 @@ where
|
||||||
T6: Serialise,
|
T6: Serialise,
|
||||||
T7: Serialise,
|
T7: Serialise,
|
||||||
T8: 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.0.serialise(stream);
|
||||||
self.1.serialise(stream);
|
self.1.serialise(stream);
|
||||||
self.2.serialise(stream);
|
self.2.serialise(stream);
|
||||||
|
@ -211,7 +280,19 @@ where
|
||||||
T7: Serialise,
|
T7: Serialise,
|
||||||
T8: Serialise,
|
T8: Serialise,
|
||||||
T9: 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.0.serialise(stream);
|
||||||
self.1.serialise(stream);
|
self.1.serialise(stream);
|
||||||
self.2.serialise(stream);
|
self.2.serialise(stream);
|
||||||
|
@ -238,7 +319,20 @@ where
|
||||||
T8: Serialise,
|
T8: Serialise,
|
||||||
T9: Serialise,
|
T9: Serialise,
|
||||||
T10: 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.0.serialise(stream);
|
||||||
self.1.serialise(stream);
|
self.1.serialise(stream);
|
||||||
self.2.serialise(stream);
|
self.2.serialise(stream);
|
||||||
|
@ -267,7 +361,21 @@ where
|
||||||
T9: Serialise,
|
T9: Serialise,
|
||||||
T10: Serialise,
|
T10: Serialise,
|
||||||
T11: 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.0.serialise(stream);
|
||||||
self.1.serialise(stream);
|
self.1.serialise(stream);
|
||||||
self.2.serialise(stream);
|
self.2.serialise(stream);
|
||||||
|
@ -284,7 +392,9 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Serialise, const N: usize> Serialise for [T; N] {
|
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);
|
u64::try_from(self.len()).unwrap().serialise(stream);
|
||||||
|
|
||||||
for v in self { v.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 () {
|
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 {
|
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)
|
u8::from(*self).serialise(stream)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Serialise for char {
|
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)
|
u32::from(*self).serialise(stream)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Serialise for Infallible {
|
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> {
|
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 {
|
match *self {
|
||||||
None => {
|
None => {
|
||||||
stream.append(&[0x00]);
|
stream.append_byte(0x00);
|
||||||
stream.append(&vec![0x00; size_of::<T>()]);
|
stream.append(&vec![0x00; size_of::<T>()]);
|
||||||
},
|
},
|
||||||
|
|
||||||
Some(ref v) => {
|
Some(ref v) => {
|
||||||
stream.append(&[0x01]);
|
stream.append_byte(0x01);
|
||||||
v.serialise(stream);
|
v.serialise(stream);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -328,15 +448,23 @@ impl<T: Serialise> Serialise for Option<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Serialise, E: Serialise> Serialise for Result<T, E> {
|
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 {
|
match *self {
|
||||||
Ok(ref v) => {
|
Ok(ref v) => {
|
||||||
stream.append(&[0x00]);
|
stream.append_byte(0x00);
|
||||||
v.serialise(stream);
|
v.serialise(stream);
|
||||||
},
|
},
|
||||||
|
|
||||||
Err(ref e) => {
|
Err(ref e) => {
|
||||||
stream.append(&[0x01]);
|
stream.append_byte(0x01);
|
||||||
e.serialise(stream);
|
e.serialise(stream);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -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]
|
#[test]
|
||||||
fn test_serialise() {
|
fn test_serialise() {
|
||||||
let mut stream = SStream::new();
|
let mut stream = Sstream::new();
|
||||||
|
|
||||||
0x00_u8.serialise(&mut stream);
|
0x00_u8.serialise(&mut stream);
|
||||||
0xFF_u8.serialise(&mut stream);
|
0xFF_u8.serialise(&mut stream);
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
// er General Public License along with bzipper. If
|
// er General Public License along with bzipper. If
|
||||||
// not, see <https://www.gnu.org/licenses/>.
|
// not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
use crate::{DStream, Serialise};
|
use crate::{Dstream, Serialise};
|
||||||
|
|
||||||
use std::fmt::{Debug, Formatter};
|
use std::fmt::{Debug, Formatter};
|
||||||
use std::mem::size_of;
|
use std::mem::size_of;
|
||||||
|
@ -27,36 +27,40 @@ use std::mem::size_of;
|
||||||
/// Byte stream for serialisation.
|
/// Byte stream for serialisation.
|
||||||
///
|
///
|
||||||
/// The bytes themselves are contained by the type.
|
/// 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)]
|
#[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.
|
/// Constructs a new, empty byte stream.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub const fn new() -> Self { Self(Vec::new()) }
|
pub const fn new() -> Self { Self(Vec::new()) }
|
||||||
|
|
||||||
/// Extends the byte stream.
|
/// Extends the byte stream.
|
||||||
#[inline(always)]
|
|
||||||
pub fn append(&mut self, extra: &[u8]) {
|
pub fn append(&mut self, extra: &[u8]) {
|
||||||
self.0.extend(extra);
|
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.
|
/// The returned object references the original stream.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
#[must_use]
|
#[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)]
|
#[inline(always)]
|
||||||
fn as_ref(&self) -> &[u8] { self.0.as_ref() }
|
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 {
|
fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
|
||||||
write!(f, "[")?;
|
write!(f, "[")?;
|
||||||
|
|
||||||
|
@ -68,12 +72,12 @@ impl Debug for SStream {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for SStream {
|
impl Default for Sstream {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn default() -> Self { Self::new() }
|
fn default() -> Self { Self::new() }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Serialise> From<&T> for SStream {
|
impl<T: Serialise> From<&T> for Sstream {
|
||||||
fn from(value: &T) -> Self {
|
fn from(value: &T) -> Self {
|
||||||
let mut stream = Self(Vec::with_capacity(size_of::<T>()));
|
let mut stream = Self(Vec::with_capacity(size_of::<T>()));
|
||||||
value.serialise(&mut stream);
|
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)]
|
#[inline(always)]
|
||||||
fn from(value: SStream) -> Self { value.0.into_boxed_slice() }
|
fn from(value: Sstream) -> Self { value.0.into_boxed_slice() }
|
||||||
}
|
}
|
Loading…
Add table
Add a link
Reference in a new issue