diff options
Diffstat (limited to 'src/codec/encode.rs')
| -rw-r--r-- | src/codec/encode.rs | 336 |
1 files changed, 188 insertions, 148 deletions
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, { |
