diff options
Diffstat (limited to 'src/codec/encode.rs')
| -rw-r--r-- | src/codec/encode.rs | 304 |
1 files changed, 264 insertions, 40 deletions
diff --git a/src/codec/encode.rs b/src/codec/encode.rs index b9ac961..ae5eb4e 100644 --- a/src/codec/encode.rs +++ b/src/codec/encode.rs @@ -1,83 +1,270 @@ //! Encoding: writing protocol values into a byte stream. -use crate::codec::error::Error; +use crate::codec::error::Result; use crate::context::Context; -use std::{io::Write, sync::Arc}; +use std::{ + collections::{BTreeMap, BTreeSet, BinaryHeap, HashMap, HashSet, LinkedList, VecDeque}, + io::Write, +}; 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) + } + + /// 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, Error> { + 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 dyn Write, + _: &Context<Data>, + ) -> Result<usize> { + let len = buffer.write( + &slice + .iter() + .flat_map(|n| n.to_be_bytes()) + .collect::<Box<[u8]>>(), + )?; + Ok(len) + } + } + }; +} + +macro_rules! impl_encode_tuples { + ($($generic: ident),+) => { + impl<Data, $($generic),+> Encode<Data> for ($($generic,)+) + where + $($generic: Encode<Data>),+ + { + #[allow(non_snake_case)] + fn encode(&self, buffer: &mut dyn Write, ctx: &Context<Data>) -> Result<usize> { + let ($($generic,)+): &($($generic,)+) = self; + let mut len = 0; + $(len += $generic.encode(buffer, ctx)?;)+ + Ok(len) + } } }; } /// Write a value into a byte stream pub trait Encode<Data> { - fn encode(&self, buffer: &mut dyn Write, ctx: &Context<Data>) -> Result<usize, Error>; + 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> + where + Self: Sized, + { + let mut len = 0; + for item in slice { + len += item.encode(buffer, ctx)?; + } + Ok(len) + } } -impl<Data> Encode<Data> for bool { - fn encode(&self, buffer: &mut dyn Write, _: &Context<Data>) -> Result<usize, Error> { - let size = buffer.write(&[*self as u8])?; - Ok(size) +// ~ 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> { + T::encode_slice(self, buffer, ctx) } } -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, Error> { - match self { - Some(val) => { - let size = val.encode(buffer, ctx)?; - Ok(size) - } - None => Ok(0), - } +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) } } -impl<Data, T: Encode<Data>> Encode<Data> for Vec<T> { - /// Encode each element of vector - /// 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, Error> { - let mut size = 0; - for item in self { - size += item.encode(buffer, ctx)?; - } - Ok(size) +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) + } +} + +// ~ 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> { + 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> { + 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> { + T::encode_slice(self, buffer, ctx) } } +// ~ Encode set + +impl<Data, T: Encode<Data>> Encode<Data> for HashSet<T> +where + T: Clone, +{ + /// 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) + } +} + +impl<Data, T: Encode<Data>> Encode<Data> for BTreeSet<T> +where + T: Clone, +{ + /// 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) + } +} + +// ~ 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> { + T::encode_slice(self.as_slice(), buffer, ctx) + } +} + +// ~ Encode maps + +impl<Data, K, V> Encode<Data> for HashMap<K, V> +where + K: Encode<Data> + Clone, + V: Encode<Data> + Clone, +{ + /// 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) + } +} + +impl<Data, K, V> Encode<Data> for BTreeMap<K, V> +where + K: Encode<Data> + Clone, + V: Encode<Data> + Clone, +{ + /// 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) + } +} + +// ~ 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, Error> { + fn encode(&self, buffer: &mut dyn Write, _: &Context<Data>) -> Result<usize> { let utf8 = self.as_bytes(); buffer.write_all(utf8)?; Ok(utf8.len()) } } -impl<Data> Encode<Data> for Arc<[u8]> { - /// write raw slice into the buffer - /// use `LenPrefix` to prefix with byte length - fn encode(&self, buffer: &mut dyn Write, _: &Context<Data>) -> Result<usize, Error> { - let len = buffer.write(self)?; - Ok(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> { + let utf8 = self.as_bytes(); + buffer.write_all(utf8)?; + Ok(utf8.len()) } } -impl<Data, const S: usize> Encode<Data> for [u8; S] { - /// write raw slice into the buffer - /// use `LenPrefix` to prefix with byte length - fn encode(&self, buffer: &mut dyn Write, _: &Context<Data>) -> Result<usize, Error> { - let len = buffer.write(self)?; +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> { + match self { + Some(val) => { + let size = val.encode(buffer, ctx)?; + Ok(size) + } + None => Ok(0), + } + } +} + +// ~ 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_slice(slice: &[Self], buffer: &mut dyn Write, _: &Context<Data>) -> Result<usize> + where + Self: Sized, + { + let len = buffer.write(&slice.iter().map(|n| *n as u8).collect::<Box<[u8]>>())?; Ok(len) } } @@ -96,5 +283,42 @@ impl_encode!(i64); impl_encode!(i128); impl_encode!(isize); +#[cfg(feature = "f16")] +impl_encode!(f16); impl_encode!(f32); impl_encode!(f64); +#[cfg(feature = "f128")] +impl_encode!(f128); + +// ~ Encode tuple + +impl<Data> Encode<Data> for () { + fn encode(&self, _: &mut dyn Write, _: &Context<Data>) -> Result<usize> { + Ok(0) + } + + fn encode_slice(_: &[Self], _: &mut dyn Write, _: &Context<Data>) -> Result<usize> + where + Self: Sized, + { + Ok(0) + } +} + +impl_encode_tuples!(A); +impl_encode_tuples!(A, B); +impl_encode_tuples!(A, B, C); +impl_encode_tuples!(A, B, C, D); +impl_encode_tuples!(A, B, C, D, E); +impl_encode_tuples!(A, B, C, D, E, F); +impl_encode_tuples!(A, B, C, D, E, F, G); +impl_encode_tuples!(A, B, C, D, E, F, G, H); +impl_encode_tuples!(A, B, C, D, E, F, G, H, I); +impl_encode_tuples!(A, B, C, D, E, F, G, H, I, J); +impl_encode_tuples!(A, B, C, D, E, F, G, H, I, J, K); +impl_encode_tuples!(A, B, C, D, E, F, G, H, I, J, K, L); +impl_encode_tuples!(A, B, C, D, E, F, G, H, I, J, K, L, M); +impl_encode_tuples!(A, B, C, D, E, F, G, H, I, J, K, L, M, N); +impl_encode_tuples!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O); +impl_encode_tuples!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P); +impl_encode_tuples!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q); |
