//! Serialization for client-server communication. use std::any::Any; use std::char; use std::io::Write; use std::num::NonZeroU32; use std::ops::Bound; use std::str; pub(super) type Writer = super::buffer::Buffer; pub(super) trait Encode: Sized { fn encode(self, w: &mut Writer, s: &mut S); } pub(super) type Reader<'a> = &'a [u8]; pub(super) trait Decode<'a, 's, S>: Sized { fn decode(r: &mut Reader<'a>, s: &'s S) -> Self; } pub(super) trait DecodeMut<'a, 's, S>: Sized { fn decode(r: &mut Reader<'a>, s: &'s mut S) -> Self; } macro_rules! rpc_encode_decode { (le $ty:ty) => { impl Encode for $ty { fn encode(self, w: &mut Writer, _: &mut S) { w.extend_from_array(&self.to_le_bytes()); } } impl DecodeMut<'_, '_, S> for $ty { fn decode(r: &mut Reader<'_>, _: &mut S) -> Self { const N: usize = ::std::mem::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 { $($field:ident),* $(,)? }) => { impl Encode for $name { fn encode(self, w: &mut Writer, s: &mut S) { $(self.$field.encode(w, s);)* } } impl DecodeMut<'_, '_, S> for $name { fn decode(r: &mut Reader<'_>, s: &mut S) -> Self { $name { $($field: DecodeMut::decode(r, s)),* } } } }; (enum $name:ident $(<$($T:ident),+>)? { $($variant:ident $(($field:ident))*),* $(,)? }) => { impl),+)?> Encode for $name $(<$($T),+>)? { fn encode(self, w: &mut Writer, s: &mut S) { // HACK(eddyb): `Tag` enum duplicated between the // two impls as there's no other place to stash it. #[allow(non_upper_case_globals)] mod tag { #[repr(u8)] enum Tag { $($variant),* } $(pub const $variant: u8 = Tag::$variant as u8;)* } match self { $($name::$variant $(($field))* => { tag::$variant.encode(w, s); $($field.encode(w, s);)* })* } } } impl<'a, S, $($($T: for<'s> DecodeMut<'a, 's, S>),+)?> DecodeMut<'a, '_, S> for $name $(<$($T),+>)? { fn decode(r: &mut Reader<'a>, s: &mut S) -> Self { // HACK(eddyb): `Tag` enum duplicated between the // two impls as there's no other place to stash it. #[allow(non_upper_case_globals)] mod tag { #[repr(u8)] enum Tag { $($variant),* } $(pub const $variant: u8 = Tag::$variant as u8;)* } match u8::decode(r, s) { $(tag::$variant => { $(let $field = DecodeMut::decode(r, s);)* $name::$variant $(($field))* })* _ => unreachable!(), } } } } } impl Encode for () { fn encode(self, _: &mut Writer, _: &mut S) {} } impl DecodeMut<'_, '_, S> for () { fn decode(_: &mut Reader<'_>, _: &mut S) -> Self {} } impl Encode for u8 { fn encode(self, w: &mut Writer, _: &mut S) { w.push(self); } } impl DecodeMut<'_, '_, S> for u8 { fn decode(r: &mut Reader<'_>, _: &mut S) -> Self { let x = r[0]; *r = &r[1..]; x } } rpc_encode_decode!(le u32); rpc_encode_decode!(le usize); impl Encode for bool { fn encode(self, w: &mut Writer, s: &mut S) { (self as u8).encode(w, s); } } impl DecodeMut<'_, '_, S> for bool { fn decode(r: &mut Reader<'_>, s: &mut S) -> Self { match u8::decode(r, s) { 0 => false, 1 => true, _ => unreachable!(), } } } impl Encode for char { fn encode(self, w: &mut Writer, s: &mut S) { (self as u32).encode(w, s); } } impl DecodeMut<'_, '_, S> for char { fn decode(r: &mut Reader<'_>, s: &mut S) -> Self { char::from_u32(u32::decode(r, s)).unwrap() } } impl Encode for NonZeroU32 { fn encode(self, w: &mut Writer, s: &mut S) { self.get().encode(w, s); } } impl DecodeMut<'_, '_, S> for NonZeroU32 { fn decode(r: &mut Reader<'_>, s: &mut S) -> Self { Self::new(u32::decode(r, s)).unwrap() } } impl, B: Encode> Encode for (A, B) { fn encode(self, w: &mut Writer, s: &mut S) { self.0.encode(w, s); self.1.encode(w, s); } } impl<'a, S, A: for<'s> DecodeMut<'a, 's, S>, B: for<'s> DecodeMut<'a, 's, S>> DecodeMut<'a, '_, S> for (A, B) { fn decode(r: &mut Reader<'a>, s: &mut S) -> Self { (DecodeMut::decode(r, s), DecodeMut::decode(r, s)) } } rpc_encode_decode!( enum Bound { Included(x), Excluded(x), Unbounded, } ); rpc_encode_decode!( enum Option { None, Some(x), } ); rpc_encode_decode!( enum Result { Ok(x), Err(e), } ); impl Encode for &[u8] { fn encode(self, w: &mut Writer, s: &mut S) { self.len().encode(w, s); w.write_all(self).unwrap(); } } impl<'a, S> DecodeMut<'a, '_, S> for &'a [u8] { fn decode(r: &mut Reader<'a>, s: &mut S) -> Self { let len = usize::decode(r, s); let xs = &r[..len]; *r = &r[len..]; xs } } impl Encode for &str { fn encode(self, w: &mut Writer, s: &mut S) { self.as_bytes().encode(w, s); } } impl<'a, S> DecodeMut<'a, '_, S> for &'a str { fn decode(r: &mut Reader<'a>, s: &mut S) -> Self { str::from_utf8(<&[u8]>::decode(r, s)).unwrap() } } impl Encode for String { fn encode(self, w: &mut Writer, s: &mut S) { self[..].encode(w, s); } } impl DecodeMut<'_, '_, S> for String { fn decode(r: &mut Reader<'_>, s: &mut S) -> Self { <&str>::decode(r, s).to_string() } } /// Simplified version of panic payloads, ignoring /// types other than `&'static str` and `String`. pub enum PanicMessage { StaticStr(&'static str), String(String), Unknown, } impl From> for PanicMessage { fn from(payload: Box) -> Self { if let Some(s) = payload.downcast_ref::<&'static str>() { return PanicMessage::StaticStr(s); } if let Ok(s) = payload.downcast::() { return PanicMessage::String(*s); } PanicMessage::Unknown } } impl Into> for PanicMessage { fn into(self) -> Box { match self { PanicMessage::StaticStr(s) => Box::new(s), PanicMessage::String(s) => Box::new(s), PanicMessage::Unknown => { struct UnknownPanicMessage; Box::new(UnknownPanicMessage) } } } } impl PanicMessage { pub fn as_str(&self) -> Option<&str> { match self { PanicMessage::StaticStr(s) => Some(s), PanicMessage::String(s) => Some(s), PanicMessage::Unknown => None, } } } impl Encode for PanicMessage { fn encode(self, w: &mut Writer, s: &mut S) { self.as_str().encode(w, s); } } impl DecodeMut<'_, '_, S> for PanicMessage { fn decode(r: &mut Reader<'_>, s: &mut S) -> Self { match Option::::decode(r, s) { Some(s) => PanicMessage::String(s), None => PanicMessage::Unknown, } } }