//! 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, }; macro_rules! impl_encode { (u8) => { impl Encode for u8 { /// write number using big endian fn encode(&self, buffer: &mut dyn Write, _: &Context) -> Result { let size = buffer.write(&self.to_be_bytes())?; Ok(size) } /// write raw bytes fn encode_slice( slice: &[Self], buffer: &mut dyn Write, _: &Context, ) -> Result { buffer.write(slice).map_err(Into::into) } } }; ($t: ty) => { impl Encode for $t { /// write number using big endian fn encode(&self, buffer: &mut dyn Write, _: &Context) -> Result { let size = buffer.write(&self.to_be_bytes())?; Ok(size) } fn encode_slice( slice: &[Self], buffer: &mut dyn Write, _: &Context, ) -> Result { let len = buffer.write( &slice .iter() .flat_map(|n| n.to_be_bytes()) .collect::>(), )?; Ok(len) } } }; } macro_rules! impl_encode_tuples { ($($generic: ident),+) => { impl Encode for ($($generic,)+) where $($generic: Encode),+ { #[allow(non_snake_case)] fn encode(&self, buffer: &mut dyn Write, ctx: &Context) -> Result { 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 { fn encode(&self, buffer: &mut dyn Write, ctx: &Context) -> Result; fn encode_slice(slice: &[Self], buffer: &mut dyn Write, ctx: &Context) -> Result where Self: Sized, { let mut len = 0; for item in slice { len += item.encode(buffer, ctx)?; } Ok(len) } } // ~ Encode arrays impl> Encode for Vec { /// 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) -> Result { T::encode_slice(self, buffer, ctx) } } impl> Encode for VecDeque { /// 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) -> Result { let (front, _) = self.as_slices(); T::encode_slice(front, buffer, ctx) } } impl> Encode for LinkedList 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) -> Result { let mut view = Vec::with_capacity(self.len()); view.extend(self.iter().cloned()); T::encode_slice(&view, buffer, ctx) } } // ~ Encode slices impl> Encode 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) -> Result { T::encode_slice(self, buffer, ctx) } } impl, const S: usize> Encode 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) -> Result { T::encode_slice(self, buffer, ctx) } } impl> Encode 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) -> Result { T::encode_slice(self, buffer, ctx) } } // ~ Encode set impl> Encode for HashSet 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) -> Result { let mut view = Vec::with_capacity(self.len()); view.extend(self.iter().cloned()); T::encode_slice(&view, buffer, ctx) } } impl> Encode for BTreeSet 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) -> Result { let mut view = Vec::with_capacity(self.len()); view.extend(self.iter().cloned()); T::encode_slice(&view, buffer, ctx) } } // ~ Encode misc impl Encode for BinaryHeap where T: Encode, { fn encode(&self, buffer: &mut dyn Write, ctx: &Context) -> Result { T::encode_slice(self.as_slice(), buffer, ctx) } } // ~ Encode maps impl Encode for HashMap where K: Encode + Clone, V: Encode + 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) -> Result { let slice: Vec<(K, V)> = self.clone().into_iter().collect(); <(K, V) as Encode>::encode_slice(&slice, buffer, ctx) } } impl Encode for BTreeMap where K: Encode + Clone, V: Encode + 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) -> Result { let slice: Vec<(K, V)> = self.clone().into_iter().collect(); <(K, V) as Encode>::encode_slice(&slice, buffer, ctx) } } // ~ Encode string impl Encode 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) -> Result { let utf8 = self.as_bytes(); buffer.write_all(utf8)?; Ok(utf8.len()) } } impl Encode 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) -> Result { let utf8 = self.as_bytes(); buffer.write_all(utf8)?; Ok(utf8.len()) } } impl> Encode for Option { /// Encode `T` if Some(T) or do nothing if None fn encode(&self, buffer: &mut dyn Write, ctx: &Context) -> Result { match self { Some(val) => { let size = val.encode(buffer, ctx)?; Ok(size) } None => Ok(0), } } } // ~ Encode primitive impl Encode for bool { fn encode(&self, buffer: &mut dyn Write, _: &Context) -> Result { let size = buffer.write(&[*self as u8])?; Ok(size) } fn encode_slice(slice: &[Self], buffer: &mut dyn Write, _: &Context) -> Result where Self: Sized, { let len = buffer.write(&slice.iter().map(|n| *n as u8).collect::>())?; 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); #[cfg(feature = "f16")] impl_encode!(f16); impl_encode!(f32); impl_encode!(f64); #[cfg(feature = "f128")] impl_encode!(f128); // ~ Encode tuple impl Encode for () { fn encode(&self, _: &mut dyn Write, _: &Context) -> Result { Ok(0) } fn encode_slice(_: &[Self], _: &mut dyn Write, _: &Context) -> Result 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);