summaryrefslogtreecommitdiff
path: root/src/codec
diff options
context:
space:
mode:
Diffstat (limited to 'src/codec')
-rw-r--r--src/codec/decode.rs251
-rw-r--r--src/codec/encode.rs336
2 files changed, 319 insertions, 268 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())
}
}
diff --git a/src/codec/encode.rs b/src/codec/encode.rs
index 7463995..735aa70 100644
--- a/src/codec/encode.rs
+++ b/src/codec/encode.rs
@@ -1,49 +1,36 @@
-//! Encoding: writing protocol values into a byte stream.
use crate::codec::error::Result;
use crate::context::Context;
-use std::{
- collections::{BTreeMap, BTreeSet, BinaryHeap, HashMap, HashSet, LinkedList, VecDeque},
- io::Write,
-};
+use std::collections::{BTreeMap, BTreeSet, BinaryHeap, HashMap, HashSet, LinkedList, VecDeque};
macro_rules! impl_encode {
- (u8) => {
- impl<Data> Encode<Data> for u8 {
- /// write number using big endian
- fn encode(&self, buffer: &mut dyn Write, _: &Context<Data>) -> Result<usize> {
- let size = buffer.write(&self.to_be_bytes())?;
- Ok(size)
+ ($t:ty) => {
+ impl<Data> Encode<Data> for $t {
+ fn encode(&self, buffer: &mut Vec<u8>, _: &Context<Data>) -> Result<usize> {
+ buffer.extend_from_slice(&self.to_be_bytes());
+ Ok(std::mem::size_of::<$t>())
}
- /// write raw bytes
- fn encode_slice(
- slice: &[Self],
- buffer: &mut dyn Write,
- _: &Context<Data>,
- ) -> Result<usize> {
- buffer.write(slice).map_err(Into::into)
- }
- }
- };
- ($t: ty) => {
- impl<Data> Encode<Data> for $t {
- /// write number using big endian
- fn encode(&self, buffer: &mut dyn Write, _: &Context<Data>) -> Result<usize> {
- let size = buffer.write(&self.to_be_bytes())?;
- Ok(size)
+ fn encode_slice(slice: &[Self], buffer: &mut Vec<u8>, _: &Context<Data>) -> Result<usize>
+ where
+ Self: Sized,
+ {
+ let len = slice.len() * std::mem::size_of::<$t>();
+ buffer.reserve(len);
+ for item in slice {
+ buffer.extend_from_slice(&item.to_be_bytes());
+ }
+ Ok(len)
}
- fn encode_slice(
- slice: &[Self],
- buffer: &mut dyn Write,
- _: &Context<Data>,
- ) -> Result<usize> {
- let len = buffer.write(
- &slice
- .iter()
- .flat_map(|n| n.to_be_bytes())
- .collect::<Box<[u8]>>(),
- )?;
+ fn encode_iter<'a, I>(iter: I, buffer: &mut Vec<u8>, ctx: &Context<Data>) -> Result<usize>
+ where
+ Self: 'a + Sized,
+ I: IntoIterator<Item = &'a Self>,
+ {
+ let mut len = 0;
+ for item in iter {
+ len += item.encode(buffer, ctx)?;
+ }
Ok(len)
}
}
@@ -57,7 +44,7 @@ macro_rules! impl_encode_tuples {
$($generic: Encode<Data>),+
{
#[allow(non_snake_case)]
- fn encode(&self, buffer: &mut dyn Write, ctx: &Context<Data>) -> Result<usize> {
+ fn encode(&self, buffer: &mut Vec<u8>, ctx: &Context<Data>) -> Result<usize> {
let ($($generic,)+): &($($generic,)+) = self;
let mut len = 0;
$(len += $generic.encode(buffer, ctx)?;)+
@@ -67,10 +54,11 @@ macro_rules! impl_encode_tuples {
};
}
-/// Write a value into a byte stream
+/// Zero-copy encoding: writes directly into a byte buffer
pub trait Encode<Data> {
- fn encode(&self, buffer: &mut dyn Write, ctx: &Context<Data>) -> Result<usize>;
- fn encode_slice(slice: &[Self], buffer: &mut dyn Write, ctx: &Context<Data>) -> Result<usize>
+ fn encode(&self, buffer: &mut Vec<u8>, ctx: &Context<Data>) -> Result<usize>;
+
+ fn encode_slice(slice: &[Self], buffer: &mut Vec<u8>, ctx: &Context<Data>) -> Result<usize>
where
Self: Sized,
{
@@ -80,204 +68,257 @@ pub trait Encode<Data> {
}
Ok(len)
}
+
+ fn encode_iter<'a, I>(iter: I, buffer: &mut Vec<u8>, ctx: &Context<Data>) -> Result<usize>
+ where
+ Self: 'a + Sized,
+ I: IntoIterator<Item = &'a Self>,
+ {
+ let mut len = 0;
+ for item in iter {
+ len += item.encode(buffer, ctx)?;
+ }
+ Ok(len)
+ }
}
-// ~ Encode arrays
+// ── Encode arrays ───────────────────────────────────────────────────────
impl<Data, T: Encode<Data>> Encode<Data> for Vec<T> {
- /// Encode each element of Vec
- /// use `CountPrefix` to prefix the vector with number of elements
- /// use `LenPrefix` to prefix the vector with encoded byte size
- fn encode(&self, buffer: &mut dyn Write, ctx: &Context<Data>) -> Result<usize> {
+ fn encode(&self, buffer: &mut Vec<u8>, ctx: &Context<Data>) -> Result<usize> {
T::encode_slice(self, buffer, ctx)
}
}
impl<Data, T: Encode<Data>> Encode<Data> for VecDeque<T> {
- /// Encode each element of VecDeque
- /// use `CountPrefix` to prefix the VecDeque with number of elements
- /// use `LenPrefix` to prefix the VecDeque with encoded byte size
- fn encode(&self, buffer: &mut dyn Write, ctx: &Context<Data>) -> Result<usize> {
- let (front, _) = self.as_slices();
- T::encode_slice(front, buffer, ctx)
+ fn encode(&self, buffer: &mut Vec<u8>, ctx: &Context<Data>) -> Result<usize> {
+ let (front, back) = self.as_slices();
+ let mut len = 0;
+ len += T::encode_slice(front, buffer, ctx)?;
+ len += T::encode_slice(back, buffer, ctx)?;
+ Ok(len)
}
}
-impl<Data, T: Encode<Data>> Encode<Data> for LinkedList<T>
-where
- T: Clone,
-{
- /// Encode each element of LinkedList (use clone..)
- /// use `CountPrefix` to prefix the LinkedList with number of elements
- /// use `LenPrefix` to prefix the LinkedList with encoded byte size
- fn encode(&self, buffer: &mut dyn Write, ctx: &Context<Data>) -> Result<usize> {
- let mut view = Vec::with_capacity(self.len());
- view.extend(self.iter().cloned());
- T::encode_slice(&view, buffer, ctx)
+impl<Data, T: Encode<Data>> Encode<Data> for LinkedList<T> {
+ fn encode(&self, buffer: &mut Vec<u8>, ctx: &Context<Data>) -> Result<usize> {
+ let mut len = 0;
+ for item in self {
+ len += item.encode(buffer, ctx)?;
+ }
+ Ok(len)
}
}
-// ~ Encode slices
+// ── Encode slices ───────────────────────────────────────────────────────
impl<Data, T: Encode<Data>> Encode<Data> for &[T] {
- /// Encode each element of slice (use clone..)
- /// use `CountPrefix` to prefix the slice with number of elements
- /// use `LenPrefix` to prefix the slice with encoded byte size
- fn encode(&self, buffer: &mut dyn Write, ctx: &Context<Data>) -> Result<usize> {
+ fn encode(&self, buffer: &mut Vec<u8>, ctx: &Context<Data>) -> Result<usize> {
T::encode_slice(self, buffer, ctx)
}
}
impl<Data, T: Encode<Data>, const S: usize> Encode<Data> for [T; S] {
- /// Encode each element of slice (use clone..)
- /// use `CountPrefix` to prefix the slice with number of elements
- /// use `LenPrefix` to prefix the slice with encoded byte size
- fn encode(&self, buffer: &mut dyn Write, ctx: &Context<Data>) -> Result<usize> {
+ fn encode(&self, buffer: &mut Vec<u8>, ctx: &Context<Data>) -> Result<usize> {
T::encode_slice(self, buffer, ctx)
}
}
impl<Data, T: Encode<Data>> Encode<Data> for [T] {
- /// Encode each element of slice (use clone..)
- /// use `CountPrefix` to prefix the slice with number of elements
- /// use `LenPrefix` to prefix the slice with encoded byte size
- fn encode(&self, buffer: &mut dyn Write, ctx: &Context<Data>) -> Result<usize> {
+ fn encode(&self, buffer: &mut Vec<u8>, ctx: &Context<Data>) -> Result<usize> {
+ T::encode_slice(self, buffer, ctx)
+ }
+}
+
+// ── Encode references to collections ────────────────────────────────────
+
+impl<Data, T: Encode<Data>> Encode<Data> for &Vec<T> {
+ fn encode(&self, buffer: &mut Vec<u8>, ctx: &Context<Data>) -> Result<usize> {
T::encode_slice(self, buffer, ctx)
}
}
-// ~ Encode set
+impl<Data, T: Encode<Data>> Encode<Data> for &VecDeque<T> {
+ fn encode(&self, buffer: &mut Vec<u8>, ctx: &Context<Data>) -> Result<usize> {
+ let (front, back) = self.as_slices();
+ let mut len = 0;
+ len += T::encode_slice(front, buffer, ctx)?;
+ len += T::encode_slice(back, buffer, ctx)?;
+ Ok(len)
+ }
+}
-impl<Data, T: Encode<Data>> Encode<Data> for HashSet<T>
+impl<Data, T: Encode<Data>> Encode<Data> for &LinkedList<T> {
+ fn encode(&self, buffer: &mut Vec<u8>, ctx: &Context<Data>) -> Result<usize> {
+ let mut len = 0;
+ for item in (*self).iter() {
+ len += item.encode(buffer, ctx)?;
+ }
+ Ok(len)
+ }
+}
+
+impl<Data, T: Encode<Data>> Encode<Data> for &HashSet<T> {
+ fn encode(&self, buffer: &mut Vec<u8>, ctx: &Context<Data>) -> Result<usize> {
+ T::encode_iter(self.iter(), buffer, ctx)
+ }
+}
+
+impl<Data, T: Encode<Data>> Encode<Data> for &BTreeSet<T> {
+ fn encode(&self, buffer: &mut Vec<u8>, ctx: &Context<Data>) -> Result<usize> {
+ T::encode_iter(self.iter(), buffer, ctx)
+ }
+}
+
+impl<Data, T: Encode<Data>> Encode<Data> for &BinaryHeap<T> {
+ fn encode(&self, buffer: &mut Vec<u8>, ctx: &Context<Data>) -> Result<usize> {
+ T::encode_slice(self.as_slice(), buffer, ctx)
+ }
+}
+
+impl<Data, K, V> Encode<Data> for &HashMap<K, V>
where
- T: Clone,
+ K: Encode<Data>,
+ V: Encode<Data>,
{
- /// Encode each element of HashSet (use clone..)
- /// use `CountPrefix` to prefix the HashSet with number of elements
- /// use `LenPrefix` to prefix the HashSet with encoded byte size
- fn encode(&self, buffer: &mut dyn Write, ctx: &Context<Data>) -> Result<usize> {
- let mut view = Vec::with_capacity(self.len());
- view.extend(self.iter().cloned());
- T::encode_slice(&view, buffer, ctx)
+ fn encode(&self, buffer: &mut Vec<u8>, ctx: &Context<Data>) -> Result<usize> {
+ let mut len = 0;
+ for (k, v) in (*self).iter() {
+ len += k.encode(buffer, ctx)?;
+ len += v.encode(buffer, ctx)?;
+ }
+ Ok(len)
}
}
-impl<Data, T: Encode<Data>> Encode<Data> for BTreeSet<T>
+impl<Data, K, V> Encode<Data> for &BTreeMap<K, V>
where
- T: Clone,
+ K: Encode<Data>,
+ V: Encode<Data>,
{
- /// Encode each element of BTreeSet (use clone..)
- /// use `CountPrefix` to prefix the BTreeSet with number of elements
- /// use `LenPrefix` to prefix the BTreeSet with encoded byte size
- fn encode(&self, buffer: &mut dyn Write, ctx: &Context<Data>) -> Result<usize> {
- let mut view = Vec::with_capacity(self.len());
- view.extend(self.iter().cloned());
- T::encode_slice(&view, buffer, ctx)
+ fn encode(&self, buffer: &mut Vec<u8>, ctx: &Context<Data>) -> Result<usize> {
+ let mut len = 0;
+ for (k, v) in (*self).iter() {
+ len += k.encode(buffer, ctx)?;
+ len += v.encode(buffer, ctx)?;
+ }
+ Ok(len)
}
}
-// ~ Encode misc
+// ── Encode set (owned) ──────────────────────────────────────────────────
+
+impl<Data, T: Encode<Data>> Encode<Data> for HashSet<T> {
+ fn encode(&self, buffer: &mut Vec<u8>, ctx: &Context<Data>) -> Result<usize> {
+ T::encode_iter(self.iter(), buffer, ctx)
+ }
+}
+
+impl<Data, T: Encode<Data>> Encode<Data> for BTreeSet<T> {
+ fn encode(&self, buffer: &mut Vec<u8>, ctx: &Context<Data>) -> Result<usize> {
+ T::encode_iter(self.iter(), buffer, ctx)
+ }
+}
+
+// ── Encode misc ─────────────────────────────────────────────────────────
impl<Data, T> Encode<Data> for BinaryHeap<T>
where
T: Encode<Data>,
{
- fn encode(&self, buffer: &mut dyn Write, ctx: &Context<Data>) -> Result<usize> {
+ fn encode(&self, buffer: &mut Vec<u8>, ctx: &Context<Data>) -> Result<usize> {
T::encode_slice(self.as_slice(), buffer, ctx)
}
}
-// ~ Encode maps
+// ── Encode maps (owned) ─────────────────────────────────────────────────
impl<Data, K, V> Encode<Data> for HashMap<K, V>
where
- K: Encode<Data> + Clone,
- V: Encode<Data> + Clone,
+ K: Encode<Data>,
+ V: Encode<Data>,
{
- /// Encode each element of HashMap (use clone..)
- /// use `CountPrefix` to prefix the HashMap with number of pairs
- /// use `LenPrefix` to prefix the HashMap with encoded byte size
- fn encode(&self, buffer: &mut dyn Write, ctx: &Context<Data>) -> Result<usize> {
- let slice: Vec<(K, V)> = self.clone().into_iter().collect();
- <(K, V) as Encode<Data>>::encode_slice(&slice, buffer, ctx)
+ fn encode(&self, buffer: &mut Vec<u8>, ctx: &Context<Data>) -> Result<usize> {
+ let mut len = 0;
+ for (k, v) in self {
+ len += k.encode(buffer, ctx)?;
+ len += v.encode(buffer, ctx)?;
+ }
+ Ok(len)
}
}
impl<Data, K, V> Encode<Data> for BTreeMap<K, V>
where
- K: Encode<Data> + Clone,
- V: Encode<Data> + Clone,
+ K: Encode<Data>,
+ V: Encode<Data>,
{
- /// Encode each element of BTreeMap (use clone..)
- /// use `CountPrefix` to prefix the BTreeMap with number of pairs
- /// use `LenPrefix` to prefix the BTreeMap with encoded byte size
- fn encode(&self, buffer: &mut dyn Write, ctx: &Context<Data>) -> Result<usize> {
- let slice: Vec<(K, V)> = self.clone().into_iter().collect();
- <(K, V) as Encode<Data>>::encode_slice(&slice, buffer, ctx)
+ fn encode(&self, buffer: &mut Vec<u8>, ctx: &Context<Data>) -> Result<usize> {
+ let mut len = 0;
+ for (k, v) in self {
+ len += k.encode(buffer, ctx)?;
+ len += v.encode(buffer, ctx)?;
+ }
+ Ok(len)
}
}
-// ~ Encode string
+// ── Encode string ───────────────────────────────────────────────────────
+
impl<Data> Encode<Data> for String {
- /// Encode the string using utf8
- /// use `CountPrefix` to prefix the string with char length
- /// use `LenPrefix` to prefix the string with utf8 bytes length
- fn encode(&self, buffer: &mut dyn Write, _: &Context<Data>) -> Result<usize> {
+ fn encode(&self, buffer: &mut Vec<u8>, _: &Context<Data>) -> Result<usize> {
let utf8 = self.as_bytes();
- buffer.write_all(utf8)?;
+ buffer.extend_from_slice(utf8);
Ok(utf8.len())
}
}
impl<Data> Encode<Data> for &str {
- /// Encode the string using utf8
- /// use `CountPrefix` to prefix the string with char length
- /// use `LenPrefix` to prefix the string with utf8 bytes length
- fn encode(&self, buffer: &mut dyn Write, _: &Context<Data>) -> Result<usize> {
+ fn encode(&self, buffer: &mut Vec<u8>, _: &Context<Data>) -> Result<usize> {
let utf8 = self.as_bytes();
- buffer.write_all(utf8)?;
+ buffer.extend_from_slice(utf8);
Ok(utf8.len())
}
}
impl<Data, T: Encode<Data>> Encode<Data> for Option<T> {
- /// Encode `T` if Some(T) or do nothing if None
- fn encode(&self, buffer: &mut dyn Write, ctx: &Context<Data>) -> Result<usize> {
+ fn encode(&self, buffer: &mut Vec<u8>, ctx: &Context<Data>) -> Result<usize> {
match self {
- Some(val) => {
- let size = val.encode(buffer, ctx)?;
- Ok(size)
- }
+ Some(val) => val.encode(buffer, ctx),
None => Ok(0),
}
}
}
-// ~ Encode primitive
+// ── Encode primitive ────────────────────────────────────────────────────
+
impl<Data> Encode<Data> for bool {
- fn encode(&self, buffer: &mut dyn Write, _: &Context<Data>) -> Result<usize> {
- let size = buffer.write(&[*self as u8])?;
- Ok(size)
+ fn encode(&self, buffer: &mut Vec<u8>, _: &Context<Data>) -> Result<usize> {
+ buffer.push(*self as u8);
+ Ok(1)
}
- fn encode_slice(slice: &[Self], buffer: &mut dyn Write, _: &Context<Data>) -> Result<usize>
+ fn encode_slice(slice: &[Self], buffer: &mut Vec<u8>, _: &Context<Data>) -> Result<usize>
where
Self: Sized,
{
- let len = buffer.write(&slice.iter().map(|n| *n as u8).collect::<Box<[u8]>>())?;
+ let len = slice.len();
+ buffer.reserve(len);
+ for &b in slice {
+ buffer.push(b as u8);
+ }
Ok(len)
}
}
-// ~ Encode pointer
+// ── Encode pointer ──────────────────────────────────────────────────────
impl<Data, T> Encode<Data> for std::sync::Arc<T>
where
T: Encode<Data>,
{
- fn encode(&self, buffer: &mut dyn Write, ctx: &Context<Data>) -> Result<usize> {
- let data = self.as_ref();
- data.encode(buffer, ctx)
+ fn encode(&self, buffer: &mut Vec<u8>, ctx: &Context<Data>) -> Result<usize> {
+ self.as_ref().encode(buffer, ctx)
}
}
@@ -285,9 +326,8 @@ impl<Data, T> Encode<Data> for std::sync::Arc<[T]>
where
T: Encode<Data>,
{
- fn encode(&self, buffer: &mut dyn Write, ctx: &Context<Data>) -> Result<usize> {
- let data = self.as_ref();
- data.encode(buffer, ctx)
+ fn encode(&self, buffer: &mut Vec<u8>, ctx: &Context<Data>) -> Result<usize> {
+ self.as_ref().encode(buffer, ctx)
}
}
@@ -312,14 +352,14 @@ impl_encode!(f64);
#[cfg(feature = "f128")]
impl_encode!(f128);
-// ~ Encode tuple
+// ── Encode tuple ────────────────────────────────────────────────────────
impl<Data> Encode<Data> for () {
- fn encode(&self, _: &mut dyn Write, _: &Context<Data>) -> Result<usize> {
+ fn encode(&self, _: &mut Vec<u8>, _: &Context<Data>) -> Result<usize> {
Ok(0)
}
- fn encode_slice(_: &[Self], _: &mut dyn Write, _: &Context<Data>) -> Result<usize>
+ fn encode_slice(_: &[Self], _: &mut Vec<u8>, _: &Context<Data>) -> Result<usize>
where
Self: Sized,
{