// Copyright (C) 2022 Soni L. // SPDX-License-Identifier: MIT OR Apache-2.0 //! Transmute objects through serde! //! //! This crate allows converting a `Serialize` value into a `Deserialize` type. //! //! # Caveats //! //! The main caveat of note is that `Serialize` is not lifetime-aware, so the //! `Deserialize` (or `DeserializeSeed`) cannot borrow from it. //! //! But we don't care because this crate was built to power parts of `datafu`. //! And it's pretty good at that. use serde::de::Error as _; use serde::de::{Deserialize, DeserializeSeed, Deserializer, Visitor}; use serde::ser::{Serialize, Serializer}; /// Transmutes the given `Serialize` into a stateless `Deserialize`. pub fn transmute<'de, D: Deserialize<'de>, S: Serialize>( s: S, settings: &Settings, ) -> Result { transmute_seed(s, std::marker::PhantomData::, settings) } /// Transmutes the given `Serialize` with a stateful `DeserializeSeed`. pub fn transmute_seed<'de, D: DeserializeSeed<'de>, S: Serialize>( s: S, d: D, settings: &Settings, ) -> Result { let collection = s.serialize(Collect::new(settings))?; d.deserialize(Transmute::new(collection, settings)) } #[derive(Debug)] pub struct TransmuteError(()); impl std::fmt::Display for TransmuteError { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { todo!() } } impl std::error::Error for TransmuteError { } impl serde::de::Error for TransmuteError { fn custom(t: T) -> Self { todo!() } } impl serde::ser::Error for TransmuteError { fn custom(t: T) -> Self { todo!() } } /// Transmutation settings. #[derive(Copy, Clone, Debug)] pub struct Settings { /// Whether to use human-readable format. human_readable: bool, /// Whether structs are sequences. structs_are_seqs: bool, numeric_variants: bool, } impl Default for Settings { fn default() -> Self { Self { human_readable: true, structs_are_seqs: false, numeric_variants: false, } } } impl Settings { /// Creates a new transmutation settings with the defaults. pub fn new() -> Self { Default::default() } /// Sets whether to use human readable formats for transmutation. /// /// Some data structures may serialize differently for human-readable and /// non-human-readable formats. /// /// The default is to use human-readable transmutation. pub fn set_human_readable(&mut self, human_readable: bool) -> &mut Self { self.human_readable = human_readable; self } /// Treat structs like `struct Foo { bar: Bar }` as maps when /// deserializing. /// /// This is the default. pub fn structs_are_maps(&mut self) -> &mut Self { self.structs_are_seqs = false; self } /// Treat structs like `struct Foo { bar: Bar }` as seqs when /// deserializing. pub fn structs_are_seqs(&mut self) -> &mut Self { self.structs_are_seqs = true; self } /// Treat enum variants as keyed by strings. /// /// This is the default. pub fn variants_are_strings(&mut self) -> &mut Self { self.numeric_variants = false; self } /// Treat enum variants as keyed by numbers. pub fn variants_are_numbers(&mut self) -> &mut Self { self.numeric_variants = true; self } } struct Transmute<'settings> { settings: &'settings Settings, collection: Collection, } impl<'settings> Transmute<'settings> { fn new(collection: Collection, settings: &'settings Settings) -> Self { Self { collection, settings } } } impl<'settings, 'de> Deserializer<'de> for Transmute<'settings> { type Error = TransmuteError; fn deserialize_any>( self, visitor: Vis, ) -> Result { let settings = self.settings; match self.collection { Collection::Bool(value) => visitor.visit_bool(value), Collection::I8(value) => visitor.visit_i8(value), Collection::I16(value) => visitor.visit_i16(value), Collection::I32(value) => visitor.visit_i32(value), Collection::I64(value) => visitor.visit_i64(value), Collection::I128(value) => visitor.visit_i128(value), Collection::U8(value) => visitor.visit_u8(value), Collection::U16(value) => visitor.visit_u16(value), Collection::U32(value) => visitor.visit_u32(value), Collection::U64(value) => visitor.visit_u64(value), Collection::U128(value) => visitor.visit_u128(value), Collection::F32(value) => visitor.visit_f32(value), Collection::F64(value) => visitor.visit_f64(value), Collection::Char(value) => visitor.visit_char(value), Collection::Str(value) => { visitor.visit_string(String::from(value)) }, Collection::Bytes(value) => { visitor.visit_byte_buf(Vec::from(value)) }, Collection::Some(value) => { visitor.visit_some(Self { settings, collection: *value, }) }, Collection::None => visitor.visit_none(), | Collection::Unit | Collection::UnitStruct { .. } | Collection::UnitVariant { .. } => visitor.visit_unit(), | Collection::NewtypeVariant { value, .. } | Collection::NewtypeStruct { value, .. } => { visitor.visit_newtype_struct(Self { settings, collection: *value, }) }, | Collection::Seq(_) | Collection::Tuple(_) | Collection::TupleVariant { .. } | Collection::TupleStruct { .. } => visitor.visit_seq(self), Collection::Map(_) => { visitor.visit_map(MapAccess { transmute: self, // FIXME? value: Err(TransmuteError(())), }) } | Collection::StructVariant { .. } | Collection::Struct { .. } => { match self.settings.structs_are_seqs { false => visitor.visit_map(MapAccess { transmute: self, // FIXME? value: Err(TransmuteError(())), }), true => visitor.visit_seq(self), } } } } fn deserialize_enum>( self, name: &'static str, variants: &'static [&'static str], visitor: Vis, ) -> Result { match self.collection { | Collection::UnitVariant { .. } | Collection::NewtypeVariant { .. } | Collection::TupleVariant { .. } | Collection::StructVariant { .. } => visitor.visit_enum(self), _ => self.deserialize_any(visitor), } } fn deserialize_ignored_any>( self, visitor: Vis, ) -> Result { visitor.visit_unit() } serde::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 } fn is_human_readable(&self) -> bool { self.settings.human_readable } } struct MapAccess<'settings> { transmute: Transmute<'settings>, value: Result, } impl<'settings, 'de> serde::de::MapAccess<'de> for MapAccess<'settings> { type Error = TransmuteError; fn next_key_seed( &mut self, seed: T, ) -> Result, Self::Error> where T: DeserializeSeed<'de>, { if self.value.is_ok() { // FIXME? return Err(TransmuteError(())); } match &mut self.transmute.collection { Collection::Map(values) => { values.next().map(|(k, v)| { self.value = Ok(v); seed.deserialize(Transmute { settings: self.transmute.settings, collection: k, }) }).transpose() }, | Collection::StructVariant { values, .. } | Collection::Struct { values, .. } => { values.next().map(|(k, v)| { self.value = Ok(v); seed.deserialize(serde::de::value::StrDeserializer::new(k)) }).transpose() }, _ => unreachable!(), } } fn next_value_seed( &mut self, seed: T, ) -> Result where T: DeserializeSeed<'de>, { // FIXME? let v = std::mem::replace(&mut self.value, Err(TransmuteError(()))); v.and_then(|it| { seed.deserialize(Transmute { settings: self.transmute.settings, collection: it, }) }) } fn next_entry_seed( &mut self, key_seed: K, value_seed: V, ) -> Result, Self::Error> where K: DeserializeSeed<'de>, V: DeserializeSeed<'de>, { if self.value.is_ok() { // FIXME? return Err(TransmuteError(())); } match &mut self.transmute.collection { Collection::Map(values) => { values.next().map(|(k, v)| { key_seed.deserialize(Transmute { settings: self.transmute.settings, collection: k, }).and_then(|k| value_seed.deserialize(Transmute { settings: self.transmute.settings, collection: v, }).map(|v| (k, v))) }).transpose() }, | Collection::StructVariant { values, .. } | Collection::Struct { values, .. } => { values.next().map(|(k, v)| { key_seed.deserialize( serde::de::value::StrDeserializer::new(k) ).and_then(|k| value_seed.deserialize(Transmute { settings: self.transmute.settings, collection: v, }).map(|v| (k, v))) }).transpose() }, _ => unreachable!(), } } } impl<'settings, 'de> serde::de::SeqAccess<'de> for Transmute<'settings> { type Error = TransmuteError; fn next_element_seed( &mut self, seed: T, ) -> Result, Self::Error> where T: DeserializeSeed<'de>, { match &mut self.collection { | Collection::Seq(values) | Collection::Tuple(values) | Collection::TupleVariant { values, .. } | Collection::TupleStruct { values, .. } => values.next(), | Collection::StructVariant { values, .. } | Collection::Struct { values, .. } => values.next().map(|(_, v)| v), _ => unreachable!(), }.map(|value| seed.deserialize(Self { settings: self.settings, collection: value, })).transpose() } fn size_hint(&self) -> Option { match &self.collection { | Collection::Seq(values) | Collection::Tuple(values) | Collection::TupleVariant { values, .. } | Collection::TupleStruct { values, .. } => values.size_hint().1, | Collection::StructVariant { values, .. } | Collection::Struct { values, .. } => values.size_hint().1, _ => unreachable!(), } } } impl<'settings, 'de> serde::de::EnumAccess<'de> for Transmute<'settings> { type Error = TransmuteError; type Variant = Self; fn variant_seed( self, seed: T, ) -> Result<(T::Value, Self), Self::Error> where T: DeserializeSeed<'de>, { let tag = match self.collection { | Collection::UnitVariant { variant, variant_index, .. } | Collection::NewtypeVariant { variant, variant_index, .. } | Collection::TupleVariant { variant, variant_index, .. } | Collection::StructVariant { variant, variant_index, .. } => { (variant, variant_index) } _ => unreachable!(), }; let val = match self.settings.numeric_variants { false => seed.deserialize({ serde::de::value::StrDeserializer::new(tag.0) }), true => seed.deserialize({ serde::de::value::U32Deserializer::new(tag.1) }), }; val.map(|val| (val, self)) } } impl<'settings, 'de> serde::de::VariantAccess<'de> for Transmute<'settings> { type Error = TransmuteError; fn unit_variant(self) -> Result<(), Self::Error> { match self.collection { Collection::UnitVariant { .. } => Ok(()), _ => { let unexp = match self.collection { Collection::UnitVariant { .. } => { serde::de::Unexpected::UnitVariant }, Collection::NewtypeVariant { .. } => { serde::de::Unexpected::NewtypeVariant }, Collection::TupleVariant { .. } => { serde::de::Unexpected::TupleVariant }, Collection::StructVariant { .. } => { serde::de::Unexpected::StructVariant }, _ => unreachable!(), }; Err(Self::Error::invalid_type(unexp, &"unit variant")) } } } fn newtype_variant_seed(self, seed: T) -> Result where T: DeserializeSeed<'de>, { match self.collection { Collection::NewtypeVariant { value, .. } => { seed.deserialize(Self { settings: self.settings, collection: *value, }) }, _ => { let unexp = match self.collection { Collection::UnitVariant { .. } => { serde::de::Unexpected::UnitVariant }, Collection::NewtypeVariant { .. } => { serde::de::Unexpected::NewtypeVariant }, Collection::TupleVariant { .. } => { serde::de::Unexpected::TupleVariant }, Collection::StructVariant { .. } => { serde::de::Unexpected::StructVariant }, _ => unreachable!(), }; Err(Self::Error::invalid_type(unexp, &"newtype variant")) } } } fn tuple_variant( self, len: usize, visitor: Vis, ) -> Result where Vis: Visitor<'de>, { match self.collection { Collection::TupleVariant { .. } => { visitor.visit_seq(self) }, _ => { let unexp = match self.collection { Collection::UnitVariant { .. } => { serde::de::Unexpected::UnitVariant }, Collection::NewtypeVariant { .. } => { serde::de::Unexpected::NewtypeVariant }, Collection::TupleVariant { .. } => { serde::de::Unexpected::TupleVariant }, Collection::StructVariant { .. } => { serde::de::Unexpected::StructVariant }, _ => unreachable!(), }; Err(Self::Error::invalid_type(unexp, &"tuple variant")) } } } fn struct_variant( self, fields: &'static [&'static str], visitor: Vis, ) -> Result where Vis: Visitor<'de>, { match self.collection { Collection::StructVariant { .. } => { match self.settings.structs_are_seqs { false => visitor.visit_map(MapAccess { transmute: self, // FIXME? value: Err(TransmuteError(())), }), true => visitor.visit_seq(self), } }, _ => { let unexp = match self.collection { Collection::UnitVariant { .. } => { serde::de::Unexpected::UnitVariant }, Collection::NewtypeVariant { .. } => { serde::de::Unexpected::NewtypeVariant }, Collection::TupleVariant { .. } => { serde::de::Unexpected::TupleVariant }, Collection::StructVariant { .. } => { serde::de::Unexpected::StructVariant }, _ => unreachable!(), }; Err(Self::Error::invalid_type(unexp, &"struct variant")) } } } } #[derive(Copy, Clone, Debug)] struct Collect<'settings> { settings: &'settings Settings, } impl<'settings> Collect<'settings> { fn new(settings: &'settings Settings) -> Self { Self { settings, } } } impl<'settings> Serializer for Collect<'settings> { type Ok = Collection; type Error = TransmuteError; fn is_human_readable(&self) -> bool { self.settings.human_readable } type SerializeSeq = CollectSeq<'settings>; type SerializeTuple = CollectTuple<'settings>; type SerializeTupleStruct = CollectTupleStruct<'settings>; type SerializeTupleVariant = CollectTupleVariant<'settings>; type SerializeMap = CollectMap<'settings>; type SerializeStruct = CollectStruct<'settings>; type SerializeStructVariant = CollectStructVariant<'settings>; fn serialize_bool(self, value: bool) -> Result { Ok(Collection::Bool(value)) } fn serialize_i8(self, value: i8) -> Result { Ok(Collection::I8(value)) } fn serialize_i16(self, value: i16) -> Result { Ok(Collection::I16(value)) } fn serialize_i32(self, value: i32) -> Result { Ok(Collection::I32(value)) } fn serialize_i64(self, value: i64) -> Result { Ok(Collection::I64(value)) } fn serialize_i128(self, value: i128) -> Result { Ok(Collection::I128(value)) } fn serialize_u8(self, value: u8) -> Result { Ok(Collection::U8(value)) } fn serialize_u16(self, value: u16) -> Result { Ok(Collection::U16(value)) } fn serialize_u32(self, value: u32) -> Result { Ok(Collection::U32(value)) } fn serialize_u64(self, value: u64) -> Result { Ok(Collection::U64(value)) } fn serialize_u128(self, value: u128) -> Result { Ok(Collection::U128(value)) } fn serialize_f32(self, value: f32) -> Result { Ok(Collection::F32(value)) } fn serialize_f64(self, value: f64) -> Result { Ok(Collection::F64(value)) } fn serialize_char(self, value: char) -> Result { Ok(Collection::Char(value)) } fn serialize_str(self, value: &str) -> Result { Ok(Collection::Str(From::from(value))) } fn serialize_bytes(self, value: &[u8]) -> Result { Ok(Collection::Bytes(From::from(value))) } fn serialize_none(self) -> Result { Ok(Collection::None) } fn serialize_some(self, value: &T) -> Result where T: Serialize + ?Sized, { value.serialize(self).map(|it| Collection::Some(Box::new(it))) } fn serialize_unit(self) -> Result { Ok(Collection::Unit) } fn serialize_unit_struct( self, name: &'static str, ) -> Result { Ok(Collection::UnitStruct { name }) } fn serialize_unit_variant( self, name: &'static str, variant_index: u32, variant: &'static str, ) -> Result { Ok(Collection::UnitVariant { name, variant_index, variant }) } fn serialize_newtype_struct( self, name: &'static str, value: &T, ) -> Result where T: Serialize + ?Sized, { value.serialize(self).map(|it| Collection::NewtypeStruct { name, value: Box::new(it) }) } fn serialize_newtype_variant( self, name: &'static str, variant_index: u32, variant: &'static str, value: &T, ) -> Result where T: Serialize + ?Sized, { value.serialize(self).map(|it| Collection::NewtypeVariant { name, variant_index, variant, value: Box::new(it) }) } fn serialize_seq( self, len: Option, ) -> Result { Ok(CollectSeq { ser: self, values: len.map_or_else(Vec::new, Vec::with_capacity), }) } fn serialize_tuple( self, len: usize, ) -> Result { Ok(CollectTuple { ser: self, len: len, values: Vec::with_capacity(len), }) } fn serialize_tuple_struct( self, name: &'static str, len: usize ) -> Result { Ok(CollectTupleStruct { ser: self, len: len, name: name, values: Vec::with_capacity(len), }) } fn serialize_tuple_variant( self, name: &'static str, variant_index: u32, variant: &'static str, len: usize, ) -> Result { Ok(CollectTupleVariant { ser: self, len, name, variant_index, variant, values: Vec::with_capacity(len), }) } fn serialize_map( self, len: Option, ) -> Result { Ok(CollectMap { ser: self, values: len.map_or_else(Vec::new, Vec::with_capacity), // FIXME? key: Err(TransmuteError(())), }) } fn serialize_struct( self, name: &'static str, len: usize, ) -> Result { Ok(CollectStruct { ser: self, len: len, name: name, values: Vec::with_capacity(len), }) } fn serialize_struct_variant( self, name: &'static str, variant_index: u32, variant: &'static str, len: usize, ) -> Result { Ok(CollectStructVariant { ser: self, len, name, variant_index, variant, values: Vec::with_capacity(len), }) } } struct CollectSeq<'settings> { ser: Collect<'settings>, values: Vec, } struct CollectTuple<'settings> { ser: Collect<'settings>, len: usize, values: Vec, } struct CollectTupleStruct<'settings> { ser: Collect<'settings>, name: &'static str, len: usize, values: Vec, } struct CollectTupleVariant<'settings> { ser: Collect<'settings>, name: &'static str, variant: &'static str, variant_index: u32, len: usize, values: Vec, } struct CollectMap<'settings> { ser: Collect<'settings>, values: Vec<(Collection, Collection)>, key: Result, } struct CollectStruct<'settings> { ser: Collect<'settings>, name: &'static str, len: usize, values: Vec<(&'static str, Collection)>, } struct CollectStructVariant<'settings> { ser: Collect<'settings>, name: &'static str, variant: &'static str, variant_index: u32, len: usize, values: Vec<(&'static str, Collection)>, } impl<'settings> serde::ser::SerializeSeq for CollectSeq<'settings> { type Ok = Collection; type Error = TransmuteError; fn serialize_element(&mut self, value: &T) -> Result<(), Self::Error> where T: Serialize + ?Sized, { value.serialize(self.ser).map(|it| self.values.push(it)) } fn end(self) -> Result { Ok(Collection::Seq(self.values.into_iter())) } } impl<'settings> serde::ser::SerializeTuple for CollectTuple<'settings> { type Ok = Collection; type Error = TransmuteError; fn serialize_element(&mut self, value: &T) -> Result<(), Self::Error> where T: Serialize + ?Sized, { value.serialize(self.ser).map(|it| self.values.push(it)) } fn end(self) -> Result { if self.values.len() != self.len { // FIXME? Err(TransmuteError(())) } else { Ok(Collection::Tuple(self.values.into_iter())) } } } impl<'settings> serde::ser::SerializeTupleStruct for CollectTupleStruct<'settings> { type Ok = Collection; type Error = TransmuteError; fn serialize_field(&mut self, value: &T) -> Result<(), Self::Error> where T: Serialize + ?Sized, { value.serialize(self.ser).map(|it| self.values.push(it)) } fn end(self) -> Result { if self.values.len() != self.len { // FIXME? Err(TransmuteError(())) } else { Ok(Collection::TupleStruct { name: self.name, values: self.values.into_iter() }) } } } impl<'settings> serde::ser::SerializeTupleVariant for CollectTupleVariant<'settings> { type Ok = Collection; type Error = TransmuteError; fn serialize_field(&mut self, value: &T) -> Result<(), Self::Error> where T: Serialize + ?Sized, { value.serialize(self.ser).map(|it| self.values.push(it)) } fn end(self) -> Result { if self.values.len() != self.len { // FIXME? Err(TransmuteError(())) } else { Ok(Collection::TupleVariant { name: self.name, variant: self.variant, variant_index: self.variant_index, values: self.values.into_iter() }) } } } impl<'settings> serde::ser::SerializeMap for CollectMap<'settings> { type Ok = Collection; type Error = TransmuteError; fn serialize_key( &mut self, key: &T, ) -> Result<(), Self::Error> where T: Serialize + ?Sized, { key.serialize(self.ser).map(|it| self.key = Ok(it)) } fn serialize_value( &mut self, value: &T, ) -> Result<(), Self::Error> where T: Serialize + ?Sized, { // FIXME? let key = std::mem::replace(&mut self.key, Err(TransmuteError(()))); key.and_then(|key| { value.serialize(self.ser).map(|it| self.values.push((key, it))) }) } fn serialize_entry( &mut self, key: &K, value: &V, ) -> Result<(), Self::Error> where K: Serialize + ?Sized, V: Serialize + ?Sized, { if self.key.is_ok() { // FIXME? Err(TransmuteError(())) } else { key.serialize(self.ser).and_then(|key| { value.serialize(self.ser).map(|it| self.values.push((key, it))) }) } } fn end(self) -> Result { if self.key.is_ok() { // FIXME? Err(TransmuteError(())) } else { Ok(Collection::Map(self.values.into_iter())) } } } impl<'settings> serde::ser::SerializeStruct for CollectStruct<'settings> { type Ok = Collection; type Error = TransmuteError; fn serialize_field( &mut self, key: &'static str, value: &T, ) -> Result<(), Self::Error> where T: Serialize + ?Sized, { value.serialize(self.ser).map(|it| self.values.push((key, it))) } fn end(self) -> Result { if self.values.len() != self.len { // FIXME? Err(TransmuteError(())) } else { Ok(Collection::Struct { name: self.name, values: self.values.into_iter() }) } } } impl<'settings> serde::ser::SerializeStructVariant for CollectStructVariant<'settings> { type Ok = Collection; type Error = TransmuteError; fn serialize_field( &mut self, key: &'static str, value: &T, ) -> Result<(), Self::Error> where T: Serialize + ?Sized, { value.serialize(self.ser).map(|it| self.values.push((key, it))) } fn end(self) -> Result { if self.values.len() != self.len { // FIXME? Err(TransmuteError(())) } else { Ok(Collection::StructVariant { name: self.name, variant: self.variant, variant_index: self.variant_index, values: self.values.into_iter() }) } } } /// Types serialized by serde. Refer to `Serializer` for details. //#[derive(Debug)] enum Collection { Bool(bool), I8(i8), I16(i16), I32(i32), I64(i64), I128(i128), U8(u8), U16(u16), U32(u32), U64(u64), U128(u128), F32(f32), F64(f64), Char(char), Str(Box), Bytes(Box<[u8]>), Some(Box), None, Unit, UnitStruct { name: &'static str, }, UnitVariant { name: &'static str, variant: &'static str, variant_index: u32, }, NewtypeStruct { name: &'static str, value: Box, }, NewtypeVariant { name: &'static str, variant: &'static str, variant_index: u32, value: Box, }, Seq(std::vec::IntoIter), Tuple(std::vec::IntoIter), TupleStruct { name: &'static str, values: std::vec::IntoIter, }, TupleVariant { name: &'static str, variant: &'static str, variant_index: u32, values: std::vec::IntoIter, }, // NOTE: support for multimaps! Map(std::vec::IntoIter<(Collection, Collection)>), Struct { name: &'static str, values: std::vec::IntoIter<(&'static str, Collection)>, }, StructVariant { name: &'static str, variant: &'static str, variant_index: u32, values: std::vec::IntoIter<(&'static str, Collection)>, }, }