feat: add serializers for pyth formats

This commit is contained in:
Reisen 2023-05-25 17:07:48 +02:00 committed by Reisen
parent 3e5b4bb095
commit af2d7b6e38
9 changed files with 1723 additions and 67 deletions

View File

@ -14,12 +14,14 @@ name = "pythnet_sdk"
bincode = "1.3.1"
borsh = "0.9.1"
bytemuck = { version = "1.11.0", features = ["derive"] }
byteorder = "1.4.3"
fast-math = "0.1"
hex = { version = "0.4.3", features = ["serde"] }
serde = { version = "1.0.144", features = ["derive"] }
serde_wormhole = { git = "https://github.com/wormhole-foundation/wormhole", tag = "v2.17.1"}
sha3 = "0.10.4"
slow_primes = "0.1.14"
thiserror = "1.0.40"
wormhole-sdk = { git = "https://github.com/wormhole-foundation/wormhole", tag = "v2.17.1" }
[dev-dependencies]

View File

@ -4,9 +4,9 @@
// #![feature(proc_macro_hygiene)]
use {
pythnet_sdk::pythnet::PYTH_PID,
serde_json::json,
solana_client::rpc_client::RpcClient,
solana_pyth::PYTH_PID,
solana_sdk::pubkey::Pubkey,
std::{
io::Write,

View File

@ -1,10 +1,9 @@
pub mod accumulators;
pub mod hashers;
pub mod payload;
pub mod wire;
pub mod wormhole;
pub(crate) type Pubkey = [u8; 32];
pub(crate) type PriceId = Pubkey;
/// Official Message Buffer Program Id
/// pubkey!("7Vbmv1jt4vyuqBZcpYPpnVhrqVe5e6ZPb6JxDcffRHUM");

View File

@ -1,64 +0,0 @@
//! Definition of the Accumulator Payload Formats.
//!
//! This module defines the data types that are injected into VAA's to be sent to other chains via
//! Wormhole. The wire format for these types must be backwards compatible and so all tyeps in this
//! module are expected to be append-only (for minor changes) and versioned for breaking changes.
use {
borsh::BorshSerialize,
serde::Serialize,
wormhole_sdk::Vaa,
};
// Transfer Format.
// --------------------------------------------------------------------------------
// This definition is what will be sent over the wire (I.E, pulled from PythNet and
// submitted to target chains).
#[derive(BorshSerialize, Serialize)]
pub struct AccumulatorProof<'a> {
magic: [u8; 4],
major_version: u8,
minor_version: u8,
trailing: &'a [u8],
proof: v1::Proof<'a>,
}
// Proof Format (V1)
// --------------------------------------------------------------------------------
// The definitions within each module can be updated with append-only data without
// requiring a new module to be defined. So for example, new accounts can be added
// to the end of `AccumulatorAccount` without moving to a `v1`.
pub mod v1 {
use super::*;
// A hash of some data.
pub type Hash = [u8; 32];
#[derive(Serialize)]
pub enum Proof<'a> {
WormholeMerkle {
proof: Vaa<VerifiedDigest>,
updates: &'a [MerkleProof<'a>],
},
}
#[derive(Serialize)]
pub struct VerifiedDigest {
magic: [u8; 4],
proof_type: u8,
len: u8,
storage_id: u64,
digest: Hash,
}
#[derive(Serialize)]
pub struct MerkleProof<'a> {
proof: &'a [Hash],
data: &'a [u8],
}
#[derive(Serialize)]
pub enum AccumulatorAccount {
Empty,
}
}

View File

@ -0,0 +1,306 @@
//! Pyth Wire Format
//!
//! Pyth uses a custom wire format when moving data between programs and chains. This module
//! provides the serialization and deserialization logic for this format as well as definitions of
//! data structures used in the PythNet ecosystem.
//!
//! See the `ser` submodule for a description of the Pyth Wire format.
use {
borsh::BorshSerialize,
serde::Serialize,
wormhole_sdk::Vaa,
};
pub mod array;
mod de;
mod prefixed_vec;
mod ser;
pub use {
de::{
from_slice,
Deserializer,
DeserializerError,
},
prefixed_vec::PrefixedVec,
ser::{
to_vec,
to_writer,
Serializer,
SerializerError,
},
};
// Transfer Format.
// --------------------------------------------------------------------------------
// This definition is what will be sent over the wire (I.E, pulled from PythNet and
// submitted to target chains).
#[derive(BorshSerialize, Serialize)]
pub struct AccumulatorProof<'a> {
magic: [u8; 4],
major_version: u8,
minor_version: u8,
trailing: &'a [u8],
proof: v1::Proof<'a>,
}
// Proof Format (V1)
// --------------------------------------------------------------------------------
// The definitions within each module can be updated with append-only data without
// requiring a new module to be defined. So for example, new accounts can be added
// to the end of `AccumulatorAccount` without moving to a `v1`.
pub mod v1 {
use super::*;
// A hash of some data.
pub type Hash = [u8; 32];
#[derive(Serialize)]
pub enum Proof<'a> {
WormholeMerkle {
proof: Vaa<VerifiedDigest>,
updates: &'a [MerkleProof<'a>],
},
}
#[derive(Serialize)]
pub struct VerifiedDigest {
magic: [u8; 4],
proof_type: u8,
len: u8,
storage_id: u64,
digest: Hash,
}
#[derive(Serialize)]
pub struct MerkleProof<'a> {
proof: &'a [Hash],
data: &'a [u8],
}
#[derive(Serialize)]
pub enum AccumulatorAccount {
Empty,
}
}
#[cfg(test)]
mod tests {
use crate::wire::{
array,
Deserializer,
PrefixedVec,
Serializer,
};
// Test the arbitrary fixed sized array serialization implementation.
#[test]
fn test_array_serde() {
// Serialize an array into a buffer.
let mut buffer = Vec::new();
let mut cursor = std::io::Cursor::new(&mut buffer);
let mut serializer: Serializer<_, byteorder::LE> = Serializer::new(&mut cursor);
array::serialize(&[1u8; 37], &mut serializer).unwrap();
// The result should not have been prefixed with a length byte.
assert_eq!(buffer.len(), 37);
// We should also be able to deserialize it back.
let mut deserializer = Deserializer::<byteorder::LE>::new(&buffer);
let deserialized: [u8; 37] = array::deserialize(&mut deserializer).unwrap();
// The deserialized array should be the same as the original.
assert_eq!(deserialized, [1u8; 37]);
}
// The array serializer should not interfere with other serializers. Here we
// check serde_json to make sure an array is written as expected.
#[test]
fn test_array_serde_json() {
// Serialize an array into a buffer.
let mut buffer = Vec::new();
let mut cursor = std::io::Cursor::new(&mut buffer);
let mut serialized = serde_json::Serializer::new(&mut cursor);
array::serialize(&[1u8; 7], &mut serialized).unwrap();
let result = String::from_utf8(buffer).unwrap();
assert_eq!(result, "[1,1,1,1,1,1,1]");
// Deserializing should also work.
let mut deserializer = serde_json::Deserializer::from_str(&result);
let deserialized: [u8; 7] = array::deserialize(&mut deserializer).unwrap();
assert_eq!(deserialized, [1u8; 7]);
}
// Golden Structure Test
//
// This test serializes a struct containing all the expected types we should
// be able to handle and checks the output is as expected. The reason I
// opted to serialize all in one struct instead of with separate tests is to
// ensure that the positioning of elements when in relation to others is
// also as expected. Especially when it comes to things such as nesting and
// length prefixing.
#[test]
fn test_pyth_serde() {
use serde::Serialize;
// Setup Serializer.
let mut buffer = Vec::new();
let mut cursor = std::io::Cursor::new(&mut buffer);
let mut serializer: Serializer<_, byteorder::LE> = Serializer::new(&mut cursor);
// Golden Test Value. As binary data can be fickle to understand in
// tests this should be kept commented with detail.
#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq)]
struct GoldenStruct<'a> {
// Test `unit` is not serialized to anything.
unit: (),
// Test `bool` is serialized to a single byte.
t_bool: bool,
// Test integer serializations.
t_u8: u8,
t_u16: u16,
t_u32: u32,
t_u64: u64,
// Test `str` is serialized to a variable length array.
t_string: String,
t_str: &'a str,
// Test `Vec` is serialized to a variable length array.
t_vec: Vec<u8>,
t_vec_empty: Vec<u8>,
t_vec_nested: Vec<Vec<u8>>,
t_vec_nested_empty: Vec<Vec<u8>>,
t_slice: &'a [u8],
t_slice_empty: &'a [u8],
// Test tuples serialize as expected.
t_tuple: (u8, u16, u32, u64, String, Vec<u8>, &'a [u8]),
t_tuple_nested: ((u8, u16), (u32, u64)),
// Test enum serializations.
t_enum_unit: GoldenEnum,
t_enum_newtype: GoldenEnum,
t_enum_tuple: GoldenEnum,
t_enum_struct: GoldenEnum,
// Test nested structs, which includes our PrefixedVec implementations work as we expect.
t_struct: GoldenNested<u8>,
t_prefixed: PrefixedVec<u16, u8>,
}
#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq)]
struct GoldenNested<T> {
nested_u8: T,
nested_tuple: (u8, u8),
}
#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq)]
enum GoldenEnum {
Unit,
Newtype(u8),
Tuple(u8, u16),
Struct { a: u8, b: u16 },
}
// Serialize the golden test value.
let golden_struct = GoldenStruct {
unit: (),
t_bool: true,
t_u8: 1,
t_u16: 2,
t_u32: 3,
t_u64: 4,
t_string: "9".to_string(),
t_str: "10",
t_vec: vec![11, 12, 13],
t_vec_empty: vec![],
t_vec_nested: vec![vec![14, 15, 16], vec![17, 18, 19]],
t_vec_nested_empty: vec![vec![], vec![]],
t_slice: &[20, 21, 22],
t_slice_empty: &[],
t_tuple: (
29,
30,
31,
32,
"10".to_string(),
vec![35, 36, 37],
&[38, 39, 40],
),
t_tuple_nested: ((41, 42), (43, 44)),
t_enum_unit: GoldenEnum::Unit,
t_enum_newtype: GoldenEnum::Newtype(45),
t_enum_tuple: GoldenEnum::Tuple(46, 47),
t_enum_struct: GoldenEnum::Struct { a: 48, b: 49 },
t_struct: GoldenNested {
nested_u8: 50,
nested_tuple: (51, 52),
},
t_prefixed: vec![0u8; 512].into(),
};
golden_struct.serialize(&mut serializer).unwrap();
// The serialized output should be as expected.
assert_eq!(
&buffer,
&[
1, // t_bool
1, // t_u8
2, 0, // t_u16
3, 0, 0, 0, // t_u32
4, 0, 0, 0, 0, 0, 0, 0, // t_u64
1, 57, // t_string
2, 49, 48, // t_str
3, 11, 12, 13, // t_vec
0, // t_vec_empty
2, 3, 14, 15, 16, 3, 17, 18, 19, // t_vec_nested
2, 0, 0, // t_vec_nested_empty
3, 20, 21, 22, // t_slice
0, // t_slice_empty
29, // t_tuple
30, 0, // u8
31, 0, 0, 0, // u16
32, 0, 0, 0, 0, 0, 0, 0, // u32
2, 49, 48, // "10"
3, 35, 36, 37, // [35, 36, 37]
3, 38, 39, 40, // [38, 39, 40]
41, 42, 0, 43, 0, 0, 0, 44, 0, 0, 0, 0, 0, 0, 0, // t_tuple_nested
0, // t_enum_unit
1, 45, // t_enum_newtype
2, 46, 47, 0, // t_enum_tuple
3, 48, 49, 0, // t_enum_struct
50, 51, 52, // t_nested
0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
]
);
// We should also be able to deserialize back into the original type.
assert_eq!(
golden_struct,
crate::wire::from_slice::<byteorder::LE, _>(&buffer).unwrap()
);
}
}

View File

@ -0,0 +1,97 @@
//! By default, serde does not know how to parse fixed length arrays of sizes
//! that aren't common (I.E: 32) Here we provide a module that can be used to
//! serialize arrays that relies on const generics.
//!
//! Usage:
//!
//! ```rust,ignore`
//! #[derive(Serialize)]
//! struct Example {
//! #[serde(with = "array")]
//! array: [u8; 55],
//! }
//! ```
use {
serde::{
Deserialize,
Serialize,
Serializer,
},
std::mem::MaybeUninit,
};
/// Serialize an array of size N using a const generic parameter to drive serialize_seq.
pub fn serialize<S, T, const N: usize>(array: &[T; N], serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
T: Serialize,
{
use serde::ser::SerializeTuple;
let mut seq = serializer.serialize_tuple(N)?;
array.iter().try_for_each(|e| seq.serialize_element(e))?;
seq.end()
}
/// A visitor that carries type-level information about the length of the array we want to
/// deserialize.
struct ArrayVisitor<T, const N: usize> {
_marker: std::marker::PhantomData<T>,
}
/// Implement a Visitor over our ArrayVisitor that knows how many times to
/// call next_element using the generic.
impl<'de, T, const N: usize> serde::de::Visitor<'de> for ArrayVisitor<T, N>
where
T: Deserialize<'de>,
{
type Value = [T; N];
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(formatter, "an array of length {}", N)
}
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
where
A: serde::de::SeqAccess<'de>,
{
// We use MaybeUninit to allocate the right amount of memory
// because we do not know if `T` has a constructor or a default.
// Without this we would have to allocate a Vec.
let mut array = MaybeUninit::<[T; N]>::uninit();
let ptr = array.as_mut_ptr() as *mut T;
let mut pos = 0;
while pos < N {
let next = seq
.next_element()?
.ok_or_else(|| serde::de::Error::invalid_length(pos, &self))?;
unsafe {
std::ptr::write(ptr.add(pos), next);
}
pos += 1;
}
// We only succeed if we fully filled the array. This prevents
// accidentally returning garbage.
if pos == N {
return Ok(unsafe { array.assume_init() });
}
Err(serde::de::Error::invalid_length(pos, &self))
}
}
/// Deserialize an array with an ArrayVisitor aware of `N` during deserialize.
pub fn deserialize<'de, D, T, const N: usize>(deserializer: D) -> Result<[T; N], D::Error>
where
D: serde::Deserializer<'de>,
T: serde::de::Deserialize<'de>,
{
deserializer.deserialize_tuple(
N,
ArrayVisitor {
_marker: std::marker::PhantomData,
},
)
}

View File

@ -0,0 +1,529 @@
//! 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::<LittleEndian, _>(&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 {
byteorder::{
ByteOrder,
ReadBytesExt,
},
serde::{
de::{
EnumAccess,
IntoDeserializer,
MapAccess,
SeqAccess,
VariantAccess,
},
Deserialize,
},
std::io::{
Cursor,
Seek,
SeekFrom,
},
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<T, DeserializerError>
where
T: Deserialize<'de>,
B: ByteOrder,
{
let mut deserializer = Deserializer::<B>::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<str>),
#[error("eof")]
Eof,
}
pub struct Deserializer<'de, B>
where
B: ByteOrder,
{
cursor: Cursor<&'de [u8]>,
endian: std::marker::PhantomData<B>,
}
impl serde::de::Error for DeserializerError {
fn custom<T: std::fmt::Display>(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<V>(self, _visitor: V) -> Result<V::Value, Self::Error>
where
V: serde::de::Visitor<'de>,
{
Err(DeserializerError::Unsupported)
}
fn deserialize_ignored_any<V>(self, _visitor: V) -> Result<V::Value, Self::Error>
where
V: serde::de::Visitor<'de>,
{
Err(DeserializerError::Unsupported)
}
fn deserialize_bool<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: serde::de::Visitor<'de>,
{
let value = self.cursor.read_u8().map_err(DeserializerError::from)?;
visitor.visit_bool(value != 0)
}
fn deserialize_i8<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: serde::de::Visitor<'de>,
{
let value = self.cursor.read_i8().map_err(DeserializerError::from)?;
visitor.visit_i8(value)
}
fn deserialize_i16<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: serde::de::Visitor<'de>,
{
let value = self
.cursor
.read_i16::<B>()
.map_err(DeserializerError::from)?;
visitor.visit_i16(value)
}
fn deserialize_i32<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: serde::de::Visitor<'de>,
{
let value = self
.cursor
.read_i32::<B>()
.map_err(DeserializerError::from)?;
visitor.visit_i32(value)
}
fn deserialize_i64<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: serde::de::Visitor<'de>,
{
let value = self
.cursor
.read_i64::<B>()
.map_err(DeserializerError::from)?;
visitor.visit_i64(value)
}
fn deserialize_u8<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: serde::de::Visitor<'de>,
{
let value = self.cursor.read_u8().map_err(DeserializerError::from)?;
visitor.visit_u8(value)
}
fn deserialize_u16<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: serde::de::Visitor<'de>,
{
let value = self
.cursor
.read_u16::<B>()
.map_err(DeserializerError::from)?;
visitor.visit_u16(value)
}
fn deserialize_u32<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: serde::de::Visitor<'de>,
{
let value = self
.cursor
.read_u32::<B>()
.map_err(DeserializerError::from)?;
visitor.visit_u32(value)
}
fn deserialize_u64<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: serde::de::Visitor<'de>,
{
let value = self
.cursor
.read_u64::<B>()
.map_err(DeserializerError::from)?;
visitor.visit_u64(value)
}
fn deserialize_f32<V>(self, _visitor: V) -> Result<V::Value, Self::Error>
where
V: serde::de::Visitor<'de>,
{
Err(DeserializerError::Unsupported)
}
fn deserialize_f64<V>(self, _visitor: V) -> Result<V::Value, Self::Error>
where
V: serde::de::Visitor<'de>,
{
Err(DeserializerError::Unsupported)
}
fn deserialize_char<V>(self, _visitor: V) -> Result<V::Value, Self::Error>
where
V: serde::de::Visitor<'de>,
{
Err(DeserializerError::Unsupported)
}
fn deserialize_str<V>(self, visitor: V) -> Result<V::Value, Self::Error>
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<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: serde::de::Visitor<'de>,
{
self.deserialize_str(visitor)
}
fn deserialize_bytes<V>(self, visitor: V) -> Result<V::Value, Self::Error>
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<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: serde::de::Visitor<'de>,
{
self.deserialize_bytes(visitor)
}
fn deserialize_option<V>(self, _visitor: V) -> Result<V::Value, Self::Error>
where
V: serde::de::Visitor<'de>,
{
Err(DeserializerError::Unsupported)
}
fn deserialize_unit<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: serde::de::Visitor<'de>,
{
visitor.visit_unit()
}
fn deserialize_unit_struct<V>(
self,
_name: &'static str,
visitor: V,
) -> Result<V::Value, Self::Error>
where
V: serde::de::Visitor<'de>,
{
visitor.visit_unit()
}
fn deserialize_newtype_struct<V>(
self,
_name: &'static str,
visitor: V,
) -> Result<V::Value, Self::Error>
where
V: serde::de::Visitor<'de>,
{
visitor.visit_newtype_struct(self)
}
fn deserialize_seq<V>(self, visitor: V) -> Result<V::Value, Self::Error>
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<V>(self, len: usize, visitor: V) -> Result<V::Value, Self::Error>
where
V: serde::de::Visitor<'de>,
{
visitor.visit_seq(SequenceIterator::new(self, len))
}
fn deserialize_tuple_struct<V>(
self,
_name: &'static str,
len: usize,
visitor: V,
) -> Result<V::Value, Self::Error>
where
V: serde::de::Visitor<'de>,
{
visitor.visit_seq(SequenceIterator::new(self, len))
}
fn deserialize_map<V>(self, visitor: V) -> Result<V::Value, Self::Error>
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<V>(
self,
_name: &'static str,
fields: &'static [&'static str],
visitor: V,
) -> Result<V::Value, Self::Error>
where
V: serde::de::Visitor<'de>,
{
visitor.visit_seq(SequenceIterator::new(self, fields.len()))
}
fn deserialize_enum<V>(
self,
_name: &'static str,
_variants: &'static [&'static str],
visitor: V,
) -> Result<V::Value, Self::Error>
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)?;
visitor.visit_enum(Enum { de: self, variant })
}
fn deserialize_identifier<V>(self, _visitor: V) -> Result<V::Value, Self::Error>
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<T>(self, seed: T) -> Result<T::Value, Self::Error>
where
T: serde::de::DeserializeSeed<'de>,
{
seed.deserialize(self)
}
fn tuple_variant<V>(self, len: usize, visitor: V) -> Result<V::Value, Self::Error>
where
V: serde::de::Visitor<'de>,
{
visitor.visit_seq(SequenceIterator::new(self, len))
}
fn struct_variant<V>(
self,
fields: &'static [&'static str],
visitor: V,
) -> Result<V::Value, Self::Error>
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<T>(&mut self, seed: T) -> Result<Option<T::Value>, 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<usize> {
Some(self.len)
}
}
impl<'de, 'a, B: ByteOrder> MapAccess<'de> for SequenceIterator<'de, 'a, B> {
type Error = DeserializerError;
fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, 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<V>(&mut self, seed: V) -> Result<V::Value, Self::Error>
where
V: serde::de::DeserializeSeed<'de>,
{
seed.deserialize(&mut *self.de)
}
fn size_hint(&self) -> Option<usize> {
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<V>(self, seed: V) -> Result<(V::Value, Self::Variant), Self::Error>
where
V: serde::de::DeserializeSeed<'de>,
{
// This is a trick to get around Serde's expectation of a u32 for discriminants. The `seed`
// here is the generated `Field` type from the `#[derive(Deserialize)]` macro. If we
// attempt to deserialize this normally it will attempt to deserialize a u32 and fail.
// Instead we take the already parsed variant and generate a deserializer for that which
// will feed the u8 wire format into the deserialization logic, which overrides the default
// deserialize call on the the `Field` type.
seed.deserialize(self.variant.into_deserializer())
.map(|v| (v, self.de))
}
}

View File

@ -0,0 +1,202 @@
use serde::{
de::DeserializeSeed,
ser::{
SerializeSeq,
SerializeStruct,
},
Deserialize,
Serialize,
};
/// PrefixlessVec overrides the serialization to _not_ write a length prefix.
#[derive(Clone, Debug, Hash, PartialEq, PartialOrd)]
struct PrefixlessVec<T> {
data: Vec<T>,
}
impl<T> Serialize for PrefixlessVec<T>
where
T: Serialize,
{
#[inline]
fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
let mut seq = serializer.serialize_seq(None)?;
for item in &self.data {
seq.serialize_element(item)?;
}
seq.end()
}
}
struct PrefixlessSeed<T> {
__phantom: std::marker::PhantomData<T>,
len: usize,
}
/// We implement DeserializeSeed for PrefixlessSeed which is aware of the len that should be read
/// for the Vec, this len would have been found previously during parsing the PrefixedVec which
/// will drive this deserializer forward. The result is a PrefixlessVec<T> which is intended to
/// be read by the PrefixedVec deserializer.
impl<'de, T> DeserializeSeed<'de> for PrefixlessSeed<T>
where
T: Deserialize<'de>,
{
type Value = PrefixlessVec<T>;
fn deserialize<D: serde::Deserializer<'de>>(
self,
deserializer: D,
) -> Result<Self::Value, D::Error> {
struct PrefixlessVecVisitor<T> {
len: usize,
__phantom: std::marker::PhantomData<T>,
}
impl<'de, T> serde::de::Visitor<'de> for PrefixlessVecVisitor<T>
where
T: Deserialize<'de>,
{
type Value = PrefixlessVec<T>;
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
formatter.write_str("struct PrefixlessVec")
}
#[inline]
fn visit_seq<V>(self, mut seq: V) -> Result<PrefixlessVec<T>, V::Error>
where
V: serde::de::SeqAccess<'de>,
{
let mut data = Vec::with_capacity(self.len);
for i in 0..self.len {
data.push(
seq.next_element::<T>()?
.ok_or_else(|| serde::de::Error::invalid_length(i, &"PrefixlessVec"))?,
);
}
Ok(PrefixlessVec { data })
}
}
deserializer.deserialize_tuple(
self.len,
PrefixlessVecVisitor {
len: self.len,
__phantom: std::marker::PhantomData,
},
)
}
}
/// PrefixedVec allows overriding the default u8 size of the length prefix for a Vec.
///
/// This is useful when the size of a Vec is greater than 255 and we wish to override the
/// Pyth serialization logic to use a u16 etc instead. This works by serializing the Vec
/// as a struct with a len field with the overridden type, when combined with PrefixlessVec
/// below the combination of `{ "len": L, "data": [T] }` is serialized as expected in the
/// wire format.
///
/// For non-Pyth formats this results in a struct which is the correct way to interpret our
/// data on chain anyway.
#[derive(Clone, Debug, Hash, PartialEq, PartialOrd)]
pub struct PrefixedVec<L, T> {
__phantom: std::marker::PhantomData<L>,
data: PrefixlessVec<T>,
}
impl<T, L> From<Vec<T>> for PrefixedVec<L, T> {
fn from(data: Vec<T>) -> Self {
Self {
__phantom: std::marker::PhantomData,
data: PrefixlessVec { data },
}
}
}
impl<L, T> Serialize for PrefixedVec<L, T>
where
T: Serialize,
L: Serialize,
L: TryFrom<usize>,
<L as TryFrom<usize>>::Error: std::fmt::Debug,
{
#[inline]
fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
let len: L = L::try_from(self.data.data.len()).unwrap();
let mut st = serializer.serialize_struct("SizedVec", 1)?;
st.serialize_field("len", &len)?;
st.serialize_field("data", &self.data)?;
st.end()
}
}
impl<'de, L, T> Deserialize<'de> for PrefixedVec<L, T>
where
T: Deserialize<'de>,
L: Deserialize<'de>,
L: Into<usize>,
L: Copy,
{
#[inline]
fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
#[derive(Deserialize)]
#[serde(field_identifier, rename_all = "lowercase")]
enum Field {
Len,
Data,
}
struct PrefixedVecVisitor<L, T> {
__phantom: std::marker::PhantomData<(L, T)>,
}
impl<'de, L, T> serde::de::Visitor<'de> for PrefixedVecVisitor<L, T>
where
T: Deserialize<'de>,
L: Deserialize<'de>,
L: Into<usize>,
L: Copy,
{
type Value = PrefixedVec<L, T>;
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
formatter.write_str("struct PrefixedVec")
}
#[inline]
fn visit_seq<V>(self, mut seq: V) -> Result<PrefixedVec<L, T>, V::Error>
where
V: serde::de::SeqAccess<'de>,
{
// First we parse the expected size type from the wire format.
let len: usize = seq
.next_element::<L>()?
.ok_or_else(|| serde::de::Error::invalid_length(0, &"PrefixlessVec"))?
.into();
// We now rely on the PrefixlessVec deserializer to do the rest of the work. We
// need to use the PrefixlessSeed to pass the expected size to the deserializer.
let data = seq
.next_element_seed(PrefixlessSeed {
__phantom: std::marker::PhantomData,
len,
})?
.ok_or_else(|| serde::de::Error::invalid_length(1, &"PrefixlessVec"))?;
Ok(PrefixedVec {
__phantom: std::marker::PhantomData,
data,
})
}
}
deserializer.deserialize_struct(
"PrefixedVec",
&["len", "data"],
PrefixedVecVisitor {
__phantom: std::marker::PhantomData,
},
)
}
}

View File

@ -0,0 +1,585 @@
//! A module defining serde serialize for a simple Rust struct-like message format. The format will
//! read Rust types exactly the size they are, and reads sequences by reading a u8 length followed
//! by a count of the elements of the vector.
//!
//! TL;DR: How to Use
//! ================================================================================
//!
//! ```rust,ignore
//! #[derive(Serialize)]
//! struct ExampleStruct {
//! a: (),
//! b: bool,
//! c: u8,
//! ...,
//! }
//!
//! let mut buf = Vec::new();
//! pythnet_sdk::ser::to_writer(&mut buf, &ExampleStruct { ... }).unwrap();
//! let result = pythnet_sdk::ser::to_vec(&ExampleStruct { ... }).unwrap();
//! ```
//!
//! A quick primer on `serde::Serialize`:
//! ================================================================================
//!
//! Given some type `T`, the `serde::Serialize` derives an implementation with a `serialize` method
//! that calls all the relevant `serialize_` calls defined in this file, so for example, given the
//! following types:
//!
//! ```rust,ignore
//! #[derive(Serialize)]
//! enum ExampleEnum {
//! A,
//! B(u8),
//! C(u8, u8),
//! D { a: u8, b: u8 },
//! }
//!
//! #[derive(Serialize)]
//! struct ExampleStruct {
//! a: (),
//! b: bool,
//! c: u8,
//! d: &str,
//! e: ExampleEnum
//! }
//! ```
//!
//! The macro will expand into (a more complicated but equivelent) version of:
//!
//! ```rust,ignore
//! impl serde::Serialize for ExampleEnum {
//! fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
//! match self {
//! ExampleEnum::A => serializer.serialize_unit_variant("ExampleEnum", 0, "A"),
//! ExampleEnum::B(v) => serializer.serialize_newtype_variant("ExampleEnum", 1, "B", v),
//! ExampleEnum::C(v0, v1) => serializer.serialize_tuple_variant("ExampleEnum", 2, "C", (v0, v1)),
//! ExampleEnum::D { a, b } => serializer.serialize_struct_variant("ExampleEnum", 3, "D", 2, "a", a, "b", b),
//! }
//! }
//! }
//!
//! impl serde::Serialize for ExampleStruct {
//! fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
//! let mut state = serializer.serialize_struct("ExampleStruct", 5)?;
//! state.serialize_field("a", &self.a)?;
//! state.serialize_field("b", &self.b)?;
//! state.serialize_field("c", &self.c)?;
//! state.serialize_field("d", &self.d)?;
//! state.serialize_field("e", &self.e)?;
//! state.end()
//! }
//! }
//! ```
//!
//! Note that any parser can be passed in, which gives the serializer the ability to serialize to
//! any format we desire as long as there is a `Serializer` implementation for it. With aggressive
//! inlining, the compiler will be able to optimize away the intermediate state objects and calls
//! to `serialize_field` and `serialize_*_variant` and the final result of our parser will have
//! very close to equivelent performance to a hand written implementation.
//!
//! The Pyth Serialization Format
//! ================================================================================
//!
//! Pyth has various data formats that are serialized in compact forms to make storing or passing
//! cross-chain cheaper. So far all these formats follow a similar pattern and so this serializer
//! is designed to be able to provide a canonical implementation for all of them.
//!
//!
//! Format Spec:
//! --------------------------------------------------------------------------------
//!
//! Integers:
//!
//! - `{u,i}8` are serialized as a single byte
//! - `{u,i}16/32/64` are serialized as bytes specified by the parser endianess type param.
//! - `{u,i}128` is not supported.
//!
//! Floats:
//!
//! - `f32/64/128` are not supported due to different chains having different float formats.
//!
//! Strings:
//!
//! - `&str` is serialized as a u8 length followed by the bytes of the string.
//! - `String` is serialized as a u8 length followed by the bytes of the string.
//!
//! Sequences:
//!
//! - `Vec<T>` is serialized as a u8 length followed by the serialized elements of the vector.
//! - `&[T]` is serialized as a u8 length followed by the serialized elements of the slice.
//!
//! Enums:
//!
//! - `enum` is serialized as a u8 variant index followed by the serialized variant data.
//! - `Option<T>` is serialized as a u8 variant index followed by the serialized variant data.
//!
//! Structs:
//!
//! - `struct` is serialized as the serialized fields of the struct in order.
//!
//! Tuples:
//!
//! - `tuple` is serialized as the serialized elements of the tuple in order.
//!
//! Unit:
//!
//! - `()` is serialized as nothing.
//!
//!
//! Example Usage
//! --------------------------------------------------------------------------------
//!
//! ```rust,ignore
//! fn example(data: &[u8]) {
//! let mut buf = Vec::new();
//! let mut cur = Cursor::new(&mut buf);
//! let mut des = Deserializer::new(&mut cur);
//! let mut result = des.deserialize::<ExampleStruct>(data).unwrap();
//! ...
//! }
//! ```
use {
byteorder::{
ByteOrder,
WriteBytesExt,
},
serde::{
ser::{
SerializeMap,
SerializeSeq,
SerializeStruct,
SerializeStructVariant,
SerializeTuple,
SerializeTupleStruct,
SerializeTupleVariant,
},
Serialize,
},
std::{
fmt::Display,
io::Write,
},
thiserror::Error,
};
pub fn to_writer<T, W, B>(writer: W, value: &T) -> Result<(), SerializerError>
where
T: Serialize,
W: Write,
B: ByteOrder,
{
value.serialize(&mut Serializer::<_, B>::new(writer))?;
Ok(())
}
pub fn to_vec<T, B>(value: &T) -> Result<Vec<u8>, SerializerError>
where
T: Serialize,
B: ByteOrder,
{
let mut buf = Vec::new();
to_writer::<T, _, B>(&mut buf, value)?;
Ok(buf)
}
#[derive(Debug, Error)]
pub enum SerializerError {
#[error("io error: {0}")]
Io(#[from] std::io::Error),
#[error("this type is not supported")]
Unsupported,
#[error("sequence too large ({0} elements), max supported is 255")]
SequenceTooLarge(usize),
#[error("sequence length must be known before serializing")]
SequenceLengthUnknown,
#[error("enum variant {0}::{1} cannot be parsed as `u8`: {2}")]
InvalidEnumVariant(&'static str, u32, &'static str),
#[error("message: {0}")]
Message(Box<str>),
}
/// A type for Pyth's common serialization format. Note that a ByteOrder type param is required as
/// we serialize in both big and little endian depending on different use-cases.
#[derive(Clone)]
pub struct Serializer<W: Write, B: ByteOrder> {
writer: W,
_endian: std::marker::PhantomData<B>,
}
impl serde::ser::Error for SerializerError {
fn custom<T: Display>(msg: T) -> Self {
SerializerError::Message(msg.to_string().into_boxed_str())
}
}
impl<W: Write, B: ByteOrder> Serializer<W, B> {
pub fn new(writer: W) -> Self {
Self {
writer,
_endian: std::marker::PhantomData,
}
}
}
impl<'a, W: Write, B: ByteOrder> serde::Serializer for &'a mut Serializer<W, B> {
type Ok = ();
type Error = SerializerError;
// Serde uses different types for different parse targets to allow for different
// implementations. We only support one target, so we can set all these to `Self`
// and implement those traits on the same type.
type SerializeSeq = Self;
type SerializeTuple = Self;
type SerializeTupleStruct = Self;
type SerializeTupleVariant = Self;
type SerializeMap = Self;
type SerializeStruct = Self;
type SerializeStructVariant = Self;
#[inline]
fn serialize_bool(self, v: bool) -> Result<Self::Ok, Self::Error> {
self.writer
.write_all(&[v as u8])
.map_err(SerializerError::from)
}
#[inline]
fn serialize_i8(self, v: i8) -> Result<Self::Ok, Self::Error> {
self.writer
.write_all(&[v as u8])
.map_err(SerializerError::from)
}
#[inline]
fn serialize_i16(self, v: i16) -> Result<Self::Ok, Self::Error> {
self.writer.write_i16::<B>(v).map_err(SerializerError::from)
}
#[inline]
fn serialize_i32(self, v: i32) -> Result<Self::Ok, Self::Error> {
self.writer.write_i32::<B>(v).map_err(SerializerError::from)
}
#[inline]
fn serialize_i64(self, v: i64) -> Result<Self::Ok, Self::Error> {
self.writer.write_i64::<B>(v).map_err(SerializerError::from)
}
#[inline]
fn serialize_u8(self, v: u8) -> Result<Self::Ok, Self::Error> {
self.writer.write_all(&[v]).map_err(SerializerError::from)
}
#[inline]
fn serialize_u16(self, v: u16) -> Result<Self::Ok, Self::Error> {
self.writer.write_u16::<B>(v).map_err(SerializerError::from)
}
#[inline]
fn serialize_u32(self, v: u32) -> Result<Self::Ok, Self::Error> {
self.writer.write_u32::<B>(v).map_err(SerializerError::from)
}
#[inline]
fn serialize_u64(self, v: u64) -> Result<Self::Ok, Self::Error> {
self.writer.write_u64::<B>(v).map_err(SerializerError::from)
}
#[inline]
fn serialize_f32(self, _: f32) -> Result<Self::Ok, Self::Error> {
Err(SerializerError::Unsupported)
}
#[inline]
fn serialize_f64(self, _: f64) -> Result<Self::Ok, Self::Error> {
Err(SerializerError::Unsupported)
}
#[inline]
fn serialize_char(self, _: char) -> Result<Self::Ok, Self::Error> {
Err(SerializerError::Unsupported)
}
#[inline]
fn serialize_str(self, v: &str) -> Result<Self::Ok, Self::Error> {
let len = u8::try_from(v.len()).map_err(|_| SerializerError::SequenceTooLarge(v.len()))?;
self.writer.write_all(&[len])?;
self.writer
.write_all(v.as_bytes())
.map_err(SerializerError::from)
}
#[inline]
fn serialize_bytes(self, v: &[u8]) -> Result<Self::Ok, Self::Error> {
let len = u8::try_from(v.len()).map_err(|_| SerializerError::SequenceTooLarge(v.len()))?;
self.writer.write_all(&[len])?;
self.writer.write_all(v).map_err(SerializerError::from)
}
#[inline]
fn serialize_none(self) -> Result<Self::Ok, Self::Error> {
Err(SerializerError::Unsupported)
}
#[inline]
fn serialize_some<T: ?Sized + Serialize>(self, value: &T) -> Result<Self::Ok, Self::Error> {
value.serialize(self)
}
#[inline]
fn serialize_unit(self) -> Result<Self::Ok, Self::Error> {
Ok(())
}
#[inline]
fn serialize_unit_struct(self, _name: &'static str) -> Result<Self::Ok, Self::Error> {
Ok(())
}
#[inline]
fn serialize_unit_variant(
self,
name: &'static str,
variant_index: u32,
variant: &'static str,
) -> Result<Self::Ok, Self::Error> {
let variant: u8 = variant_index
.try_into()
.map_err(|_| SerializerError::InvalidEnumVariant(name, variant_index, variant))?;
self.writer
.write_all(&[variant])
.map_err(SerializerError::from)
}
#[inline]
fn serialize_newtype_struct<T: ?Sized + Serialize>(
self,
_name: &'static str,
value: &T,
) -> Result<Self::Ok, Self::Error> {
value.serialize(self)
}
#[inline]
fn serialize_newtype_variant<T: ?Sized + Serialize>(
self,
name: &'static str,
variant_index: u32,
variant: &'static str,
value: &T,
) -> Result<Self::Ok, Self::Error> {
let variant: u8 = variant_index
.try_into()
.map_err(|_| SerializerError::InvalidEnumVariant(name, variant_index, variant))?;
self.writer.write_all(&[variant])?;
value.serialize(self)
}
/// We use the fact that len can be None here to optionally not prefix a sequence when we
/// serialize. This allows us to disable length prefixing optionally when writing serializers
/// by hand. See `PrefixlessVec` for an example.
#[inline]
fn serialize_seq(self, len: Option<usize>) -> Result<Self::SerializeSeq, Self::Error> {
if let Some(len) = len {
let len = u8::try_from(len).map_err(|_| SerializerError::SequenceTooLarge(len))?;
self.writer.write_all(&[len])?;
}
Ok(self)
}
#[inline]
fn serialize_tuple(self, _len: usize) -> Result<Self::SerializeTuple, Self::Error> {
Ok(self)
}
#[inline]
fn serialize_tuple_struct(
self,
_name: &'static str,
_len: usize,
) -> Result<Self::SerializeTupleStruct, Self::Error> {
Ok(self)
}
#[inline]
fn serialize_tuple_variant(
self,
name: &'static str,
variant_index: u32,
variant: &'static str,
_len: usize,
) -> Result<Self::SerializeTupleVariant, Self::Error> {
let variant: u8 = variant_index
.try_into()
.map_err(|_| SerializerError::InvalidEnumVariant(name, variant_index, variant))?;
self.writer.write_all(&[variant])?;
Ok(self)
}
#[inline]
fn serialize_map(self, len: Option<usize>) -> Result<Self::SerializeMap, Self::Error> {
let len = len
.ok_or(SerializerError::SequenceLengthUnknown)
.and_then(|len| {
u8::try_from(len).map_err(|_| SerializerError::SequenceTooLarge(len))
})?;
self.writer.write_all(&[len])?;
Ok(self)
}
#[inline]
fn serialize_struct(
self,
_name: &'static str,
_len: usize,
) -> Result<Self::SerializeStruct, Self::Error> {
Ok(self)
}
#[inline]
fn serialize_struct_variant(
self,
name: &'static str,
variant_index: u32,
variant: &'static str,
_len: usize,
) -> Result<Self::SerializeStructVariant, Self::Error> {
let variant: u8 = variant_index
.try_into()
.map_err(|_| SerializerError::InvalidEnumVariant(name, variant_index, variant))?;
self.writer.write_all(&[variant])?;
Ok(self)
}
fn is_human_readable(&self) -> bool {
false
}
fn collect_str<T: ?Sized + Display>(self, value: &T) -> Result<Self::Ok, Self::Error> {
self.serialize_str(&value.to_string())
}
}
impl<'a, W: Write, B: ByteOrder> SerializeSeq for &'a mut Serializer<W, B> {
type Ok = ();
type Error = SerializerError;
#[inline]
fn serialize_element<T: ?Sized + Serialize>(&mut self, value: &T) -> Result<(), Self::Error> {
value.serialize(&mut **self)
}
fn end(self) -> Result<Self::Ok, Self::Error> {
Ok(())
}
}
impl<'a, W: Write, B: ByteOrder> SerializeTuple for &'a mut Serializer<W, B> {
type Ok = ();
type Error = SerializerError;
#[inline]
fn serialize_element<T: ?Sized + Serialize>(&mut self, value: &T) -> Result<(), Self::Error> {
value.serialize(&mut **self)
}
fn end(self) -> Result<Self::Ok, Self::Error> {
Ok(())
}
}
impl<'a, W: Write, B: ByteOrder> SerializeTupleStruct for &'a mut Serializer<W, B> {
type Ok = ();
type Error = SerializerError;
#[inline]
fn serialize_field<T: ?Sized + Serialize>(&mut self, value: &T) -> Result<(), Self::Error> {
value.serialize(&mut **self)
}
fn end(self) -> Result<Self::Ok, Self::Error> {
Ok(())
}
}
impl<'a, W: Write, B: ByteOrder> SerializeTupleVariant for &'a mut Serializer<W, B> {
type Ok = ();
type Error = SerializerError;
#[inline]
fn serialize_field<T: ?Sized + Serialize>(&mut self, value: &T) -> Result<(), Self::Error> {
value.serialize(&mut **self)
}
fn end(self) -> Result<Self::Ok, Self::Error> {
Ok(())
}
}
impl<'a, W: Write, B: ByteOrder> SerializeMap for &'a mut Serializer<W, B> {
type Ok = ();
type Error = SerializerError;
#[inline]
fn serialize_key<T: ?Sized + Serialize>(&mut self, key: &T) -> Result<(), Self::Error> {
key.serialize(&mut **self)
}
#[inline]
fn serialize_value<T: ?Sized + Serialize>(&mut self, value: &T) -> Result<(), Self::Error> {
value.serialize(&mut **self)
}
fn end(self) -> Result<Self::Ok, Self::Error> {
Ok(())
}
}
impl<'a, W: Write, B: ByteOrder> SerializeStruct for &'a mut Serializer<W, B> {
type Ok = ();
type Error = SerializerError;
#[inline]
fn serialize_field<T: ?Sized + Serialize>(
&mut self,
_key: &'static str,
value: &T,
) -> Result<(), Self::Error> {
value.serialize(&mut **self)
}
fn end(self) -> Result<Self::Ok, Self::Error> {
Ok(())
}
}
impl<'a, W: Write, B: ByteOrder> SerializeStructVariant for &'a mut Serializer<W, B> {
type Ok = ();
type Error = SerializerError;
#[inline]
fn serialize_field<T: ?Sized + Serialize>(
&mut self,
_key: &'static str,
value: &T,
) -> Result<(), Self::Error> {
value.serialize(&mut **self)
}
fn end(self) -> Result<Self::Ok, Self::Error> {
Ok(())
}
}