summaryrefslogtreecommitdiff
path: root/src/codec/decode.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/codec/decode.rs')
-rw-r--r--src/codec/decode.rs251
1 files changed, 131 insertions, 120 deletions
diff --git a/src/codec/decode.rs b/src/codec/decode.rs
index 529c448..d068760 100644
--- a/src/codec/decode.rs
+++ b/src/codec/decode.rs
@@ -1,150 +1,133 @@
-//! Decoding: reading protocol values from a byte stream.
use std::{
collections::{BTreeMap, BTreeSet, BinaryHeap, HashMap, HashSet},
hash::Hash,
- io::Read,
sync::Arc,
};
-use crate::{DEFAULT_BUFFER_LEN, codec::error::Result};
-use crate::{codec::error::CodecError, context::Context};
+use crate::{codec::error::Result, codec::error::CodecError, context::Context};
macro_rules! impl_decode {
- (u8) => {
- impl<Data> Decode<Data> for u8 {
- fn decode(reader: &mut dyn Read, _: &Context<Data>) -> Result<Self>
+ ($t:ty) => {
+ impl<Data> Decode<Data> for $t {
+ fn decode(buf: &mut &[u8], _: &Context<Data>) -> Result<Self>
where
Self: Sized,
{
- let mut byte = [0u8; 1];
- reader.read_exact(&mut byte)?;
- Ok(byte[0])
+ const BYTES: usize = std::mem::size_of::<$t>();
+ if buf.len() < BYTES {
+ return Err(CodecError::IoError(std::io::Error::new(
+ std::io::ErrorKind::UnexpectedEof,
+ "insufficient bytes",
+ )));
+ }
+ let (bytes, rest) = buf.split_at(BYTES);
+ *buf = rest;
+ Ok(<$t>::from_be_bytes(bytes.try_into().unwrap()))
}
- fn decode_slice(reader: &mut dyn Read, _: &Context<Data>) -> Result<Vec<Self>>
+ fn decode_slice(buf: &mut &[u8], _: &Context<Data>) -> Result<Vec<Self>>
where
Self: Sized,
{
- let mut buf = Vec::new();
- reader.read_to_end(&mut buf)?;
- Ok(buf)
+ const BYTES: usize = std::mem::size_of::<$t>();
+ let count = buf.len() / BYTES;
+ let mut vec = Vec::with_capacity(count);
+ for _ in 0..count {
+ let (bytes, rest) = buf.split_at(BYTES);
+ *buf = rest;
+ vec.push(<$t>::from_be_bytes(bytes.try_into().unwrap()));
+ }
+ Ok(vec)
}
}
};
- ($type: ty) => {
- impl<Data> Decode<Data> for $type {
- // decode number using big endian
- fn decode(reader: &mut dyn Read, _: &Context<Data>) -> 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))
- }
+}
- fn decode_slice(reader: &mut dyn Read, _: &Context<Data>) -> Result<Vec<Self>>
+macro_rules! impl_decode_tuples {
+ ($($generic: ident),+) => {
+ impl<Data, $($generic),+> Decode<Data> for ($($generic,)+)
+ where
+ $($generic: Decode<Data>),+
+ {
+ #[allow(non_snake_case)]
+ fn decode(buf: &mut &[u8], ctx: &Context<Data>) -> Result<Self>
where
Self: Sized,
{
- let mut buf = Vec::with_capacity(DEFAULT_BUFFER_LEN);
- reader.read_to_end(&mut buf);
- const BYTES: usize = <$type>::BITS as usize / 8;
- Ok(buf
- .chunks(BYTES)
- .map(|slice| {
- let Some(bytes): Option<&[u8; BYTES]> = slice.as_array() else {
- unreachable!()
- };
- <$type>::from_be_bytes(*bytes)
- })
- .collect())
+ $(
+ let $generic = $generic::decode(buf, ctx)?;
+ )+
+ Ok(($($generic,)+))
}
}
};
}
-macro_rules! impl_decode_tuples {
- ($($generic: ident),+) => {
- impl<Data, $($generic),+> Decode<Data> for ($($generic,)+) where $($generic: Decode<Data>,)+ {
- #[allow(non_snake_case)]
- fn decode(reader: &mut dyn Read, ctx: &Context<Data>) -> Result<Self>
- where
- Self: Sized {
- $(
- let $generic = $generic::decode(reader, ctx)?;
- )+
- Ok(($($generic,)+))
- }
- }
- };
-}
-
-/// Read a value from a byte stream
+/// Zero-copy decoding: reads directly from a byte slice
pub trait Decode<Data> {
- fn decode(reader: &mut dyn Read, ctx: &Context<Data>) -> Result<Self>
+ fn decode(buf: &mut &[u8], ctx: &Context<Data>) -> Result<Self>
where
Self: Sized;
- // TODO : change for anything else than Vec
- /// assume reader contains only the slice to decode
- fn decode_slice(reader: &mut dyn Read, ctx: &Context<Data>) -> Result<Vec<Self>>
+ fn decode_slice(buf: &mut &[u8], ctx: &Context<Data>) -> Result<Vec<Self>>
where
Self: Sized,
{
- let mut buf = Vec::new();
- loop {
- match Self::decode(reader, ctx) {
- Ok(value) => buf.push(value),
+ let mut vec = Vec::new();
+ while !buf.is_empty() {
+ match Self::decode(buf, ctx) {
+ Ok(value) => vec.push(value),
Err(CodecError::IoError(err))
- if let std::io::ErrorKind::UnexpectedEof = err.kind() =>
+ if err.kind() == std::io::ErrorKind::UnexpectedEof =>
{
- return Ok(buf);
+ return Ok(vec);
}
Err(err) => return Err(err),
}
}
+ Ok(vec)
}
}
-// ~ Decode arrays
+// ── Decode arrays ───────────────────────────────────────────────────────
impl<Data, T: Decode<Data>> Decode<Data> for Vec<T> {
- fn decode(reader: &mut dyn Read, ctx: &Context<Data>) -> Result<Self>
+ fn decode(buf: &mut &[u8], ctx: &Context<Data>) -> Result<Self>
where
Self: Sized,
{
- let len = usize::decode(reader, ctx)?;
+ let len = usize::decode(buf, ctx)?;
let mut vec = Vec::with_capacity(len);
for _ in 0..len {
- vec.push(T::decode(reader, ctx)?);
+ vec.push(T::decode(buf, ctx)?);
}
Ok(vec)
}
}
impl<Data, T: Decode<Data>> Decode<Data> for Option<T> {
- /// Assume is always some
- fn decode(reader: &mut dyn Read, ctx: &Context<Data>) -> Result<Self>
+ fn decode(buf: &mut &[u8], ctx: &Context<Data>) -> Result<Self>
where
Self: Sized,
{
- T::decode(reader, ctx).map(Some)
+ if buf.is_empty() {
+ return Ok(None);
+ }
+ T::decode(buf, ctx).map(Some)
}
}
-// ~ Decode slices
+// ── Decode slices ───────────────────────────────────────────────────────
impl<Data, T, const S: usize> Decode<Data> for [T; S]
where
T: Decode<Data> + Default + Copy,
{
- fn decode(reader: &mut dyn Read, ctx: &Context<Data>) -> Result<Self>
+ fn decode(buf: &mut &[u8], ctx: &Context<Data>) -> Result<Self>
where
Self: Sized,
{
- let slice = T::decode_slice(reader, ctx)?;
+ let slice = T::decode_slice(buf, ctx)?;
let got = slice.len();
slice
.as_array()
@@ -157,7 +140,7 @@ impl<Data, T> Decode<Data> for &[T]
where
T: Decode<Data> + Default + Copy,
{
- fn decode(_: &mut dyn Read, _: &Context<Data>) -> Result<Self>
+ fn decode(_: &mut &[u8], _: &Context<Data>) -> Result<Self>
where
Self: Sized,
{
@@ -165,18 +148,22 @@ where
}
}
-// ~ Decode set
+// ── Decode set ──────────────────────────────────────────────────────────
impl<Data, T> Decode<Data> for HashSet<T>
where
T: Decode<Data> + Eq + Hash,
{
- fn decode(reader: &mut dyn Read, ctx: &Context<Data>) -> Result<Self>
+ fn decode(buf: &mut &[u8], ctx: &Context<Data>) -> Result<Self>
where
Self: Sized,
{
- let slice = T::decode_slice(reader, ctx)?;
- Ok(slice.into_iter().collect())
+ let len = usize::decode(buf, ctx)?;
+ let mut set = HashSet::with_capacity(len);
+ for _ in 0..len {
+ set.insert(T::decode(buf, ctx)?);
+ }
+ Ok(set)
}
}
@@ -184,43 +171,57 @@ impl<Data, T> Decode<Data> for BTreeSet<T>
where
T: Decode<Data> + Ord,
{
- fn decode(reader: &mut dyn Read, ctx: &Context<Data>) -> Result<Self>
+ fn decode(buf: &mut &[u8], ctx: &Context<Data>) -> Result<Self>
where
Self: Sized,
{
- let slice = T::decode_slice(reader, ctx)?;
- Ok(slice.into_iter().collect())
+ let len = usize::decode(buf, ctx)?;
+ let mut set = BTreeSet::new();
+ for _ in 0..len {
+ set.insert(T::decode(buf, ctx)?);
+ }
+ Ok(set)
}
}
-// ~ Decode misc
+// ── Decode misc ─────────────────────────────────────────────────────────
impl<Data, T> Decode<Data> for BinaryHeap<T>
where
T: Decode<Data> + Ord,
{
- fn decode(reader: &mut dyn Read, ctx: &Context<Data>) -> Result<Self>
+ fn decode(buf: &mut &[u8], ctx: &Context<Data>) -> Result<Self>
where
Self: Sized,
{
- let slice = T::decode_slice(reader, ctx)?;
- Ok(BinaryHeap::from_iter(slice))
+ let len = usize::decode(buf, ctx)?;
+ let mut heap = BinaryHeap::with_capacity(len);
+ for _ in 0..len {
+ heap.push(T::decode(buf, ctx)?);
+ }
+ Ok(heap)
}
}
-// ~ Decode maps
+// ── Decode maps ─────────────────────────────────────────────────────────
impl<Data, K, V> Decode<Data> for HashMap<K, V>
where
K: Decode<Data> + Eq + Hash,
V: Decode<Data>,
{
- fn decode(reader: &mut dyn Read, ctx: &Context<Data>) -> Result<Self>
+ fn decode(buf: &mut &[u8], ctx: &Context<Data>) -> Result<Self>
where
Self: Sized,
{
- let slice = <(K, V) as Decode<Data>>::decode_slice(reader, ctx)?;
- Ok(slice.into_iter().collect())
+ let len = usize::decode(buf, ctx)?;
+ let mut map = HashMap::with_capacity(len);
+ for _ in 0..len {
+ let key = K::decode(buf, ctx)?;
+ let val = V::decode(buf, ctx)?;
+ map.insert(key, val);
+ }
+ Ok(map)
}
}
@@ -229,19 +230,25 @@ where
K: Decode<Data> + Ord,
V: Decode<Data>,
{
- fn decode(reader: &mut dyn Read, ctx: &Context<Data>) -> Result<Self>
+ fn decode(buf: &mut &[u8], ctx: &Context<Data>) -> Result<Self>
where
Self: Sized,
{
- let slice = <(K, V) as Decode<Data>>::decode_slice(reader, ctx)?;
- Ok(slice.into_iter().collect())
+ let len = usize::decode(buf, ctx)?;
+ let mut map = BTreeMap::new();
+ for _ in 0..len {
+ let key = K::decode(buf, ctx)?;
+ let val = V::decode(buf, ctx)?;
+ map.insert(key, val);
+ }
+ Ok(map)
}
}
-// ~ Decode string
+// ── Decode string - requires length prefix ──────────────────────────────
impl<Data> Decode<Data> for &str {
- fn decode(_: &mut dyn Read, _: &Context<Data>) -> Result<Self>
+ fn decode(_: &mut &[u8], _: &Context<Data>) -> Result<Self>
where
Self: Sized,
{
@@ -250,17 +257,17 @@ impl<Data> Decode<Data> for &str {
}
impl<Data> Decode<Data> for String {
- fn decode(reader: &mut dyn Read, _: &Context<Data>) -> Result<Self>
+ fn decode(buf: &mut &[u8], ctx: &Context<Data>) -> Result<Self>
where
Self: Sized,
{
- let mut bytes: Vec<u8> = Vec::new();
- reader.read_to_end(&mut bytes)?;
- Ok(String::from_utf8_lossy(&bytes).to_string())
+ // String must be length-prefixed - decode as LenPrefixed<u16, String>
+ crate::types::prefix::length::LenPrefixed::<u16, String>::decode(buf, ctx)
+ .map(|p| p.data().clone())
}
}
-// ~ Decode primitive
+// ── Decode primitive ────────────────────────────────────────────────────
impl_decode!(u8);
impl_decode!(u16);
@@ -277,39 +284,43 @@ impl_decode!(i128);
impl_decode!(isize);
impl<Data> Decode<Data> for f64 {
- fn decode(reader: &mut dyn Read, ctx: &Context<Data>) -> Result<Self>
+ fn decode(buf: &mut &[u8], ctx: &Context<Data>) -> Result<Self>
where
Self: Sized,
{
- let bits = u64::decode(reader, ctx)?;
- let value = f64::from_bits(bits);
- Ok(value)
+ let bits = u64::decode(buf, ctx)?;
+ Ok(f64::from_bits(bits))
}
}
impl<Data> Decode<Data> for f32 {
- fn decode(reader: &mut dyn Read, ctx: &Context<Data>) -> Result<Self>
+ fn decode(buf: &mut &[u8], ctx: &Context<Data>) -> Result<Self>
where
Self: Sized,
{
- let bits = u32::decode(reader, ctx)?;
- let value = f32::from_bits(bits);
- Ok(value)
+ let bits = u32::decode(buf, ctx)?;
+ Ok(f32::from_bits(bits))
}
}
impl<Data> Decode<Data> for bool {
- fn decode(reader: &mut dyn Read, _: &Context<Data>) -> Result<Self>
+ fn decode(buf: &mut &[u8], _: &Context<Data>) -> Result<Self>
where
Self: Sized,
{
- let mut byte = [0_u8];
- reader.read_exact(&mut byte)?;
- Ok(byte[0] != 0)
+ if buf.is_empty() {
+ return Err(CodecError::IoError(std::io::Error::new(
+ std::io::ErrorKind::UnexpectedEof,
+ "insufficient bytes for bool",
+ )));
+ }
+ let b = buf[0];
+ *buf = &buf[1..];
+ Ok(b != 0)
}
}
-// ~ Decode tuple
+// ── Decode tuple ────────────────────────────────────────────────────────
impl_decode_tuples!(A);
impl_decode_tuples!(A, B);
@@ -329,14 +340,14 @@ impl_decode_tuples!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O);
impl_decode_tuples!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P);
impl_decode_tuples!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q);
-// ~ Decode pointer
+// ── Decode pointer ──────────────────────────────────────────────────────
impl<Data, T> Decode<Data> for std::sync::Arc<T>
where
T: Decode<Data>,
{
- fn decode(reader: &mut dyn Read, ctx: &Context<Data>) -> Result<Self> {
- T::decode(reader, ctx).map(Arc::new)
+ fn decode(buf: &mut &[u8], ctx: &Context<Data>) -> Result<Self> {
+ T::decode(buf, ctx).map(Arc::new)
}
}
@@ -344,11 +355,11 @@ impl<Data, T> Decode<Data> for Arc<[T]>
where
T: Decode<Data>,
{
- fn decode(reader: &mut dyn Read, ctx: &Context<Data>) -> Result<Self>
+ fn decode(buf: &mut &[u8], ctx: &Context<Data>) -> Result<Self>
where
Self: Sized,
{
- let slice = T::decode_slice(reader, ctx)?;
+ let slice = T::decode_slice(buf, ctx)?;
Ok(slice.into())
}
}