diff options
Diffstat (limited to 'src/deserialise')
-rw-r--r-- | src/deserialise/d_stream/mod.rs | 80 | ||||
-rw-r--r-- | src/deserialise/deserialise/mod.rs | 181 | ||||
-rw-r--r-- | src/deserialise/mod.rs | 170 | ||||
-rw-r--r-- | src/deserialise/test.rs | 19 |
4 files changed, 177 insertions, 273 deletions
diff --git a/src/deserialise/d_stream/mod.rs b/src/deserialise/d_stream/mod.rs deleted file mode 100644 index 900aee3..0000000 --- a/src/deserialise/d_stream/mod.rs +++ /dev/null @@ -1,80 +0,0 @@ -// Copyright 2024 Gabriel Bjørnager Jensen. -// -// This file is part of bzipper. -// -// bzipper is free software: you can redistribute -// it and/or modify it under the terms of the GNU -// Lesser General Public License as published by -// the Free Software Foundation, either version 3 -// of the License, or (at your option) any later -// version. -// -// bzipper is distributed in the hope that it will -// be useful, but WITHOUT ANY WARRANTY; without -// even the implied warranty of MERCHANTABILITY or -// FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Less- -// er General Public License along with bzipper. If -// not, see <https://www.gnu.org/licenses/>. - -use crate::error::{Error, Result}; - -use std::fmt::{Debug, Formatter}; - -/// A byte stream for deserialisation. -/// -/// This type borrows a byte slice (hence [`new`](DStream::new)), keeping track internally of the used bytes. -#[derive(Clone)] -pub struct DStream<'a> { - data: &'a [u8], - len: usize, -} - -impl<'a> DStream<'a> { - /// Constructs a new byte stream. - pub fn new<T: AsRef<[u8]> + ?Sized>(buf: &'a T) -> Self { Self { - data: buf.as_ref(), - len: buf.as_ref().len(), - } } - - /// Takes bytes from the stream. - /// - /// # Errors - /// - /// If the internal buffer doesn't hold at least the requested 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 } ) } - - let start = self.data.len() - self.len; - let stop = start + len; - - self.len -= len; - - Ok(&self.data[start..stop]) - } -} - -impl Debug for DStream<'_> { - fn fmt(&self, f: &mut Formatter) -> std::fmt::Result { - let stop = self.data.len(); - let start = self.data.len() - self.len; - - write!(f, "[")?; - - for v in &self.data[start..stop] { write!(f, "{v:#02X},")? }; - - write!(f, "]")?; - - Ok(()) - } -} - -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> { - fn from(value: &'a [u8; N]) -> Self { Self::new(value) } -} diff --git a/src/deserialise/deserialise/mod.rs b/src/deserialise/deserialise/mod.rs deleted file mode 100644 index e345b12..0000000 --- a/src/deserialise/deserialise/mod.rs +++ /dev/null @@ -1,181 +0,0 @@ -// Copyright 2024 Gabriel Bjørnager Jensen. -// -// This file is part of bzipper. -// -// bzipper is free software: you can redistribute -// it and/or modify it under the terms of the GNU -// Lesser General Public License as published by -// the Free Software Foundation, either version 3 -// of the License, or (at your option) any later -// version. -// -// bzipper is distributed in the hope that it will -// be useful, but WITHOUT ANY WARRANTY; without -// even the implied warranty of MERCHANTABILITY or -// FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Less- -// er General Public License along with bzipper. If -// not, see <https://www.gnu.org/licenses/>. - -use crate::deserialise::DStream; -use crate::error::Error; - -use std::convert::Infallible; -use std::error::Error as StdError; -use std::mem::size_of; -use std::num::NonZero; - -/// Denotes a type capable of being deserialised. -pub trait Deserialise: Sized { - type Error; - - /// Deserialises the byte stream to an object. - fn deserialise(stream: &mut DStream) -> Result<Self, Self::Error>; -} - -macro_rules! impl_float { - ($type:ty) => { - impl Deserialise for $type { - type Error = Error; - - fn deserialise(stream: &mut DStream) -> Result<Self, Self::Error> { - let data = stream - .take(size_of::<Self>())? - .try_into() - .unwrap(); - - Ok(Self::from_be_bytes(data)) - } - } - }; -} - -macro_rules! impl_int { - ($type:ty) => { - impl Deserialise for $type { - type Error = Error; - - fn deserialise(stream: &mut DStream) -> Result<Self, Self::Error> { - let data = stream - .take(size_of::<Self>())? - .try_into() - .unwrap(); - - Ok(Self::from_be_bytes(data)) - } - } - - impl Deserialise for NonZero<$type> { - type Error = Error; - - fn deserialise(stream: &mut DStream) -> Result<Self, Self::Error> { - let value = <$type>::deserialise(stream)?; - - NonZero::new(value) - .ok_or(Error::NullInteger) - } - } - }; -} - -impl<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> { - let len = usize::try_from(u64::deserialise(stream)?).unwrap(); - if len != N { return Err(Box::new(Error::ArrayLengthMismatch { len, ok_len: N })) }; - - let mut buf = Vec::with_capacity(len); - for _ in 0x0..len { buf.push(Deserialise::deserialise(stream)?); } - - // If we had used the checked unwrap, we would also - // have to require `T: Debug`. - Ok(unsafe { buf.try_into().unwrap_unchecked() }) - } -} - -impl Deserialise for () { - type Error = Error; - - fn deserialise(_stream: &mut DStream) -> Result<Self, Self::Error> { Ok(()) } -} - -impl Deserialise for bool { - type Error = Error; - - fn deserialise(stream: &mut DStream) -> Result<Self, Self::Error> { - let value = u8::deserialise(stream)?; - - match value { - 0x00 => Ok(false), - 0x01 => Ok(true), - _ => Err(Error::InvalidBoolean { value }) - } - } -} - -impl Deserialise for char { - type Error = Error; - - fn deserialise(stream: &mut DStream) -> Result<Self, Self::Error> { - let value = u32::deserialise(stream)?; - - Self::from_u32(value) - .ok_or(Error::InvalidCodePoint { value }) - } -} - -impl Deserialise for Infallible { - type Error = Error; - - 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> { - let sign = bool::deserialise(stream)?; - - if sign { - Ok(Some(T::deserialise(stream)?)) - } else { - Ok(None) - } - } -} - -impl<T: Deserialise, E: Deserialise> Deserialise for Result<T, E> -where - <T as Deserialise>::Error: StdError + 'static, - <E as Deserialise>::Error: StdError + 'static, { - type Error = Box<dyn StdError>; - - fn deserialise(stream: &mut DStream) -> Result<Self, Self::Error> { - let sign = bool::deserialise(stream)?; - - let value = if sign { - Err(E::deserialise(stream)?) - } else { - Ok(T::deserialise(stream)?) - }; - - Ok(value) - } -} - -impl_float!(f32); -impl_float!(f64); - -impl_int!(i128); -impl_int!(i16); -impl_int!(i32); -impl_int!(i64); -impl_int!(i8); -impl_int!(u128); -impl_int!(u16); -impl_int!(u32); -impl_int!(u64); -impl_int!(u8); diff --git a/src/deserialise/mod.rs b/src/deserialise/mod.rs index cd0889a..2678670 100644 --- a/src/deserialise/mod.rs +++ b/src/deserialise/mod.rs @@ -19,11 +19,169 @@ // er General Public License along with bzipper. If // not, see <https://www.gnu.org/licenses/>. -//! Deserialisation utilities. - -use crate::use_mod; -use_mod!(pub d_stream); -use_mod!(pub deserialise); - #[cfg(test)] mod test; + +use crate::{DStream, Error}; + +use std::convert::Infallible; +use std::error::Error as StdError; +use std::mem::size_of; +use std::num::NonZero; + +/// Denotes a type capable of being deserialised. +pub trait Deserialise: Sized { + type Error; + + /// Deserialises the byte stream to an object. + /// + /// # Errors + /// + /// If deserialisation failed, e.g. by an invalid value being found, an error is returned. + fn deserialise(stream: &mut DStream) -> Result<Self, Self::Error>; +} + +macro_rules! impl_float { + ($type:ty) => { + impl Deserialise for $type { + type Error = Error; + + fn deserialise(stream: &mut DStream) -> Result<Self, Self::Error> { + let data = stream + .take(size_of::<Self>())? + .try_into() + .unwrap(); + + Ok(Self::from_be_bytes(data)) + } + } + }; +} + +macro_rules! impl_int { + ($type:ty) => { + impl Deserialise for $type { + type Error = Error; + + fn deserialise(stream: &mut DStream) -> Result<Self, Self::Error> { + let data = stream + .take(size_of::<Self>())? + .try_into() + .unwrap(); + + Ok(Self::from_be_bytes(data)) + } + } + + impl Deserialise for NonZero<$type> { + type Error = Error; + + fn deserialise(stream: &mut DStream) -> Result<Self, Self::Error> { + let value = <$type>::deserialise(stream)?; + + NonZero::new(value) + .ok_or(Error::NullInteger) + } + } + }; +} + +impl<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> { + let len = usize::try_from(u64::deserialise(stream)?).unwrap(); + if len != N { return Err(Box::new(Error::ArrayLengthMismatch { len, ok_len: N })) }; + + let mut buf = Vec::with_capacity(len); + for _ in 0x0..len { buf.push(Deserialise::deserialise(stream)?); } + + // If we had used the checked unwrap, we would also + // have to require `T: Debug`. + Ok(unsafe { buf.try_into().unwrap_unchecked() }) + } +} + +impl Deserialise for () { + type Error = Error; + + fn deserialise(_stream: &mut DStream) -> Result<Self, Self::Error> { Ok(()) } +} + +impl Deserialise for bool { + type Error = Error; + + fn deserialise(stream: &mut DStream) -> Result<Self, Self::Error> { + let value = u8::deserialise(stream)?; + + match value { + 0x00 => Ok(false), + 0x01 => Ok(true), + _ => Err(Error::InvalidBoolean { value }) + } + } +} + +impl Deserialise for char { + type Error = Error; + + fn deserialise(stream: &mut DStream) -> Result<Self, Self::Error> { + let value = u32::deserialise(stream)?; + + Self::from_u32(value) + .ok_or(Error::InvalidCodePoint { value }) + } +} + +impl Deserialise for Infallible { + type Error = Error; + + 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> { + let sign = bool::deserialise(stream)?; + + if sign { + Ok(Some(T::deserialise(stream)?)) + } else { + Ok(None) + } + } +} + +impl<T: Deserialise, E: Deserialise> Deserialise for Result<T, E> +where + <T as Deserialise>::Error: StdError + 'static, + <E as Deserialise>::Error: StdError + 'static, { + type Error = Box<dyn StdError>; + + fn deserialise(stream: &mut DStream) -> Result<Self, Self::Error> { + let sign = bool::deserialise(stream)?; + + let value = if sign { + Err(E::deserialise(stream)?) + } else { + Ok(T::deserialise(stream)?) + }; + + Ok(value) + } +} + +impl_float!(f32); +impl_float!(f64); + +impl_int!(i128); +impl_int!(i16); +impl_int!(i32); +impl_int!(i64); +impl_int!(i8); +impl_int!(u128); +impl_int!(u16); +impl_int!(u32); +impl_int!(u64); +impl_int!(u8); diff --git a/src/deserialise/test.rs b/src/deserialise/test.rs index fb95cc6..394ed64 100644 --- a/src/deserialise/test.rs +++ b/src/deserialise/test.rs @@ -19,18 +19,20 @@ // er General Public License along with bzipper. If // not, see <https://www.gnu.org/licenses/>. -use crate::deserialise::{Deserialise, DStream}; +use crate::{Deserialise, DStream, FixedString}; #[test] -fn test_serialise() { +fn test_deserialise() { let data = [ 0x00, 0xFF, 0xFF, 0x0F, 0xEF, 0x1F, 0xDF, 0x2F, 0xCF, 0x3F, 0xBF, 0x4F, 0xAF, 0x5F, 0x9F, 0x6F, 0x8F, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x05, 0x00, 0x00, 0x03, 0xBB, 0x00, 0x00, - 0x03, 0x91, 0x00, 0x00, 0x03, 0xBC, 0x00, 0x00, - 0x03, 0x94, 0x00, 0x00, 0x03, 0xB1, 0x01, 0x00, - 0x00, 0x01, 0x80, + 0x00, 0x09, 0x6D, 0xC3, 0xA1, 0x6E, 0x61, 0xC3, + 0xB0, 0x75, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x05, 0x00, 0x00, 0x03, 0xBB, 0x00, + 0x00, 0x03, 0x91, 0x00, 0x00, 0x03, 0xBC, 0x00, + 0x00, 0x03, 0x94, 0x00, 0x00, 0x03, 0xB1, 0x01, + 0x00, 0x00, 0x01, 0x80, ]; let mut stream = DStream::from(&data); @@ -50,6 +52,11 @@ fn test_serialise() { ); assert_eq!( + FixedString::<0x10>::deserialise(&mut stream).unwrap(), + "m\u{00E1}na\u{00F0}ur", + ); + + assert_eq!( <[char; 0x5]>::deserialise(&mut stream).unwrap(), ['\u{03BB}', '\u{0391}', '\u{03BC}', '\u{0394}', '\u{03B1}'], ); |