| //! Serialization for client-server communication. |
| |
| use std::num::NonZero; |
| |
| use super::buffer::Buffer; |
| |
| pub(super) trait Encode<S>: Sized { |
| fn encode(self, w: &mut Buffer, s: &mut S); |
| } |
| |
| pub(super) trait Decode<'a, 's, S>: Sized { |
| fn decode(r: &mut &'a [u8], s: &'s mut S) -> Self; |
| } |
| |
| macro_rules! rpc_encode_decode { |
| (le $ty:ty) => { |
| impl<S> Encode<S> for $ty { |
| #[inline] |
| fn encode(self, w: &mut Buffer, _: &mut S) { |
| w.extend_from_array(&self.to_le_bytes()); |
| } |
| } |
| |
| impl<S> Decode<'_, '_, S> for $ty { |
| #[inline] |
| fn decode(r: &mut &[u8], _: &mut S) -> Self { |
| const N: usize = size_of::<$ty>(); |
| |
| let mut bytes = [0; N]; |
| bytes.copy_from_slice(&r[..N]); |
| *r = &r[N..]; |
| |
| Self::from_le_bytes(bytes) |
| } |
| } |
| }; |
| (struct $name:ident $(<$($T:ident),+>)? { $($field:ident),* $(,)? }) => { |
| impl<S, $($($T: Encode<S>),+)?> Encode<S> for $name $(<$($T),+>)? { |
| fn encode(self, w: &mut Buffer, s: &mut S) { |
| $(self.$field.encode(w, s);)* |
| } |
| } |
| |
| impl<'a, S, $($($T: for<'s> Decode<'a, 's, S>),+)?> Decode<'a, '_, S> |
| for $name $(<$($T),+>)? |
| { |
| #[inline] |
| fn decode(r: &mut &'a [u8], s: &mut S) -> Self { |
| $name { |
| $($field: Decode::decode(r, s)),* |
| } |
| } |
| } |
| }; |
| (enum $name:ident $(<$($T:ident),+>)? { $($variant:ident $(($field:ident))*),* $(,)? }) => { |
| #[allow(non_upper_case_globals, non_camel_case_types)] |
| const _: () = { |
| #[repr(u8)] enum Tag { $($variant),* } |
| |
| $(const $variant: u8 = Tag::$variant as u8;)* |
| |
| impl<S, $($($T: Encode<S>),+)?> Encode<S> for $name $(<$($T),+>)? { |
| #[inline] |
| fn encode(self, w: &mut Buffer, s: &mut S) { |
| match self { |
| $($name::$variant $(($field))* => { |
| $variant.encode(w, s); |
| $($field.encode(w, s);)* |
| })* |
| } |
| } |
| } |
| |
| impl<'a, S, $($($T: for<'s> Decode<'a, 's, S>),+)?> Decode<'a, '_, S> |
| for $name $(<$($T),+>)? |
| { |
| #[inline] |
| fn decode(r: &mut &'a [u8], s: &mut S) -> Self { |
| match u8::decode(r, s) { |
| $($variant => { |
| $(let $field = Decode::decode(r, s);)* |
| $name::$variant $(($field))* |
| })* |
| _ => unreachable!(), |
| } |
| } |
| } |
| }; |
| } |
| } |
| |
| impl<S> Encode<S> for () { |
| #[inline] |
| fn encode(self, _: &mut Buffer, _: &mut S) {} |
| } |
| |
| impl<S> Decode<'_, '_, S> for () { |
| #[inline] |
| fn decode(_: &mut &[u8], _: &mut S) -> Self {} |
| } |
| |
| impl<S> Encode<S> for u8 { |
| #[inline] |
| fn encode(self, w: &mut Buffer, _: &mut S) { |
| w.push(self); |
| } |
| } |
| |
| impl<S> Decode<'_, '_, S> for u8 { |
| #[inline] |
| fn decode(r: &mut &[u8], _: &mut S) -> Self { |
| let x = r[0]; |
| *r = &r[1..]; |
| x |
| } |
| } |
| |
| rpc_encode_decode!(le u32); |
| #[cfg(target_pointer_width = "64")] |
| rpc_encode_decode!(le usize); |
| |
| #[cfg(not(target_pointer_width = "64"))] |
| const MAX_USIZE_SIZE: usize = 8; |
| |
| #[cfg(not(target_pointer_width = "64"))] |
| impl<S> Encode<S> for usize { |
| #[inline] |
| fn encode(self, w: &mut Buffer, _: &mut S) { |
| const N: usize = size_of::<usize>(); |
| |
| // We can pad with zeros without changing the value because of |
| // little endian encoding. |
| let mut bytes = [0; MAX_USIZE_SIZE]; |
| bytes[..N].copy_from_slice(&self.to_le_bytes()); |
| |
| w.extend_from_array(&bytes); |
| } |
| } |
| |
| #[cfg(not(target_pointer_width = "64"))] |
| impl<S> Decode<'_, '_, S> for usize { |
| #[inline] |
| fn decode(r: &mut &[u8], _: &mut S) -> Self { |
| const N: usize = size_of::<usize>(); |
| const { |
| assert!(N <= MAX_USIZE_SIZE); |
| } |
| |
| let mut bytes = [0; N]; |
| bytes.copy_from_slice(&r[..N]); |
| *r = &r[MAX_USIZE_SIZE..]; |
| |
| Self::from_le_bytes(bytes) |
| } |
| } |
| |
| impl<S> Encode<S> for bool { |
| #[inline] |
| fn encode(self, w: &mut Buffer, s: &mut S) { |
| (self as u8).encode(w, s); |
| } |
| } |
| |
| impl<S> Decode<'_, '_, S> for bool { |
| #[inline] |
| fn decode(r: &mut &[u8], s: &mut S) -> Self { |
| match u8::decode(r, s) { |
| 0 => false, |
| 1 => true, |
| _ => unreachable!(), |
| } |
| } |
| } |
| |
| impl<S> Encode<S> for NonZero<u32> { |
| #[inline] |
| fn encode(self, w: &mut Buffer, s: &mut S) { |
| self.get().encode(w, s); |
| } |
| } |
| |
| impl<S> Decode<'_, '_, S> for NonZero<u32> { |
| #[inline] |
| fn decode(r: &mut &[u8], s: &mut S) -> Self { |
| Self::new(u32::decode(r, s)).unwrap() |
| } |
| } |
| |
| impl<S, A: Encode<S>, B: Encode<S>> Encode<S> for (A, B) { |
| #[inline] |
| fn encode(self, w: &mut Buffer, s: &mut S) { |
| self.0.encode(w, s); |
| self.1.encode(w, s); |
| } |
| } |
| |
| impl<'a, S, A: for<'s> Decode<'a, 's, S>, B: for<'s> Decode<'a, 's, S>> Decode<'a, '_, S> |
| for (A, B) |
| { |
| #[inline] |
| fn decode(r: &mut &'a [u8], s: &mut S) -> Self { |
| (Decode::decode(r, s), Decode::decode(r, s)) |
| } |
| } |
| |
| impl<S> Encode<S> for &str { |
| #[inline] |
| fn encode(self, w: &mut Buffer, s: &mut S) { |
| let bytes = self.as_bytes(); |
| bytes.len().encode(w, s); |
| w.extend_from_slice(bytes); |
| } |
| } |
| |
| impl<'a, S> Decode<'a, '_, S> for &'a str { |
| #[inline] |
| fn decode(r: &mut &'a [u8], s: &mut S) -> Self { |
| let len = usize::decode(r, s); |
| let xs = &r[..len]; |
| *r = &r[len..]; |
| str::from_utf8(xs).unwrap() |
| } |
| } |
| |
| impl<S> Encode<S> for String { |
| #[inline] |
| fn encode(self, w: &mut Buffer, s: &mut S) { |
| self[..].encode(w, s); |
| } |
| } |
| |
| impl<S> Decode<'_, '_, S> for String { |
| #[inline] |
| fn decode(r: &mut &[u8], s: &mut S) -> Self { |
| <&str>::decode(r, s).to_string() |
| } |
| } |
| |
| impl<S, T: Encode<S>> Encode<S> for Vec<T> { |
| #[inline] |
| fn encode(self, w: &mut Buffer, s: &mut S) { |
| self.len().encode(w, s); |
| for x in self { |
| x.encode(w, s); |
| } |
| } |
| } |
| |
| impl<'a, S, T: for<'s> Decode<'a, 's, S>> Decode<'a, '_, S> for Vec<T> { |
| #[inline] |
| fn decode(r: &mut &'a [u8], s: &mut S) -> Self { |
| let len = usize::decode(r, s); |
| let mut vec = Vec::with_capacity(len); |
| for _ in 0..len { |
| vec.push(T::decode(r, s)); |
| } |
| vec |
| } |
| } |