From e8cb366408131142a6cd37d83467f1b9de18a791 Mon Sep 17 00:00:00 2001 From: "Brian J. Tarricone" Date: Thu, 7 Mar 2024 00:55:17 -0800 Subject: [PATCH] wip: Add PayloadValue type This will act as a replacement for serde_json::Value that can also hold binary payloads. --- socketioxide/src/lib.rs | 2 + socketioxide/src/payload_value/binary.rs | 80 +++ socketioxide/src/payload_value/de.rs | 737 +++++++++++++++++++++++ socketioxide/src/payload_value/from.rs | 99 +++ socketioxide/src/payload_value/mod.rs | 409 +++++++++++++ socketioxide/src/payload_value/ser.rs | 590 ++++++++++++++++++ 6 files changed, 1917 insertions(+) create mode 100644 socketioxide/src/payload_value/binary.rs create mode 100644 socketioxide/src/payload_value/de.rs create mode 100644 socketioxide/src/payload_value/from.rs create mode 100644 socketioxide/src/payload_value/mod.rs create mode 100644 socketioxide/src/payload_value/ser.rs diff --git a/socketioxide/src/lib.rs b/socketioxide/src/lib.rs index 80144cd2..c5b62e0a 100644 --- a/socketioxide/src/lib.rs +++ b/socketioxide/src/lib.rs @@ -275,11 +275,13 @@ pub use engineioxide::TransportType; pub use errors::{AckError, AdapterError, BroadcastError, DisconnectError, SendError, SocketError}; pub use handler::extract; pub use io::{SocketIo, SocketIoBuilder, SocketIoConfig}; +pub use payload_value::{binary::Binary, PayloadValue}; mod client; mod errors; mod io; mod ns; +mod payload_value; /// Socket.IO protocol version. /// It is accessible with the [`Socket::protocol`](socket::Socket) method or as an extractor diff --git a/socketioxide/src/payload_value/binary.rs b/socketioxide/src/payload_value/binary.rs new file mode 100644 index 00000000..02edb443 --- /dev/null +++ b/socketioxide/src/payload_value/binary.rs @@ -0,0 +1,80 @@ +use std::ops::{Deref, DerefMut}; + +use serde::de; + +#[derive(Debug, Clone, PartialEq)] +pub struct Binary(Vec); + +impl From> for Binary { + fn from(value: Vec) -> Self { + Binary(value) + } +} + +impl<'a> From<&'a [u8]> for Binary { + fn from(value: &'a [u8]) -> Self { + Binary(value.to_vec()) + } +} + +impl From for Vec { + fn from(value: Binary) -> Self { + value.0 + } +} + +impl Deref for Binary { + type Target = Vec; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl DerefMut for Binary { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } +} + +impl serde::Serialize for Binary { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_bytes(self.0.as_slice()) + } +} + +impl<'de> serde::Deserialize<'de> for Binary { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + struct BinaryVisitor; + + impl<'de> de::Visitor<'de> for BinaryVisitor { + type Value = Binary; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + formatter.write_str("binary data") + } + + fn visit_bytes(self, v: &[u8]) -> Result + where + E: de::Error, + { + Ok(Binary(v.to_owned())) + } + + fn visit_str(self, v: &str) -> Result + where + E: de::Error, + { + Ok(Binary(v.as_bytes().to_owned())) + } + } + + deserializer.deserialize_any(BinaryVisitor) + } +} diff --git a/socketioxide/src/payload_value/de.rs b/socketioxide/src/payload_value/de.rs new file mode 100644 index 00000000..10623597 --- /dev/null +++ b/socketioxide/src/payload_value/de.rs @@ -0,0 +1,737 @@ +use std::{borrow::Cow, collections::HashMap, vec}; + +use serde::{ + de::{ + self, EnumAccess, Error, IntoDeserializer, MapAccess, SeqAccess, Unexpected, VariantAccess, + }, + forward_to_deserialize_any, +}; + +use super::PayloadValue; + +// For Deserializer impl for PayloadValue +macro_rules! impl_deser_number { + ($method:ident) => { + fn $method(self, visitor: V) -> Result + where + V: de::Visitor<'de>, + { + match self { + PayloadValue::Number(n) => n.deserialize_any(visitor), + _ => Err(serde_json::Error::invalid_type(self.unexpected(), &visitor)), + } + } + }; +} + +// For Deserializer impl for MapKeyDeserializer +macro_rules! impl_deser_numeric_key { + ($method:ident) => { + fn $method(self, visitor: V) -> Result + where + V: de::Visitor<'de>, + { + let reader = VecRead::from(self.key); + let mut deser = serde_json::Deserializer::from_reader(reader); + let number = deser.$method(visitor)?; + let _ = deser + .end() + .map_err(|_| serde_json::Error::custom("expected numeric map key"))?; + Ok(number) + } + }; +} + +struct VecRead { + vec: Vec, + pos: usize, +} + +impl<'any> From> for VecRead { + fn from(value: Cow<'any, str>) -> Self { + Self { + vec: value.to_string().into_bytes(), + pos: 0, + } + } +} + +impl std::io::Read for VecRead { + fn read(&mut self, mut buf: &mut [u8]) -> std::io::Result { + use std::io::Write; + + let to_write = std::cmp::min(buf.len(), self.vec.len() - self.pos); + if to_write > 0 { + let written = buf.write(&self.vec[self.pos..to_write])?; + self.pos += to_write; + Ok(written) + } else { + Ok(0) + } + } +} + +impl PayloadValue { + fn unexpected<'a>(&'a self) -> Unexpected<'a> { + match self { + PayloadValue::Null => Unexpected::Unit, + PayloadValue::Bool(b) => Unexpected::Bool(*b), + PayloadValue::Number(n) => { + if let Some(n) = n.as_u64() { + Unexpected::Unsigned(n) + } else if let Some(n) = n.as_i64() { + Unexpected::Signed(n) + } else if let Some(n) = n.as_f64() { + Unexpected::Float(n) + } else { + Unexpected::Other("non-unsigned, non-signed, non-float number") + } + } + PayloadValue::String(s) => Unexpected::Str(s), + PayloadValue::Binary(_, data) => Unexpected::Bytes(data), + PayloadValue::Array(_) => Unexpected::Seq, + PayloadValue::Object(_) => Unexpected::Map, + } + } +} + +impl<'de> serde::Deserializer<'de> for PayloadValue { + type Error = serde_json::Error; + + fn deserialize_any(self, visitor: V) -> Result + where + V: de::Visitor<'de>, + { + match self { + PayloadValue::Null => visitor.visit_unit(), + PayloadValue::Bool(b) => visitor.visit_bool(b), + PayloadValue::Number(n) => n.deserialize_any(visitor), + PayloadValue::String(s) => visitor.visit_string(s), + PayloadValue::Binary(_, data) => visitor.visit_byte_buf(data), + PayloadValue::Array(a) => visit_array(a, visitor), + PayloadValue::Object(o) => visit_object(o, visitor), + } + } + + fn deserialize_unit(self, visitor: V) -> Result + where + V: de::Visitor<'de>, + { + match self { + PayloadValue::Null => visitor.visit_unit(), + _ => Err(serde_json::Error::invalid_type(self.unexpected(), &visitor)), + } + } + + fn deserialize_unit_struct( + self, + _name: &'static str, + visitor: V, + ) -> Result + where + V: de::Visitor<'de>, + { + self.deserialize_unit(visitor) + } + + fn deserialize_bool(self, visitor: V) -> Result + where + V: de::Visitor<'de>, + { + match self { + PayloadValue::Bool(b) => visitor.visit_bool(b), + _ => Err(serde_json::Error::invalid_type(self.unexpected(), &visitor)), + } + } + + impl_deser_number!(deserialize_i8); + impl_deser_number!(deserialize_i16); + impl_deser_number!(deserialize_i32); + impl_deser_number!(deserialize_i64); + impl_deser_number!(deserialize_i128); + impl_deser_number!(deserialize_u8); + impl_deser_number!(deserialize_u16); + impl_deser_number!(deserialize_u32); + impl_deser_number!(deserialize_u64); + impl_deser_number!(deserialize_u128); + impl_deser_number!(deserialize_f32); + impl_deser_number!(deserialize_f64); + + fn deserialize_char(self, visitor: V) -> Result + where + V: de::Visitor<'de>, + { + self.deserialize_string(visitor) + } + + fn deserialize_str(self, visitor: V) -> Result + where + V: de::Visitor<'de>, + { + self.deserialize_string(visitor) + } + + fn deserialize_string(self, visitor: V) -> Result + where + V: de::Visitor<'de>, + { + match self { + PayloadValue::String(s) => visitor.visit_string(s), + _ => Err(serde_json::Error::invalid_type(self.unexpected(), &visitor)), + } + } + + fn deserialize_identifier(self, visitor: V) -> Result + where + V: de::Visitor<'de>, + { + self.deserialize_string(visitor) + } + + fn deserialize_byte_buf(self, visitor: V) -> Result + where + V: de::Visitor<'de>, + { + match self { + PayloadValue::String(s) => visitor.visit_string(s), + PayloadValue::Binary(_, data) => visitor.visit_byte_buf(data), + PayloadValue::Array(a) => visit_array(a, visitor), + _ => Err(serde_json::Error::invalid_type(self.unexpected(), &visitor)), + } + } + + fn deserialize_bytes(self, visitor: V) -> Result + where + V: de::Visitor<'de>, + { + self.deserialize_byte_buf(visitor) + } + + fn deserialize_option(self, visitor: V) -> Result + where + V: de::Visitor<'de>, + { + match self { + PayloadValue::Null => visitor.visit_none(), + other => visitor.visit_some(other), + } + } + + fn deserialize_seq(self, visitor: V) -> Result + where + V: de::Visitor<'de>, + { + match self { + PayloadValue::Array(a) => visit_array(a, visitor), + _ => Err(serde_json::Error::invalid_type(self.unexpected(), &visitor)), + } + } + + fn deserialize_tuple(self, _len: usize, visitor: V) -> Result + where + V: de::Visitor<'de>, + { + self.deserialize_seq(visitor) + } + + fn deserialize_tuple_struct( + self, + _name: &'static str, + _len: usize, + visitor: V, + ) -> Result + where + V: de::Visitor<'de>, + { + self.deserialize_seq(visitor) + } + + fn deserialize_newtype_struct( + self, + _name: &'static str, + visitor: V, + ) -> Result + where + V: de::Visitor<'de>, + { + visitor.visit_newtype_struct(self) + } + + fn deserialize_map(self, visitor: V) -> Result + where + V: de::Visitor<'de>, + { + match self { + PayloadValue::Object(o) => visit_object(o, visitor), + _ => Err(serde_json::Error::invalid_type(self.unexpected(), &visitor)), + } + } + + fn deserialize_struct( + self, + _name: &'static str, + _fields: &'static [&'static str], + visitor: V, + ) -> Result + where + V: de::Visitor<'de>, + { + match self { + PayloadValue::Object(o) => visit_object(o, visitor), + PayloadValue::Array(a) => visit_array(a, visitor), + _ => Err(serde_json::Error::invalid_type(self.unexpected(), &visitor)), + } + } + + fn deserialize_enum( + self, + _name: &'static str, + _variants: &'static [&'static str], + visitor: V, + ) -> Result + where + V: de::Visitor<'de>, + { + match self { + PayloadValue::Object(o) => { + // From serde_json: enums are encoded as a map with _only_ a single key-value pair + if o.len() == 1 { + let (variant, value) = o.into_iter().next().unwrap(); + visitor.visit_enum(EnumDeserializer::from((variant, Some(value)))) + } else { + Err(serde_json::Error::invalid_value( + Unexpected::Map, + &"a map with a single key-value pair", + )) + } + } + PayloadValue::String(s) => visitor.visit_enum(EnumDeserializer::from((s, None))), + _ => Err(serde_json::Error::invalid_type( + self.unexpected(), + &"map or string", + )), + } + } + + fn deserialize_ignored_any(self, visitor: V) -> Result + where + V: de::Visitor<'de>, + { + drop(self); + visitor.visit_unit() + } +} + +fn visit_array<'de, V>(a: Vec, visitor: V) -> Result +where + V: de::Visitor<'de>, +{ + let len = a.len(); + let mut deser = SeqDeserializer::from(a); + let seq = visitor.visit_seq(&mut deser)?; + if deser.iter.len() == 0 { + Ok(seq) + } else { + Err(serde_json::Error::invalid_length( + len, + &"array with fewer elements", + )) + } +} + +fn visit_object<'de, V>( + o: HashMap, + visitor: V, +) -> Result +where + V: de::Visitor<'de>, +{ + let len = o.len(); + let mut deser = MapDeserializer::from(o); + let map = visitor.visit_map(&mut deser)?; + if deser.iter.len() == 0 { + Ok(map) + } else { + Err(serde_json::Error::invalid_length( + len, + &"map with fewer elements", + )) + } +} + +struct SeqDeserializer { + iter: vec::IntoIter, +} + +impl From> for SeqDeserializer { + fn from(value: Vec) -> Self { + Self { + iter: value.into_iter(), + } + } +} + +impl<'de> SeqAccess<'de> for SeqDeserializer { + type Error = serde_json::Error; + + fn next_element_seed(&mut self, seed: T) -> Result, Self::Error> + where + T: de::DeserializeSeed<'de>, + { + match self.iter.next() { + Some(value) => seed.deserialize(value).map(Some), + None => Ok(None), + } + } + + fn size_hint(&self) -> Option { + match self.iter.size_hint() { + (_, Some(upper)) => Some(upper), + (lower, _) if lower > 0 => Some(lower), + _ => None, + } + } +} + +struct MapDeserializer { + iter: as IntoIterator>::IntoIter, + next_value: Option, +} + +impl From> for MapDeserializer { + fn from(value: HashMap) -> Self { + Self { + iter: value.into_iter(), + next_value: None, + } + } +} + +impl<'de> MapAccess<'de> for MapDeserializer { + type Error = serde_json::Error; + + fn next_key_seed(&mut self, seed: K) -> Result, Self::Error> + where + K: de::DeserializeSeed<'de>, + { + match self.iter.next() { + Some((key, value)) => { + self.next_value = Some(value); + let deser = MapKeyDeserializer::from(key); + seed.deserialize(deser).map(Some) + } + None => Ok(None), + } + } + + fn next_value_seed(&mut self, seed: V) -> Result + where + V: de::DeserializeSeed<'de>, + { + match self.next_value.take() { + Some(value) => seed.deserialize(value), + None => Err(serde_json::Error::custom( + "next_value() called before next_key()", + )), + } + } + + fn size_hint(&self) -> Option { + match self.iter.size_hint() { + (_, Some(upper)) => Some(upper), + (lower, _) if lower > 0 => Some(lower), + _ => None, + } + } +} + +struct MapKeyDeserializer<'de> { + key: Cow<'de, str>, +} + +impl<'de> From for MapKeyDeserializer<'de> { + fn from(value: String) -> Self { + MapKeyDeserializer { + key: Cow::Owned(value), + } + } +} + +impl<'de> serde::Deserializer<'de> for MapKeyDeserializer<'de> { + type Error = serde_json::Error; + + fn deserialize_any(self, visitor: V) -> Result + where + V: de::Visitor<'de>, + { + MapKeyStrDeserializer::from(self.key).deserialize_any(visitor) + } + + fn deserialize_bool(self, visitor: V) -> Result + where + V: de::Visitor<'de>, + { + match self.key.as_ref() { + "true" => visitor.visit_bool(true), + "false" => visitor.visit_bool(false), + _ => Err(serde_json::Error::invalid_type( + Unexpected::Str(&self.key), + &visitor, + )), + } + } + + impl_deser_numeric_key!(deserialize_i8); + impl_deser_numeric_key!(deserialize_i16); + impl_deser_numeric_key!(deserialize_i32); + impl_deser_numeric_key!(deserialize_i64); + impl_deser_numeric_key!(deserialize_u8); + impl_deser_numeric_key!(deserialize_u16); + impl_deser_numeric_key!(deserialize_u32); + impl_deser_numeric_key!(deserialize_u64); + impl_deser_numeric_key!(deserialize_f64); + impl_deser_numeric_key!(deserialize_f32); + impl_deser_numeric_key!(deserialize_i128); + impl_deser_numeric_key!(deserialize_u128); + + fn deserialize_option(self, visitor: V) -> Result + where + V: de::Visitor<'de>, + { + visitor.visit_some(self) + } + + fn deserialize_newtype_struct( + self, + _name: &'static str, + visitor: V, + ) -> Result + where + V: de::Visitor<'de>, + { + visitor.visit_newtype_struct(self) + } + + fn deserialize_enum( + self, + name: &'static str, + variants: &'static [&'static str], + visitor: V, + ) -> Result + where + V: de::Visitor<'de>, + { + self.key + .into_deserializer() + .deserialize_enum(name, variants, visitor) + } + + forward_to_deserialize_any! { + char str string bytes byte_buf unit unit_struct seq tuple tuple_struct + map struct identifier ignored_any + } +} + +struct MapKeyStrDeserializer<'de> { + key: Cow<'de, str>, +} + +impl<'de> From> for MapKeyStrDeserializer<'de> { + fn from(value: Cow<'de, str>) -> Self { + Self { key: value } + } +} + +impl<'de> serde::Deserializer<'de> for MapKeyStrDeserializer<'de> { + type Error = serde_json::Error; + + fn deserialize_any(self, visitor: V) -> Result + where + V: de::Visitor<'de>, + { + match self.key { + Cow::Owned(s) => visitor.visit_string(s), + Cow::Borrowed(s) => visitor.visit_borrowed_str(s), + } + } + + fn deserialize_enum( + self, + _name: &'static str, + _variants: &'static [&'static str], + visitor: V, + ) -> Result + where + V: de::Visitor<'de>, + { + visitor.visit_enum(self) + } + + forward_to_deserialize_any! { + bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string + bytes byte_buf option unit unit_struct newtype_struct seq tuple + tuple_struct map struct identifier ignored_any + } +} + +impl<'de> EnumAccess<'de> for MapKeyStrDeserializer<'de> { + type Variant = UnitEnum; + type Error = serde_json::Error; + + fn variant_seed(self, seed: V) -> Result<(V::Value, Self::Variant), Self::Error> + where + V: de::DeserializeSeed<'de>, + { + Ok((seed.deserialize(self)?, UnitEnum)) + } +} + +struct UnitEnum; + +impl<'de> VariantAccess<'de> for UnitEnum { + type Error = serde_json::Error; + + fn unit_variant(self) -> Result<(), Self::Error> { + Ok(()) + } + + fn tuple_variant(self, _len: usize, _visitor: V) -> Result + where + V: de::Visitor<'de>, + { + Err(serde_json::Error::invalid_type( + Unexpected::UnitVariant, + &"tuple variant", + )) + } + + fn struct_variant( + self, + _fields: &'static [&'static str], + _visitor: V, + ) -> Result + where + V: de::Visitor<'de>, + { + Err(serde_json::Error::invalid_type( + Unexpected::UnitVariant, + &"struct variant", + )) + } + + fn newtype_variant_seed(self, _seed: T) -> Result + where + T: de::DeserializeSeed<'de>, + { + Err(serde_json::Error::invalid_type( + Unexpected::UnitVariant, + &"newtype variant", + )) + } +} + +struct EnumDeserializer { + variant: String, + value: Option, +} + +impl From<(String, Option)> for EnumDeserializer { + fn from(value: (String, Option)) -> Self { + Self { + variant: value.0, + value: value.1, + } + } +} + +impl<'de> EnumAccess<'de> for EnumDeserializer { + type Variant = VariantDeserializer; + type Error = serde_json::Error; + + fn variant_seed(self, seed: V) -> Result<(V::Value, Self::Variant), Self::Error> + where + V: de::DeserializeSeed<'de>, + { + let variant = self.variant.into_deserializer(); + let visitor = VariantDeserializer::from(self.value); + seed.deserialize(variant).map(|v| (v, visitor)) + } +} + +struct VariantDeserializer { + value: Option, +} + +impl From> for VariantDeserializer { + fn from(value: Option) -> Self { + Self { value } + } +} + +impl<'de> VariantAccess<'de> for VariantDeserializer { + type Error = serde_json::Error; + + fn unit_variant(self) -> Result<(), Self::Error> { + match self.value { + Some(value) => serde::Deserialize::deserialize(value), + None => Ok(()), + } + } + + fn tuple_variant(self, _len: usize, visitor: V) -> Result + where + V: de::Visitor<'de>, + { + match self.value { + Some(PayloadValue::Array(a)) => { + if a.is_empty() { + visitor.visit_unit() + } else { + visit_array(a, visitor) + } + } + Some(other) => Err(serde_json::Error::invalid_type( + other.unexpected(), + &"tuple variant", + )), + None => Err(serde_json::Error::invalid_type( + Unexpected::UnitVariant, + &"tuple variant", + )), + } + } + + fn struct_variant( + self, + _fields: &'static [&'static str], + visitor: V, + ) -> Result + where + V: de::Visitor<'de>, + { + match self.value { + Some(PayloadValue::Object(o)) => visit_object(o, visitor), + Some(other) => Err(serde_json::Error::invalid_type( + other.unexpected(), + &"struct variant", + )), + None => Err(serde_json::Error::invalid_type( + Unexpected::UnitVariant, + &"struct variant", + )), + } + } + + fn newtype_variant_seed(self, seed: T) -> Result + where + T: de::DeserializeSeed<'de>, + { + match self.value { + Some(value) => seed.deserialize(value), + None => Err(serde_json::Error::invalid_type( + Unexpected::UnitVariant, + &"newtype variant", + )), + } + } +} diff --git a/socketioxide/src/payload_value/from.rs b/socketioxide/src/payload_value/from.rs new file mode 100644 index 00000000..92db342a --- /dev/null +++ b/socketioxide/src/payload_value/from.rs @@ -0,0 +1,99 @@ +use std::collections::HashMap; + +use serde_json::{Number, Value}; + +use super::PayloadValue; + +impl From<()> for PayloadValue { + fn from(_value: ()) -> Self { + PayloadValue::Null + } +} + +impl From for PayloadValue { + fn from(value: bool) -> Self { + PayloadValue::Bool(value) + } +} + +impl From for PayloadValue { + fn from(value: Number) -> Self { + PayloadValue::Number(value) + } +} + +impl From for PayloadValue { + fn from(value: String) -> Self { + PayloadValue::String(value) + } +} + +impl> From> for PayloadValue { + fn from(value: HashMap) -> Self { + PayloadValue::Object(value.into_iter().map(|(k, v)| (k, v.into())).collect()) + } +} + +impl> From> for PayloadValue { + fn from(value: Vec) -> Self { + PayloadValue::Array(value.into_iter().map(Into::into).collect()) + } +} + +impl From for PayloadValue { + fn from(value: Value) -> Self { + match value { + Value::Null => PayloadValue::Null, + Value::Bool(b) => PayloadValue::Bool(b), + Value::Number(n) => PayloadValue::Number(n), + Value::String(s) => PayloadValue::String(s), + Value::Array(a) => PayloadValue::Array(a.into_iter().map(Into::into).collect()), + Value::Object(o) => match (o.get("_placeholder"), o.get("num")) { + (Some(Value::Bool(true)), Some(Value::Number(num))) + if num + .as_u64() + .map(|n| n <= usize::MAX as u64) + .unwrap_or(false) => + { + PayloadValue::Binary(num.as_u64().unwrap() as usize, vec![]) + } + _ => PayloadValue::Object(o.into_iter().map(|(k, v)| (k, v.into())).collect()), + }, + } + } +} + +impl From for Value { + fn from(value: PayloadValue) -> Self { + match value { + PayloadValue::Null => Value::Null, + PayloadValue::Bool(b) => Value::Bool(b), + PayloadValue::Number(n) => Value::Number(n), + PayloadValue::String(s) => Value::String(s), + PayloadValue::Binary(num, _) => Value::Object( + [ + ("_placeholder".to_string(), Value::Bool(true)), + ("num".to_string(), Value::Number(Number::from(num))), + ] + .into_iter() + .collect(), + ), + PayloadValue::Array(a) => Value::Array(a.into_iter().map(Into::into).collect()), + PayloadValue::Object(o) => { + Value::Object(o.into_iter().map(|(k, v)| (k, v.into())).collect()) + } + } + } +} + +impl> FromIterator<(String, V)> for PayloadValue { + fn from_iter>(iter: T) -> Self { + PayloadValue::Object(iter.into_iter().map(|(k, v)| (k, v.into())).collect()) + } +} + +impl> FromIterator for PayloadValue { + fn from_iter>(iter: I) -> Self { + PayloadValue::Array(iter.into_iter().map(Into::into).collect()) + } +} diff --git a/socketioxide/src/payload_value/mod.rs b/socketioxide/src/payload_value/mod.rs new file mode 100644 index 00000000..3cefd58a --- /dev/null +++ b/socketioxide/src/payload_value/mod.rs @@ -0,0 +1,409 @@ +use std::collections::HashMap; + +use serde::{de::DeserializeOwned, Deserialize, Serialize}; +use serde_json::Number; + +mod binary; +mod de; +mod from; +mod ser; + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(untagged)] +pub enum PayloadValue { + Null, + Bool(bool), + Number(Number), + String(String), + #[serde(with = "serde_payload_value_binary")] + Binary(usize, Vec), + Array(Vec), + Object(HashMap), +} + +impl PayloadValue { + pub fn from_data(data: T) -> Result { + ser::to_payload_value(data) + } + + pub fn into_data(self) -> Result { + T::deserialize(self) + } + + pub fn as_str(&self) -> Option<&str> { + match self { + PayloadValue::String(s) => Some(s), + _ => None, + } + } + + pub fn has_binary(&self) -> bool { + self.count_payloads() > 0 + } + + pub fn count_payloads(&self) -> usize { + match self { + PayloadValue::Binary(_, _) => 1, + PayloadValue::Array(a) => a.iter().map(PayloadValue::count_payloads).sum(), + PayloadValue::Object(o) => o.iter().map(|(_, v)| v.count_payloads()).sum(), + _ => 0, + } + } + + /// Extracts and returns all binary payloads. + /// 'self' is modified in-place, so this can only be called once + pub fn extract_binary_payloads(&mut self) -> Vec> { + fn rec(data: &mut PayloadValue) -> Vec<(usize, Vec)> { + let mut bins = Vec::<(usize, Vec)>::new(); + + match data { + PayloadValue::Binary(num, ref mut bin) => { + bins.push((*num, std::mem::take(bin))); + } + PayloadValue::Array(a) => { + for value in a.iter_mut() { + bins.extend(rec(value)); + } + } + PayloadValue::Object(o) => { + for value in o.values_mut() { + bins.extend(rec(value)); + } + } + _ => (), + } + + bins + } + + let mut bins = rec(self); + bins.sort_by(|(a, _), (b, _)| a.cmp(b)); + bins.into_iter().map(|(_, bin)| bin).collect() + } +} + +mod serde_payload_value_binary { + use std::fmt; + + use serde::{de, ser::SerializeMap, Deserializer, Serializer}; + use serde_json::Value; + + pub fn serialize(num: &usize, _data: &Vec, serializer: S) -> Result + where + S: Serializer, + { + let mut map = serializer.serialize_map(Some(2))?; + map.serialize_entry(&"_placeholder", &true)?; + map.serialize_entry(&"num", num)?; + map.end() + } + + pub fn deserialize<'de, D>(deserializer: D) -> Result<(usize, Vec), D::Error> + where + D: Deserializer<'de>, + { + struct BinaryVisitor; + + impl<'de> de::Visitor<'de> for BinaryVisitor { + type Value = (usize, Vec); + + fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + formatter.write_str("a _placeholder object with a num field") + } + + fn visit_map(self, mut map: A) -> Result + where + A: de::MapAccess<'de>, + { + use de::Error; + + let (first_key, first_value) = map + .next_entry::()? + .ok_or(A::Error::custom( + "not enough values in object for pending binary", + ))?; + let (second_key, second_value) = map + .next_entry::()? + .ok_or(A::Error::custom( + "not enough values in object for pending binary", + ))?; + + let placeholder_value = if first_key == "_placeholder" { + Ok(&first_value) + } else if second_key == "_placeholder" { + Ok(&second_value) + } else { + Err(A::Error::custom("no '_placeholder' present")) + }?; + + let num_value = if first_key == "num" { + Ok(&first_value) + } else if second_key == "num" { + Ok(&second_value) + } else { + Err(A::Error::custom("no 'num' present")) + }?; + + match (placeholder_value, num_value) { + (Value::Bool(true), Value::Number(num)) + if num.as_u64().filter(|n| *n <= usize::MAX as u64).is_some() => + { + Ok((num.as_u64().unwrap() as usize, vec![])) + } + _ => Err(A::Error::custom( + "_placeholder & num are of incorrect types or values", + )), + } + } + } + + deserializer.deserialize_map(BinaryVisitor) + } +} + +#[cfg(test)] +mod test { + use serde::{Deserialize, Serialize}; + use serde_json::{json, Number, Value}; + + use super::{binary::Binary, PayloadValue}; + + #[derive(Debug, Serialize, Deserialize, PartialEq)] + struct TestSubPayload { + more_binary: Binary, + opt_int: Option, + opt_float: Option, + opt_string: Option, + opt_boolean: Option, + } + + #[derive(Debug, Serialize, Deserialize, PartialEq)] + struct TestPayload { + uint: u32, + float: f64, + binary: Binary, + string: String, + boolean: bool, + array: Vec, + sub_payload: TestSubPayload, + } + + fn build_test_payload(fill_options: bool) -> TestPayload { + let fill_options = fill_options.then_some(true); + TestPayload { + uint: 42, + float: 1.75, + binary: vec![1, 2, 3, 4, 5, 6, 7].into(), + string: "test string".to_string(), + boolean: true, + array: ["one", "two", "three"] + .into_iter() + .map(ToString::to_string) + .collect(), + sub_payload: TestSubPayload { + more_binary: vec![10, 9, 8, 7, 6, 5].into(), + opt_int: fill_options.map(|_| 99), + opt_float: fill_options.map(|_| 2.5), + opt_string: fill_options.map(|_| "another test string".to_string()), + opt_boolean: fill_options, + }, + } + } + + fn build_test_payload_value(fill_options: bool, fill_binary_data: bool) -> PayloadValue { + let fill_options = fill_options.then_some(true); + let fill_binary_data = fill_binary_data.then_some(true); + PayloadValue::Object( + [ + ("uint", PayloadValue::Number(42.into())), + ( + "float", + PayloadValue::Number(Number::from_f64(1.75).unwrap()), + ), + ( + "binary", + PayloadValue::Binary( + 0, + fill_binary_data + .map(|_| vec![1, 2, 3, 4, 5, 6, 7]) + .unwrap_or(vec![]), + ), + ), + ("string", PayloadValue::String("test string".to_string())), + ("boolean", PayloadValue::Bool(true)), + ( + "array", + PayloadValue::Array( + ["one", "two", "three"] + .into_iter() + .map(|s| PayloadValue::String(s.to_string())) + .collect(), + ), + ), + ( + "sub_payload", + PayloadValue::Object( + [ + ( + "more_binary", + PayloadValue::Binary( + 1, + fill_binary_data + .map(|_| vec![10, 9, 8, 7, 6, 5]) + .unwrap_or(vec![]), + ), + ), + ( + "opt_int", + fill_options + .map(|_| PayloadValue::Number(99.into())) + .unwrap_or(PayloadValue::Null), + ), + ( + "opt_float", + fill_options + .map(|_| { + PayloadValue::Number( + Number::from_f64(2.5f32 as f64).unwrap(), + ) + }) + .unwrap_or(PayloadValue::Null), + ), + ( + "opt_string", + fill_options + .map(|_| { + PayloadValue::String("another test string".to_string()) + }) + .unwrap_or(PayloadValue::Null), + ), + ( + "opt_boolean", + fill_options + .map(PayloadValue::Bool) + .unwrap_or(PayloadValue::Null), + ), + ] + .into_iter() + .map(|(k, v)| (k.to_string(), v)) + .collect(), + ), + ), + ] + .into_iter() + .map(|(k, v)| (k.to_string(), v)) + .collect(), + ) + } + + fn build_test_payload_json(fill_options: bool) -> Value { + let sub_payload = if fill_options { + json!({ + "more_binary": { + "_placeholder": true, + "num": 1 + }, + "opt_int": 99, + "opt_float": 2.5, + "opt_string": "another test string", + "opt_boolean": true + }) + } else { + json!({ + "more_binary": { + "_placeholder": true, + "num": 1 + }, + "opt_int": null, + "opt_float": null, + "opt_string": null, + "opt_boolean": null + }) + }; + + let mut main_payload = json!({ + "uint": 42, + "float": 1.75, + "binary": { + "_placeholder": true, + "num": 0 + }, + "string": "test string", + "boolean": true, + "array": [ + "one", + "two", + "three" + ] + }); + + if let Value::Object(ref mut o) = &mut main_payload { + o.insert("sub_payload".to_string(), sub_payload); + } else { + panic!("test bug: not an object"); + } + + main_payload + } + + #[test] + pub fn test_payload_value_from_data() { + let test_payload = build_test_payload(true); + let payload_value = PayloadValue::from_data(test_payload).unwrap(); + assert_eq!(payload_value, build_test_payload_value(true, true)); + + let test_payload = build_test_payload(false); + let payload_value = PayloadValue::from_data(test_payload).unwrap(); + assert_eq!(payload_value, build_test_payload_value(false, true)); + } + + #[test] + pub fn test_payload_value_into_data() { + let payload_value = build_test_payload_value(true, true); + let test_payload: TestPayload = payload_value.into_data().unwrap(); + assert_eq!(test_payload, build_test_payload(true)); + + let payload_value = build_test_payload_value(false, true); + let test_payload: TestPayload = payload_value.into_data().unwrap(); + assert_eq!(test_payload, build_test_payload(false)); + } + + #[test] + pub fn test_payload_value_ser() { + let payload_value = build_test_payload_value(true, false); + let json = serde_json::to_value(payload_value).unwrap(); + assert_eq!(json, build_test_payload_json(true)); + + let payload_value = build_test_payload_value(false, false); + let json = serde_json::to_value(payload_value).unwrap(); + assert_eq!(json, build_test_payload_json(false)); + } + + #[test] + pub fn test_payload_value_deser() { + let json = build_test_payload_json(true); + let payload_value: PayloadValue = serde_json::from_value(json).unwrap(); + assert_eq!(payload_value, build_test_payload_value(true, false)); + + let json = build_test_payload_json(false); + let payload_value: PayloadValue = serde_json::from_value(json).unwrap(); + assert_eq!(payload_value, build_test_payload_value(false, false)); + } + + #[test] + pub fn test_count_payloads() { + let payload_value = build_test_payload_value(true, false); + assert_eq!(payload_value.count_payloads(), 2); + } + + #[test] + pub fn test_extract_binary_payloads() { + let test_payload = build_test_payload(true); + let mut payload_value = build_test_payload_value(true, true); + let bins = payload_value.extract_binary_payloads(); + + assert_eq!(bins.len(), 2); + assert_eq!(bins[0], *test_payload.binary); + assert_eq!(bins[1], *test_payload.sub_payload.more_binary); + } +} diff --git a/socketioxide/src/payload_value/ser.rs b/socketioxide/src/payload_value/ser.rs new file mode 100644 index 00000000..532c8268 --- /dev/null +++ b/socketioxide/src/payload_value/ser.rs @@ -0,0 +1,590 @@ +use std::collections::HashMap; + +use serde::ser::{Error, Impossible, SerializeSeq}; +use serde_json::Number; + +use super::PayloadValue; + +const KEY_STRING_ERROR: &'static str = "key must be a string"; + +pub fn to_payload_value(data: T) -> Result { + let mut ser = Serializer::default(); + data.serialize(&mut ser) +} + +struct Serializer { + next_binary_payload_num: usize, +} + +impl Default for Serializer { + fn default() -> Self { + Self { + next_binary_payload_num: 0, + } + } +} + +impl<'a> serde::Serializer for &'a mut Serializer { + type Ok = PayloadValue; + type Error = serde_json::Error; + + type SerializeSeq = SerializeVec<'a>; + type SerializeTuple = SerializeVec<'a>; + type SerializeTupleVariant = SerializeTupleVariant<'a>; + type SerializeMap = SerializeMap<'a>; + type SerializeStruct = SerializeMap<'a>; + type SerializeStructVariant = SerializeStructVariant<'a>; + type SerializeTupleStruct = SerializeVec<'a>; + + fn serialize_bool(self, v: bool) -> Result { + Ok(PayloadValue::Bool(v)) + } + + fn serialize_i8(self, v: i8) -> Result { + self.serialize_i64(v as i64) + } + + fn serialize_i16(self, v: i16) -> Result { + self.serialize_i64(v as i64) + } + + fn serialize_i32(self, v: i32) -> Result { + self.serialize_i64(v as i64) + } + + fn serialize_i64(self, v: i64) -> Result { + Ok(PayloadValue::Number(v.into())) + } + + fn serialize_i128(self, v: i128) -> Result { + if let Ok(v) = u64::try_from(v) { + Ok(PayloadValue::Number(v.into())) + } else if let Ok(v) = i64::try_from(v) { + Ok(PayloadValue::Number(v.into())) + } else { + Err(serde_json::Error::custom("number out of range")) + } + } + + fn serialize_u8(self, v: u8) -> Result { + self.serialize_u64(v as u64) + } + + fn serialize_u16(self, v: u16) -> Result { + self.serialize_u64(v as u64) + } + + fn serialize_u32(self, v: u32) -> Result { + self.serialize_u64(v as u64) + } + + fn serialize_u64(self, v: u64) -> Result { + Ok(PayloadValue::Number(v.into())) + } + + fn serialize_u128(self, v: u128) -> Result { + if let Ok(v) = u64::try_from(v) { + Ok(PayloadValue::Number(v.into())) + } else { + Err(serde_json::Error::custom("number out of range")) + } + } + + fn serialize_f32(self, v: f32) -> Result { + if v.is_finite() { + Ok(Number::from_f64(v as f64).map_or(PayloadValue::Null, PayloadValue::Number)) + } else { + Ok(PayloadValue::Null) + } + } + + fn serialize_f64(self, v: f64) -> Result { + Ok(Number::from_f64(v).map_or(PayloadValue::Null, PayloadValue::Number)) + } + + fn serialize_char(self, v: char) -> Result { + Ok(PayloadValue::String(String::from(v))) + } + + fn serialize_str(self, v: &str) -> Result { + Ok(PayloadValue::String(v.to_string())) + } + + fn serialize_bytes(self, v: &[u8]) -> Result { + let num = self.next_binary_payload_num; + self.next_binary_payload_num += 1; + Ok(PayloadValue::Binary(num, Vec::from(v))) + } + + fn serialize_unit(self) -> Result { + Ok(PayloadValue::Null) + } + + fn serialize_unit_struct(self, _name: &'static str) -> Result { + self.serialize_unit() + } + + fn serialize_unit_variant( + self, + _name: &'static str, + _variant_index: u32, + variant: &'static str, + ) -> Result { + self.serialize_str(variant) + } + + fn serialize_newtype_struct( + self, + _name: &'static str, + value: &T, + ) -> Result { + value.serialize(self) + } + + fn serialize_none(self) -> Result { + self.serialize_unit() + } + + fn serialize_some( + self, + value: &T, + ) -> Result { + value.serialize(self) + } + + fn serialize_seq(self, len: Option) -> Result { + Ok(SerializeVec { + root_ser: self, + elements: Vec::with_capacity(len.unwrap_or(0)), + }) + } + + fn serialize_tuple(self, len: usize) -> Result { + self.serialize_seq(Some(len)) + } + + fn serialize_tuple_variant( + self, + _name: &'static str, + _variant_index: u32, + variant: &'static str, + len: usize, + ) -> Result { + Ok(SerializeTupleVariant { + root_ser: self, + name: String::from(variant), + elements: Vec::with_capacity(len), + }) + } + + fn serialize_map(self, len: Option) -> Result { + Ok(SerializeMap { + root_ser: self, + map: HashMap::with_capacity(len.unwrap_or(0)), + next_key: None, + }) + } + + fn serialize_struct( + self, + _name: &'static str, + len: usize, + ) -> Result { + self.serialize_map(Some(len)) + } + + fn serialize_struct_variant( + self, + _name: &'static str, + _variant_index: u32, + variant: &'static str, + _len: usize, + ) -> Result { + Ok(SerializeStructVariant { + root_ser: self, + name: String::from(variant), + map: HashMap::new(), + }) + } + + fn serialize_tuple_struct( + self, + _name: &'static str, + len: usize, + ) -> Result { + self.serialize_seq(Some(len)) + } + + fn serialize_newtype_variant( + self, + name: &'static str, + _variant_index: u32, + _variant: &'static str, + value: &T, + ) -> Result { + let mut obj = HashMap::new(); + obj.insert(name.to_string(), value.serialize(self)?); + Ok(PayloadValue::Object(obj)) + } + + fn collect_str( + self, + value: &T, + ) -> Result { + Ok(PayloadValue::String(value.to_string())) + } +} + +struct SerializeVec<'a> { + root_ser: &'a mut Serializer, + elements: Vec, +} + +impl<'a> SerializeSeq for SerializeVec<'a> { + type Ok = PayloadValue; + type Error = serde_json::Error; + + fn serialize_element( + &mut self, + value: &T, + ) -> Result<(), Self::Error> { + let element = sub_serialize(self.root_ser, value)?; + self.elements.push(element); + Ok(()) + } + + fn end(self) -> Result { + Ok(PayloadValue::Array(self.elements)) + } +} + +impl<'a> serde::ser::SerializeTuple for SerializeVec<'a> { + type Ok = PayloadValue; + type Error = serde_json::Error; + + fn serialize_element( + &mut self, + value: &T, + ) -> Result<(), Self::Error> { + serde::ser::SerializeSeq::serialize_element(self, value) + } + + fn end(self) -> Result { + serde::ser::SerializeSeq::end(self) + } +} + +impl<'a> serde::ser::SerializeTupleStruct for SerializeVec<'a> { + type Ok = PayloadValue; + type Error = serde_json::Error; + + fn serialize_field( + &mut self, + value: &T, + ) -> Result<(), Self::Error> { + serde::ser::SerializeSeq::serialize_element(self, value) + } + + fn end(self) -> Result { + serde::ser::SerializeSeq::end(self) + } +} + +struct SerializeTupleVariant<'a> { + root_ser: &'a mut Serializer, + name: String, + elements: Vec, +} + +impl<'a> serde::ser::SerializeTupleVariant for SerializeTupleVariant<'a> { + type Ok = PayloadValue; + type Error = serde_json::Error; + + fn serialize_field( + &mut self, + value: &T, + ) -> Result<(), Self::Error> { + let element = sub_serialize(self.root_ser, value)?; + self.elements.push(element); + Ok(()) + } + + fn end(self) -> Result { + let mut obj = HashMap::new(); + obj.insert(self.name, PayloadValue::Array(self.elements)); + Ok(PayloadValue::Object(obj)) + } +} + +struct SerializeMap<'a> { + root_ser: &'a mut Serializer, + map: HashMap, + next_key: Option, +} + +impl<'a> serde::ser::SerializeMap for SerializeMap<'a> { + type Ok = PayloadValue; + type Error = serde_json::Error; + + fn serialize_key(&mut self, key: &T) -> Result<(), Self::Error> { + self.next_key = Some(key.serialize(MapKeySerializer)?); + Ok(()) + } + + fn serialize_value( + &mut self, + value: &T, + ) -> Result<(), Self::Error> { + if let Some(key) = self.next_key.take() { + self.map.insert(key, sub_serialize(self.root_ser, value)?); + Ok(()) + } else { + panic!("serialize_value() called before serialize_key()"); + } + } + + fn serialize_entry( + &mut self, + key: &K, + value: &V, + ) -> Result<(), Self::Error> { + self.map.insert( + key.serialize(MapKeySerializer)?, + sub_serialize(self.root_ser, value)?, + ); + Ok(()) + } + + fn end(self) -> Result { + Ok(PayloadValue::Object(self.map)) + } +} + +impl<'a> serde::ser::SerializeStruct for SerializeMap<'a> { + type Ok = PayloadValue; + type Error = serde_json::Error; + + fn serialize_field( + &mut self, + key: &'static str, + value: &T, + ) -> Result<(), Self::Error> { + serde::ser::SerializeMap::serialize_entry(self, key, value) + } + + fn end(self) -> Result { + serde::ser::SerializeMap::end(self) + } +} + +struct SerializeStructVariant<'a> { + root_ser: &'a mut Serializer, + name: String, + map: HashMap, +} + +impl<'a> serde::ser::SerializeStructVariant for SerializeStructVariant<'a> { + type Ok = PayloadValue; + type Error = serde_json::Error; + + fn serialize_field( + &mut self, + key: &'static str, + value: &T, + ) -> Result<(), Self::Error> { + self.map + .insert(key.to_string(), sub_serialize(self.root_ser, value)?); + Ok(()) + } + + fn end(self) -> Result { + let mut obj = HashMap::new(); + obj.insert(self.name, PayloadValue::Object(self.map)); + Ok(PayloadValue::Object(obj)) + } +} + +struct MapKeySerializer; + +impl serde::Serializer for MapKeySerializer { + type Ok = String; + type Error = serde_json::Error; + + type SerializeSeq = Impossible; + type SerializeMap = Impossible; + type SerializeTuple = Impossible; + type SerializeStruct = Impossible; + type SerializeTupleStruct = Impossible; + type SerializeTupleVariant = Impossible; + type SerializeStructVariant = Impossible; + + fn serialize_bool(self, v: bool) -> Result { + Ok(v.to_string()) + } + + fn serialize_i8(self, v: i8) -> Result { + Ok(v.to_string()) + } + + fn serialize_i16(self, v: i16) -> Result { + Ok(v.to_string()) + } + + fn serialize_i32(self, v: i32) -> Result { + Ok(v.to_string()) + } + + fn serialize_i64(self, v: i64) -> Result { + Ok(v.to_string()) + } + + fn serialize_i128(self, v: i128) -> Result { + Ok(v.to_string()) + } + + fn serialize_u8(self, v: u8) -> Result { + Ok(v.to_string()) + } + + fn serialize_u16(self, v: u16) -> Result { + Ok(v.to_string()) + } + + fn serialize_u32(self, v: u32) -> Result { + Ok(v.to_string()) + } + + fn serialize_u64(self, v: u64) -> Result { + Ok(v.to_string()) + } + + fn serialize_u128(self, v: u128) -> Result { + Ok(v.to_string()) + } + + fn serialize_f32(self, v: f32) -> Result { + Ok(v.to_string()) + } + + fn serialize_f64(self, v: f64) -> Result { + Ok(v.to_string()) + } + + fn serialize_char(self, v: char) -> Result { + Ok(v.to_string()) + } + + fn serialize_str(self, v: &str) -> Result { + Ok(v.to_string()) + } + + fn serialize_bytes(self, _v: &[u8]) -> Result { + Err(Self::Error::custom(KEY_STRING_ERROR)) + } + + fn serialize_seq(self, _len: Option) -> Result { + Err(Self::Error::custom(KEY_STRING_ERROR)) + } + + fn serialize_map(self, _len: Option) -> Result { + Err(Self::Error::custom(KEY_STRING_ERROR)) + } + + fn serialize_none(self) -> Result { + Err(Self::Error::custom(KEY_STRING_ERROR)) + } + + fn serialize_some( + self, + _value: &T, + ) -> Result { + Err(Self::Error::custom(KEY_STRING_ERROR)) + } + + fn serialize_unit(self) -> Result { + Err(Self::Error::custom(KEY_STRING_ERROR)) + } + + fn serialize_tuple(self, _len: usize) -> Result { + Err(Self::Error::custom(KEY_STRING_ERROR)) + } + + fn serialize_struct( + self, + _name: &'static str, + _len: usize, + ) -> Result { + Err(Self::Error::custom(KEY_STRING_ERROR)) + } + + fn serialize_unit_struct(self, _name: &'static str) -> Result { + Err(Self::Error::custom(KEY_STRING_ERROR)) + } + + fn serialize_unit_variant( + self, + _name: &'static str, + _variant_index: u32, + _variant: &'static str, + ) -> Result { + Err(Self::Error::custom(KEY_STRING_ERROR)) + } + + fn serialize_tuple_struct( + self, + _name: &'static str, + _len: usize, + ) -> Result { + Err(Self::Error::custom(KEY_STRING_ERROR)) + } + + fn serialize_tuple_variant( + self, + _name: &'static str, + _variant_index: u32, + _variant: &'static str, + _len: usize, + ) -> Result { + Err(Self::Error::custom(KEY_STRING_ERROR)) + } + + fn serialize_newtype_struct( + self, + _name: &'static str, + _value: &T, + ) -> Result { + Err(Self::Error::custom(KEY_STRING_ERROR)) + } + + fn serialize_struct_variant( + self, + _name: &'static str, + _variant_index: u32, + _variant: &'static str, + _len: usize, + ) -> Result { + Err(Self::Error::custom(KEY_STRING_ERROR)) + } + + fn serialize_newtype_variant( + self, + _name: &'static str, + _variant_index: u32, + _variant: &'static str, + _value: &T, + ) -> Result { + Err(Self::Error::custom(KEY_STRING_ERROR)) + } +} + +fn sub_serialize( + parent_ser: &mut Serializer, + data: &T, +) -> Result { + let mut sub_ser = Serializer { + next_binary_payload_num: parent_ser.next_binary_payload_num, + }; + let value = data.serialize(&mut sub_ser)?; + parent_ser.next_binary_payload_num = sub_ser.next_binary_payload_num; + Ok(value) +}