diff --git a/Cargo.toml b/Cargo.toml index d1d1bc5..71cdb39 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "byte_lamination" -version = "0.1.0" +version = "0.1.1" edition = "2021" authors = ["Olivier 'reivilibre'"] repository = "https://git.emunest.net/reivilibre/byte_lamination.git" diff --git a/src/compression/zstd.rs b/src/compression/zstd.rs index 5847b80..e01fb35 100644 --- a/src/compression/zstd.rs +++ b/src/compression/zstd.rs @@ -4,6 +4,8 @@ use std::error::Error; use std::marker::PhantomData; use crate::{AutoDelaminate, AutoLaminate, ByteLamination}; +/// Wrapper that performs Zstd (de)compression on the bytes. +#[derive(Clone, Debug, Ord, PartialOrd, Eq, PartialEq, Hash)] pub struct Zstd<'a, T> { bytes: Cow<'a, [u8]>, _marker: PhantomData, @@ -24,7 +26,19 @@ impl<'a, T> Into> for Zstd<'a, T> { } } -impl<'a, T> ByteLamination<'a> for Zstd<'a, T> {} +impl<'a, T> ByteLamination<'a> for Zstd<'a, T> { + fn as_cow_bytes(&self) -> Cow<'_, [u8]> { + Cow::Borrowed(&self.bytes) + } + + fn into_bytes(self) -> Vec { + todo!() + } + + fn try_from_bytes(bytes: Cow<'a, [u8]>) -> Result> { + Ok(Self::from(bytes)) + } +} /// Default Zstd compression level used for the AutoLaminate helper. pub const DEFAULT_ZSTD_LEVEL: i32 = 12; @@ -50,9 +64,10 @@ impl<'a, T> Zstd<'a, T> { } -impl<'a, T: AutoLaminate + ByteLamination<'a>, U> AutoLaminate for Zstd<'a, T> { +impl<'a, T: AutoLaminate + ByteLamination<'a> + 'a, U> AutoLaminate for Zstd<'a, T> { fn laminate(item: U) -> Result> { - let bytes: Cow<'a, [u8]> = T::laminate(item)?.into(); + let lamination = T::laminate(item)?; + let bytes: Cow<'_, [u8]> = lamination.as_cow_bytes(); Zstd::compress(&bytes, DEFAULT_ZSTD_LEVEL) } } @@ -61,6 +76,6 @@ impl<'a, T: AutoDelaminate + ByteLamination<'a>, U> AutoDelaminate for Zst fn delaminate(self) -> Result> { let memory_limit = max(DEFAULT_MEMORY_LIMIT_MINIMUM, DEFAULT_MEMORY_LIMIT_MULTIPLIER * self.bytes.len()); let bytes = self.decompress(memory_limit)?; - T::from(Cow::Owned(bytes)).delaminate() + T::try_from_bytes(Cow::Owned(bytes))?.delaminate() } } diff --git a/src/lib.rs b/src/lib.rs index 7bf9fc9..6cb1304 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -16,6 +16,7 @@ use std::borrow::Cow; use std::error::Error; +pub mod raw; pub mod compression; pub mod serialisation; @@ -42,6 +43,12 @@ pub trait AutoDelaminateBorrowed<'a, T> { } -pub trait ByteLamination<'a>: From> + Into> { +pub trait ByteLamination<'a>: Sized { + /// Get the raw bytes from this lamination. + /// If possible, this should return borrowed bytes. + fn as_cow_bytes(&self) -> Cow<'_, [u8]>; + fn into_bytes(self) -> Vec; + + fn try_from_bytes(bytes: Cow<'a, [u8]>) -> Result>; } diff --git a/src/raw.rs b/src/raw.rs new file mode 100644 index 0000000..1d7d000 --- /dev/null +++ b/src/raw.rs @@ -0,0 +1,73 @@ +use std::borrow::Cow; +use std::error::Error; +use crate::ByteLamination; + +impl<'a> ByteLamination<'a> for Cow<'a, [u8]> { + fn as_cow_bytes(&self) -> Cow<'_, [u8]> { + Cow::Borrowed(self.as_ref()) + } + + fn into_bytes(self) -> Vec { + todo!() + } + + fn try_from_bytes(bytes: Cow<'a, [u8]>) -> Result> { + Ok(bytes) + } +} + +impl<'a> ByteLamination<'a> for Vec { + fn as_cow_bytes(&self) -> Cow<'_, [u8]> { + Cow::Borrowed(self.as_ref()) + } + + fn into_bytes(self) -> Vec { + todo!() + } + + fn try_from_bytes(bytes: Cow<'a, [u8]>) -> Result> { + Ok(bytes.into_owned()) + } +} + +impl<'a> ByteLamination<'a> for String { + fn as_cow_bytes(&self) -> Cow<'_, [u8]> { + Cow::Borrowed(self.as_bytes()) + } + + fn into_bytes(self) -> Vec { + todo!() + } + + fn try_from_bytes(bytes: Cow<'a, [u8]>) -> Result> { + Ok(match bytes { + Cow::Borrowed(bslice) => { + std::str::from_utf8(bslice)?.to_owned() + } + Cow::Owned(bvec) => { + String::from_utf8(bvec)? + } + }) + } +} + +impl<'a> ByteLamination<'a> for Cow<'a, str> { + fn as_cow_bytes(&self) -> Cow<'_, [u8]> { + Cow::Borrowed(self.as_bytes()) + } + + fn into_bytes(self) -> Vec { + todo!() + } + + fn try_from_bytes(bytes: Cow<'a, [u8]>) -> Result> { + Ok(match bytes { + Cow::Borrowed(bslice) => { + Cow::Borrowed(std::str::from_utf8(bslice)?) + } + Cow::Owned(bvec) => { + Cow::Owned(String::from_utf8(bvec)?) + } + }) + } +} \ No newline at end of file diff --git a/src/serialisation/bare.rs b/src/serialisation/bare.rs index 91fc97a..f4b5a26 100644 --- a/src/serialisation/bare.rs +++ b/src/serialisation/bare.rs @@ -6,6 +6,7 @@ use serde::de::DeserializeOwned; use crate::{AutoDelaminate, AutoLaminate, ByteLamination}; /// Wrapper that uses serde to perform BARE serialisation on an arbitrary type. +#[derive(Clone, Debug, Ord, PartialOrd, Eq, PartialEq, Hash)] pub struct SerdeBare<'a, T> { bytes: Cow<'a, [u8]>, _marker: PhantomData, @@ -26,7 +27,19 @@ impl<'a, T> Into> for SerdeBare<'a, T> { } } -impl<'a, T> ByteLamination<'a> for SerdeBare<'a, T> {} +impl<'a, T> ByteLamination<'a> for SerdeBare<'a, T> { + fn as_cow_bytes(&self) -> Cow<'_, [u8]> { + Cow::Borrowed(&self.bytes) + } + + fn into_bytes(self) -> Vec { + todo!() + } + + fn try_from_bytes(bytes: Cow<'a, [u8]>) -> Result> { + Ok(Self::from(bytes)) + } +} impl<'a, T: Serialize> SerdeBare<'a, T> { pub fn serialise<'inp>(inner: &'inp T) -> Result> { diff --git a/src/serialisation/cbor.rs b/src/serialisation/cbor.rs index e3c0525..ff78b7d 100644 --- a/src/serialisation/cbor.rs +++ b/src/serialisation/cbor.rs @@ -6,6 +6,7 @@ use serde::de::DeserializeOwned; use crate::{AutoDelaminate, AutoDelaminateBorrowed, AutoLaminate, ByteLamination}; /// Wrapper that uses serde to perform CBOR serialisation on an arbitrary type. +#[derive(Clone, Debug, Ord, PartialOrd, Eq, PartialEq, Hash)] pub struct SerdeCbor<'a, T> { bytes: Cow<'a, [u8]>, _marker: PhantomData, @@ -26,7 +27,19 @@ impl<'a, T> Into> for SerdeCbor<'a, T> { } } -impl<'a, T> ByteLamination<'a> for SerdeCbor<'a, T> {} +impl<'a, T> ByteLamination<'a> for SerdeCbor<'a, T> { + fn as_cow_bytes(&self) -> Cow<'_, [u8]> { + Cow::Borrowed(&self.bytes) + } + + fn into_bytes(self) -> Vec { + todo!() + } + + fn try_from_bytes(bytes: Cow<'a, [u8]>) -> Result> { + Ok(Self::from(bytes)) + } +} impl<'a, T: Serialize> SerdeCbor<'a, T> { pub fn serialise<'inp>(inner: &'inp T) -> Result> {