//! A module defining serde dserialize for the format described in ser.rs //! //! TL;DR: How to Use //! ================================================================================ //! //! ```rust,ignore //! #[derive(Deserialize)] //! struct ExampleStruct { //! a: (), //! b: bool, //! c: u8, //! ..., //! } //! //! let bytes = ...; //! let s: ExampleStruct = pythnet_sdk::de::from_slice::(&bytes)?; //! ``` //! //! The deserialization mechanism is a bit more complex than the serialization mechanism as it //! employs a visitor pattern. Rather than describe it here, the serde documentation on how to //! implement a deserializer can be found here: //! //! https://serde.rs/impl-deserializer.html use { crate::require, byteorder::{ ByteOrder, ReadBytesExt, }, serde::{ de::{ EnumAccess, MapAccess, SeqAccess, VariantAccess, }, Deserialize, }, std::{ io::{ Cursor, Seek, SeekFrom, }, mem::size_of, }, thiserror::Error, }; /// Deserialize a Pyth wire-format buffer into a type. /// /// Note that this method will not consume left-over bytes ore report errors. This is due to the /// fact that the Pyth wire formatted is intended to allow for appending of new fields without /// breaking backwards compatibility. As such, it is possible that a newer version of the format /// will contain fields that are not known to the deserializer. This is not an error, and the /// deserializer will simply ignore these fields. pub fn from_slice<'de, B, T>(bytes: &'de [u8]) -> Result where T: Deserialize<'de>, B: ByteOrder, { let mut deserializer = Deserializer::::new(bytes); T::deserialize(&mut deserializer) } #[derive(Debug, Error)] pub enum DeserializerError { #[error("io error: {0}")] Io(#[from] std::io::Error), #[error("invalid utf8: {0}")] Utf8(#[from] std::str::Utf8Error), #[error("this type is not supported")] Unsupported, #[error("sequence too large ({0} elements), max supported is 255")] SequenceTooLarge(usize), #[error("message: {0}")] Message(Box), #[error("invalid enum variant, higher than expected variant range")] InvalidEnumVariant, #[error("eof")] Eof, } pub struct Deserializer<'de, B> where B: ByteOrder, { cursor: Cursor<&'de [u8]>, endian: std::marker::PhantomData, } impl serde::de::Error for DeserializerError { fn custom(msg: T) -> Self { DeserializerError::Message(msg.to_string().into_boxed_str()) } } impl<'de, B> Deserializer<'de, B> where B: ByteOrder, { pub fn new(buffer: &'de [u8]) -> Self { Self { cursor: Cursor::new(buffer), endian: std::marker::PhantomData, } } } impl<'de, B> serde::de::Deserializer<'de> for &'_ mut Deserializer<'de, B> where B: ByteOrder, { type Error = DeserializerError; fn deserialize_any(self, _visitor: V) -> Result where V: serde::de::Visitor<'de>, { Err(DeserializerError::Unsupported) } fn deserialize_ignored_any(self, _visitor: V) -> Result where V: serde::de::Visitor<'de>, { Err(DeserializerError::Unsupported) } fn deserialize_bool(self, visitor: V) -> Result where V: serde::de::Visitor<'de>, { let value = self.cursor.read_u8().map_err(DeserializerError::from)?; visitor.visit_bool(value != 0) } fn deserialize_i8(self, visitor: V) -> Result where V: serde::de::Visitor<'de>, { let value = self.cursor.read_i8().map_err(DeserializerError::from)?; visitor.visit_i8(value) } fn deserialize_i16(self, visitor: V) -> Result where V: serde::de::Visitor<'de>, { let value = self .cursor .read_i16::() .map_err(DeserializerError::from)?; visitor.visit_i16(value) } fn deserialize_i32(self, visitor: V) -> Result where V: serde::de::Visitor<'de>, { let value = self .cursor .read_i32::() .map_err(DeserializerError::from)?; visitor.visit_i32(value) } fn deserialize_i64(self, visitor: V) -> Result where V: serde::de::Visitor<'de>, { let value = self .cursor .read_i64::() .map_err(DeserializerError::from)?; visitor.visit_i64(value) } fn deserialize_i128(self, visitor: V) -> Result where V: serde::de::Visitor<'de>, { let value = self .cursor .read_i128::() .map_err(DeserializerError::from)?; visitor.visit_i128(value) } fn deserialize_u8(self, visitor: V) -> Result where V: serde::de::Visitor<'de>, { let value = self.cursor.read_u8().map_err(DeserializerError::from)?; visitor.visit_u8(value) } fn deserialize_u16(self, visitor: V) -> Result where V: serde::de::Visitor<'de>, { let value = self .cursor .read_u16::() .map_err(DeserializerError::from)?; visitor.visit_u16(value) } fn deserialize_u32(self, visitor: V) -> Result where V: serde::de::Visitor<'de>, { let value = self .cursor .read_u32::() .map_err(DeserializerError::from)?; visitor.visit_u32(value) } fn deserialize_u64(self, visitor: V) -> Result where V: serde::de::Visitor<'de>, { let value = self .cursor .read_u64::() .map_err(DeserializerError::from)?; visitor.visit_u64(value) } fn deserialize_u128(self, visitor: V) -> Result where V: serde::de::Visitor<'de>, { let value = self .cursor .read_u128::() .map_err(DeserializerError::from)?; visitor.visit_u128(value) } fn deserialize_f32(self, _visitor: V) -> Result where V: serde::de::Visitor<'de>, { Err(DeserializerError::Unsupported) } fn deserialize_f64(self, _visitor: V) -> Result where V: serde::de::Visitor<'de>, { Err(DeserializerError::Unsupported) } fn deserialize_char(self, _visitor: V) -> Result where V: serde::de::Visitor<'de>, { Err(DeserializerError::Unsupported) } fn deserialize_str(self, visitor: V) -> Result where V: serde::de::Visitor<'de>, { let len = self.cursor.read_u8().map_err(DeserializerError::from)? as u64; // We cannot use cursor read methods as they copy the data out of the internal buffer, // where we actually want a pointer into that buffer. So instead, we take the internal // representation (the underlying &[u8]) and slice it to get the data we want. We then // advance the cursor to simulate the read. // // Note that we do the advance first because otherwise we run into a immutable->mutable // borrow issue, but the reverse is fine. self.cursor .seek(SeekFrom::Current(len as i64)) .map_err(DeserializerError::from)?; let buf = { let buf = self.cursor.get_ref(); buf[(self.cursor.position() - len) as usize..] .get(..len as usize) .ok_or(DeserializerError::Eof)? }; visitor.visit_borrowed_str(std::str::from_utf8(buf).map_err(DeserializerError::from)?) } fn deserialize_string(self, visitor: V) -> Result where V: serde::de::Visitor<'de>, { self.deserialize_str(visitor) } fn deserialize_bytes(self, visitor: V) -> Result where V: serde::de::Visitor<'de>, { let len = self.cursor.read_u8().map_err(DeserializerError::from)? as u64; // See comment in deserialize_str for an explanation of this code. self.cursor .seek(SeekFrom::Current(len as i64)) .map_err(DeserializerError::from)?; let buf = { let buf = self.cursor.get_ref(); buf[(self.cursor.position() - len) as usize..] .get(..len as usize) .ok_or(DeserializerError::Eof)? }; visitor.visit_borrowed_bytes(buf) } fn deserialize_byte_buf(self, visitor: V) -> Result where V: serde::de::Visitor<'de>, { self.deserialize_bytes(visitor) } fn deserialize_option(self, _visitor: V) -> Result where V: serde::de::Visitor<'de>, { Err(DeserializerError::Unsupported) } fn deserialize_unit(self, visitor: V) -> Result where V: serde::de::Visitor<'de>, { visitor.visit_unit() } fn deserialize_unit_struct( self, _name: &'static str, visitor: V, ) -> Result where V: serde::de::Visitor<'de>, { visitor.visit_unit() } fn deserialize_newtype_struct( self, _name: &'static str, visitor: V, ) -> Result where V: serde::de::Visitor<'de>, { visitor.visit_newtype_struct(self) } fn deserialize_seq(self, visitor: V) -> Result where V: serde::de::Visitor<'de>, { let len = self.cursor.read_u8().map_err(DeserializerError::from)? as usize; visitor.visit_seq(SequenceIterator::new(self, len)) } fn deserialize_tuple(self, len: usize, visitor: V) -> Result where V: serde::de::Visitor<'de>, { visitor.visit_seq(SequenceIterator::new(self, len)) } fn deserialize_tuple_struct( self, _name: &'static str, len: usize, visitor: V, ) -> Result where V: serde::de::Visitor<'de>, { visitor.visit_seq(SequenceIterator::new(self, len)) } fn deserialize_map(self, visitor: V) -> Result where V: serde::de::Visitor<'de>, { let len = self.cursor.read_u8().map_err(DeserializerError::from)? as usize; visitor.visit_map(SequenceIterator::new(self, len)) } fn deserialize_struct( self, _name: &'static str, fields: &'static [&'static str], visitor: V, ) -> Result where V: serde::de::Visitor<'de>, { visitor.visit_seq(SequenceIterator::new(self, fields.len())) } fn deserialize_enum( self, _name: &'static str, variants: &'static [&'static str], visitor: V, ) -> Result where V: serde::de::Visitor<'de>, { // We read the discriminator here so that we can make the expected enum variant available // to the `visit_enum` call. let variant = self.cursor.read_u8().map_err(DeserializerError::from)?; if variant >= variants.len() as u8 { return Err(DeserializerError::InvalidEnumVariant); } visitor.visit_enum(Enum { de: self, variant }) } fn deserialize_identifier(self, _visitor: V) -> Result where V: serde::de::Visitor<'de>, { Err(DeserializerError::Unsupported) } } impl<'de, 'a, B: ByteOrder> VariantAccess<'de> for &'a mut Deserializer<'de, B> { type Error = DeserializerError; fn unit_variant(self) -> Result<(), Self::Error> { Ok(()) } fn newtype_variant_seed(self, seed: T) -> Result where T: serde::de::DeserializeSeed<'de>, { seed.deserialize(self) } fn tuple_variant(self, len: usize, visitor: V) -> Result where V: serde::de::Visitor<'de>, { visitor.visit_seq(SequenceIterator::new(self, len)) } fn struct_variant( self, fields: &'static [&'static str], visitor: V, ) -> Result where V: serde::de::Visitor<'de>, { visitor.visit_seq(SequenceIterator::new(self, fields.len())) } } struct SequenceIterator<'de, 'a, B: ByteOrder> { de: &'a mut Deserializer<'de, B>, len: usize, } impl<'de, 'a, B: ByteOrder> SequenceIterator<'de, 'a, B> { fn new(de: &'a mut Deserializer<'de, B>, len: usize) -> Self { Self { de, len } } } impl<'de, 'a, B: ByteOrder> SeqAccess<'de> for SequenceIterator<'de, 'a, B> { type Error = DeserializerError; fn next_element_seed(&mut self, seed: T) -> Result, Self::Error> where T: serde::de::DeserializeSeed<'de>, { if self.len == 0 { return Ok(None); } self.len -= 1; seed.deserialize(&mut *self.de).map(Some) } fn size_hint(&self) -> Option { Some(self.len) } } impl<'de, 'a, B: ByteOrder> MapAccess<'de> for SequenceIterator<'de, 'a, B> { type Error = DeserializerError; fn next_key_seed(&mut self, seed: K) -> Result, Self::Error> where K: serde::de::DeserializeSeed<'de>, { if self.len == 0 { return Ok(None); } self.len -= 1; seed.deserialize(&mut *self.de).map(Some) } fn next_value_seed(&mut self, seed: V) -> Result where V: serde::de::DeserializeSeed<'de>, { seed.deserialize(&mut *self.de) } fn size_hint(&self) -> Option { Some(self.len) } } struct Enum<'de, 'a, B: ByteOrder> { de: &'a mut Deserializer<'de, B>, variant: u8, } impl<'de, 'a, B: ByteOrder> EnumAccess<'de> for Enum<'de, 'a, B> { type Error = DeserializerError; type Variant = &'a mut Deserializer<'de, B>; fn variant_seed(self, _: V) -> Result<(V::Value, Self::Variant), Self::Error> where V: serde::de::DeserializeSeed<'de>, { // When serializing/deserializing, serde passes a variant_index into the handlers. We // currently write these as u8's and have already parsed' them during deserialize_enum // before we reach this point. // // Normally, when deserializing enum tags from a wire format that does not match the // expected size, we would use a u*.into_deserializer() to feed the already parsed // result into the visit_u64 visitor method during `__Field` deserialize. // // The problem with this however is during `visit_u64`, there is a possibility the // enum variant is not valid, which triggers Serde to return an `Unexpected` error. // These errors have the unfortunate side effect of triggering Rust including float // operations in the resulting binary, which breaks WASM environments. // // To work around this, we rely on the following facts: // // - variant_index in Serde is always 0 indexed and contiguous // - transmute_copy into a 0 sized type is safe // - transmute_copy is safe to cast into __Field as long as u8 >= size_of::<__Field>() // // This behaviour relies on serde not changing its enum deserializer generation, but // this would be a major backwards compatibility break for them so we should be safe. require!( size_of::() >= size_of::(), DeserializerError::InvalidEnumVariant ); Ok(( unsafe { std::mem::transmute_copy::(&self.variant) }, self.de, )) } }