diff options
| author | zirkonya <zirkonya@iridium.lan> | 2026-07-26 22:22:32 +0200 |
|---|---|---|
| committer | zirkonya <zirkonya@iridium.lan> | 2026-07-26 22:22:32 +0200 |
| commit | da20363883b00aaf56b6ba068465d3e9bdf9fedf (patch) | |
| tree | 792c6d0692392baf5ac380bafd7ea4a66b3346b6 /src | |
| parent | 08c8e9d37f3e0f9a82c3792c1927967631de73cd (diff) | |
Add some prefixe
Diffstat (limited to 'src')
| -rw-r--r-- | src/codec.rs | 1 | ||||
| -rw-r--r-- | src/codec/decode.rs | 88 | ||||
| -rw-r--r-- | src/codec/encode.rs | 55 | ||||
| -rw-r--r-- | src/codec/error.rs | 22 | ||||
| -rw-r--r-- | src/lib.rs | 2 | ||||
| -rw-r--r-- | src/types.rs (renamed from src/types/mod.rs) | 1 | ||||
| -rw-r--r-- | src/types/prefix.rs | 10 | ||||
| -rw-r--r-- | src/types/prefix/count.rs | 92 | ||||
| -rw-r--r-- | src/types/prefix/length.rs | 79 | ||||
| -rw-r--r-- | src/types/size.rs | 30 |
10 files changed, 367 insertions, 13 deletions
diff --git a/src/codec.rs b/src/codec.rs index f11a88e..fcb18a3 100644 --- a/src/codec.rs +++ b/src/codec.rs @@ -2,6 +2,7 @@ use crate::codec::{decode::Decode, encode::Encode}; pub mod decode; pub mod encode; +pub mod error; pub trait Codec: Encode + Decode {} impl<T> Codec for T where T: Encode + Decode {} diff --git a/src/codec/decode.rs b/src/codec/decode.rs index 65f08b5..1059811 100644 --- a/src/codec/decode.rs +++ b/src/codec/decode.rs @@ -1,7 +1,91 @@ -use std::io::{self, Read}; +use std::{io::Read, sync::Arc}; + +use crate::DEFAULT_BUFFER_LEN; + +macro_rules! impl_decode { + ($type: ty) => { + impl Decode for $type { + fn decode(reader: &mut dyn Read) -> crate::codec::error::Result<Self> + where + Self: Sized, + { + const BYTES: usize = (<$type>::BITS / 8) as usize; + let mut bytes = [0; BYTES]; + reader.read_exact(&mut bytes)?; + Ok(<$type>::from_be_bytes(bytes)) + } + } + }; +} pub trait Decode { - fn decode(reader: &impl Read) -> io::Result<Self> + fn decode(reader: &mut dyn Read) -> crate::codec::error::Result<Self> where Self: Sized; } + +impl Decode for bool { + fn decode(reader: &mut dyn Read) -> crate::codec::error::Result<Self> + where + Self: Sized, + { + let mut byte = [0_u8]; + reader.read_exact(&mut byte)?; + Ok(byte[0] != 0) + } +} + +impl Decode for Arc<[u8]> { + fn decode(reader: &mut dyn Read) -> crate::codec::error::Result<Self> { + let mut buf = Vec::with_capacity(DEFAULT_BUFFER_LEN); + reader.read_to_end(&mut buf)?; + Ok(Arc::<[u8]>::from(buf.into_boxed_slice())) + } +} + +impl<const S: usize> Decode for [u8; S] { + fn decode(reader: &mut dyn Read) -> crate::codec::error::Result<Self> + where + Self: Sized, + { + let mut slice = [0_u8; S]; + reader.read_exact(&mut slice)?; + Ok(slice) + } +} + +impl_decode!(u8); +impl_decode!(u16); +impl_decode!(u32); +impl_decode!(u64); +impl_decode!(u128); +impl_decode!(usize); + +impl_decode!(i8); +impl_decode!(i16); +impl_decode!(i32); +impl_decode!(i64); +impl_decode!(i128); +impl_decode!(isize); + +impl Decode for f64 { + fn decode(reader: &mut dyn Read) -> crate::codec::error::Result<Self> + where + Self: Sized, + { + let bits = u64::decode(reader)?; + let value = f64::from_bits(bits); + Ok(value) + } +} + +impl Decode for f32 { + fn decode(reader: &mut dyn Read) -> crate::codec::error::Result<Self> + where + Self: Sized, + { + let bits = u32::decode(reader)?; + let value = f32::from_bits(bits); + Ok(value) + } +} diff --git a/src/codec/encode.rs b/src/codec/encode.rs index f23913b..a40f551 100644 --- a/src/codec/encode.rs +++ b/src/codec/encode.rs @@ -1,6 +1,55 @@ -use std::io::{self, Write}; +use crate::codec::error::Error; +use std::{io::Write, sync::Arc}; + +macro_rules! impl_encode { + ($t: ty) => { + impl Encode for $t { + fn encode(self, buffer: &mut dyn Write) -> Result<usize, Error> { + let size = buffer.write(&self.to_be_bytes())?; + Ok(size) + } + } + }; +} pub trait Encode { - fn encode(&self, write: &mut dyn Write) -> io::Result<usize>; - fn encoded_size(&self) -> Option<usize>; + fn encode(self, buffer: &mut dyn Write) -> Result<usize, Error>; +} + +impl Encode for bool { + fn encode(self, buffer: &mut dyn Write) -> Result<usize, Error> { + let size = buffer.write(&[self as u8])?; + Ok(size) + } +} + +impl Encode for Arc<[u8]> { + fn encode(self, buffer: &mut dyn Write) -> Result<usize, Error> { + let len = buffer.write(&self)?; + Ok(len) + } } + +impl<const S: usize> Encode for [u8; S] { + fn encode(self, buffer: &mut dyn Write) -> Result<usize, Error> { + let len = buffer.write(&self)?; + Ok(len) + } +} + +impl_encode!(u8); +impl_encode!(u16); +impl_encode!(u32); +impl_encode!(u64); +impl_encode!(u128); +impl_encode!(usize); + +impl_encode!(i8); +impl_encode!(i16); +impl_encode!(i32); +impl_encode!(i64); +impl_encode!(i128); +impl_encode!(isize); + +impl_encode!(f32); +impl_encode!(f64); diff --git a/src/codec/error.rs b/src/codec/error.rs new file mode 100644 index 0000000..6639c98 --- /dev/null +++ b/src/codec/error.rs @@ -0,0 +1,22 @@ +use std::fmt::Display; + +#[derive(Debug)] +pub enum Error { + IoError(std::io::Error), +} + +impl std::error::Error for Error {} + +impl Display for Error { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{self:?}") + } +} + +pub type Result<T> = core::result::Result<T, Error>; + +impl From<std::io::Error> for Error { + fn from(value: std::io::Error) -> Self { + Self::IoError(value) + } +} @@ -1,2 +1,4 @@ pub mod codec; pub mod types; + +pub(crate) const DEFAULT_BUFFER_LEN: usize = 2048; diff --git a/src/types/mod.rs b/src/types.rs index 5a68507..b1575b5 100644 --- a/src/types/mod.rs +++ b/src/types.rs @@ -1 +1,2 @@ pub mod prefix; +pub mod size; diff --git a/src/types/prefix.rs b/src/types/prefix.rs index e60c23b..67cf047 100644 --- a/src/types/prefix.rs +++ b/src/types/prefix.rs @@ -1,8 +1,2 @@ -use std::marker::PhantomData; - -use crate::codec::Codec; - -pub struct LenPrefixed<L: Codec, D: Codec> { - data: D, - _len: PhantomData<L>, -} +pub mod count; +pub mod length; diff --git a/src/types/prefix/count.rs b/src/types/prefix/count.rs new file mode 100644 index 0000000..7495660 --- /dev/null +++ b/src/types/prefix/count.rs @@ -0,0 +1,92 @@ +use std::{io::Read, marker::PhantomData}; + +use crate::{ + codec::{Codec, decode::Decode, encode::Encode}, + types::size::Size, +}; + +pub struct CountPrefix<I: Codec, L: Codec + Size, D: IntoIterator<Item = I>> { + data: D, + _len: PhantomData<L>, +} + +impl<I, L, D> CountPrefix<I, L, D> +where + I: Codec, + L: Codec + Size, + D: IntoIterator<Item = I>, +{ + pub fn new(data: D) -> Self { + Self { + data, + _len: PhantomData, + } + } +} + +impl<I, L, D> AsRef<D> for CountPrefix<I, L, D> +where + I: Codec, + L: Codec + Size, + D: IntoIterator<Item = I>, +{ + fn as_ref(&self) -> &D { + &self.data + } +} + +impl<I, L, D> AsMut<D> for CountPrefix<I, L, D> +where + I: Codec, + L: Codec + Size, + D: IntoIterator<Item = I>, +{ + fn as_mut(&mut self) -> &mut D { + &mut self.data + } +} + +impl<I, L, D> Encode for CountPrefix<I, L, D> +where + I: Codec, + L: Codec + Size, + D: IntoIterator<Item = I>, +{ + fn encode( + self, + buffer: &mut dyn std::io::prelude::Write, + ) -> Result<usize, crate::codec::error::Error> + where + Self: Sized, + { + let vec = self.data.into_iter().collect::<Vec<I>>(); + let mut l = L::from_size(vec.len()).encode(buffer)?; + for item in vec { + l += item.encode(buffer)?; + } + Ok(l) + } +} + +impl<I, L, D> Decode for CountPrefix<I, L, D> +where + I: Codec, + L: Codec + Size, + D: IntoIterator<Item = I> + FromIterator<I>, +{ + fn decode(reader: &mut dyn Read) -> crate::codec::error::Result<Self> + where + Self: Sized, + { + let len = L::decode(reader)?.as_size(); + let mut data = Vec::with_capacity(len); + for _ in 0..len { + let item = I::decode(reader)?; + data.push(item); + } + Ok(Self { + data: D::from_iter(data.into_iter()), + _len: PhantomData, + }) + } +} diff --git a/src/types/prefix/length.rs b/src/types/prefix/length.rs new file mode 100644 index 0000000..c825375 --- /dev/null +++ b/src/types/prefix/length.rs @@ -0,0 +1,79 @@ +use std::{io::Write, marker::PhantomData}; + +use crate::{ + DEFAULT_BUFFER_LEN, + codec::{self, Codec, decode::Decode, encode::Encode}, + types::size::Size, +}; + +pub struct LenPrefixed<L: Codec + Size, D: Codec> { + data: D, + _len: PhantomData<L>, +} + +impl<L, D> LenPrefixed<L, D> +where + L: Codec + Size, + D: Codec, +{ + pub fn new(data: D) -> Self { + Self { + data, + _len: PhantomData, + } + } +} + +impl<L, D> AsRef<D> for LenPrefixed<L, D> +where + L: Codec + Size, + D: Codec, +{ + fn as_ref(&self) -> &D { + &self.data + } +} + +impl<L, D> AsMut<D> for LenPrefixed<L, D> +where + L: Codec + Size, + D: Codec, +{ + fn as_mut(&mut self) -> &mut D { + &mut self.data + } +} + +impl<L, D> Encode for LenPrefixed<L, D> +where + L: Codec + Size, + D: Codec, +{ + fn encode(self, writer: &mut dyn Write) -> Result<usize, codec::error::Error> { + let mut buf = Vec::with_capacity(DEFAULT_BUFFER_LEN); + self.data.encode(&mut buf)?; + let mut l = L::from_size(buf.len()).encode(writer)?; + l += writer.write(&buf)?; + Ok(l) + } +} + +impl<L, D> Decode for LenPrefixed<L, D> +where + L: Codec + Size, + D: Codec, +{ + fn decode(reader: &mut dyn std::io::prelude::Read) -> crate::codec::error::Result<Self> + where + Self: Sized, + { + let len = L::decode(reader)?.as_size(); + let mut limited = vec![0_u8; len]; + reader.read_exact(&mut limited)?; + let data = D::decode(&mut &limited[..])?; + Ok(Self { + data, + _len: PhantomData, + }) + } +} diff --git a/src/types/size.rs b/src/types/size.rs new file mode 100644 index 0000000..6bce689 --- /dev/null +++ b/src/types/size.rs @@ -0,0 +1,30 @@ +macro_rules! impl_size { + ($t: ty) => { + impl Size for $t { + fn from_size(size: usize) -> Self { + size as $t + } + + fn as_size(self) -> usize { + self as usize + } + } + }; +} + +pub trait Size { + fn from_size(size: usize) -> Self; + fn as_size(self) -> usize; +} + +impl_size!(u8); +impl_size!(u16); +impl_size!(u32); +impl_size!(u64); +impl_size!(u128); + +impl_size!(i8); +impl_size!(i16); +impl_size!(i32); +impl_size!(i64); +impl_size!(i128); |
