// 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::{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, } impl Default for Settings { fn default() -> Self { Self { human_readable: true, structs_are_seqs: 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 } } 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 { todo!() } 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 enum identifier } } #[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)) } } 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)) } } } 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 }) } } } 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 }) } } } 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 end(self) -> Result { if self.key.is_ok() { // FIXME? Err(TransmuteError(())) } else { Ok(Collection::Map(self.values)) } } } 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 }) } } } 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 }) } } } /// 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(Vec), 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(Vec), Tuple(Vec), TupleStruct { name: &'static str, values: Vec, }, TupleVariant { name: &'static str, variant: &'static str, variant_index: u32, values: Vec, }, // NOTE: support for multimaps! Map(Vec<(Collection, Collection)>), Struct { name: &'static str, values: Vec<(&'static str, Collection)>, }, StructVariant { name: &'static str, variant: &'static str, variant_index: u32, values: Vec<(&'static str, Collection)>, }, }