feat: add serializers for pyth formats
This commit is contained in:
parent
3e5b4bb095
commit
af2d7b6e38
|
@ -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]
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
}
|
|
@ -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()
|
||||
);
|
||||
}
|
||||
}
|
|
@ -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,
|
||||
},
|
||||
)
|
||||
}
|
|
@ -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))
|
||||
}
|
||||
}
|
|
@ -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,
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
|
@ -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(())
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue