// 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<D, TransmuteError> {
transmute_seed(s, std::marker::PhantomData::<D>, 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<D::Value, TransmuteError> {
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: std::fmt::Display>(t: T) -> Self {
todo!()
}
}
impl serde::ser::Error for TransmuteError {
fn custom<T: std::fmt::Display>(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<Vis: Visitor<'de>>(
self,
visitor: Vis,
) -> Result<Vis::Value, Self::Error> {
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(_) => {
todo!()
}
| Collection::StructVariant { .. }
| Collection::Struct { .. }
=> {
todo!()
}
}
}
fn deserialize_enum<Vis: Visitor<'de>>(
self,
name: &'static str,
variants: &'static [&'static str],
visitor: Vis,
) -> Result<Vis::Value, Self::Error> {
match self.collection {
| Collection::UnitVariant { .. }
| Collection::NewtypeVariant { .. }
| Collection::TupleVariant { .. }
| Collection::StructVariant { .. }
=> visitor.visit_enum(self),
// FIXME?
_ => Err(TransmuteError(())),
}
}
fn deserialize_ignored_any<Vis: Visitor<'de>>(
self,
visitor: Vis,
) -> Result<Vis::Value, Self::Error> {
visitor.visit_unit()
}
serde::forward_to_deserialize_any! {
<Vis: Visitor<'de>>
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
}
}
impl<'settings, 'de> serde::de::SeqAccess<'de> for Transmute<'settings> {
type Error = TransmuteError;
fn next_element_seed<T>(
&mut self,
seed: T,
) -> Result<Option<T::Value>, Self::Error>
where
T: DeserializeSeed<'de>,
{
match &mut self.collection {
| Collection::Seq(values)
| Collection::Tuple(values)
| Collection::TupleVariant { values, .. }
| Collection::TupleStruct { values, .. }
=> values.next(),
_ => unreachable!(),
}.map(|value| seed.deserialize(Self {
settings: self.settings,
collection: value,
})).transpose()
}
fn size_hint(&self) -> Option<usize> {
match &self.collection {
| Collection::Seq(values)
| Collection::Tuple(values)
| Collection::TupleVariant { values, .. }
| Collection::TupleStruct { 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<T>(
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<T>(self, seed: T) -> Result<T::Value, Self::Error>
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<Vis>(
self,
len: usize,
visitor: Vis,
) -> Result<Vis::Value, Self::Error>
where
Vis: Visitor<'de>,
{
match self.collection {
Collection::TupleVariant { .. } => todo!(),
_ => {
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<Vis>(
self,
fields: &'static [&'static str],
visitor: Vis,
) -> Result<Vis::Value, Self::Error>
where
Vis: Visitor<'de>,
{
match self.collection {
Collection::StructVariant { .. } => todo!(),
_ => {
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<Self::Ok, Self::Error> {
Ok(Collection::Bool(value))
}
fn serialize_i8(self, value: i8) -> Result<Self::Ok, Self::Error> {
Ok(Collection::I8(value))
}
fn serialize_i16(self, value: i16) -> Result<Self::Ok, Self::Error> {
Ok(Collection::I16(value))
}
fn serialize_i32(self, value: i32) -> Result<Self::Ok, Self::Error> {
Ok(Collection::I32(value))
}
fn serialize_i64(self, value: i64) -> Result<Self::Ok, Self::Error> {
Ok(Collection::I64(value))
}
fn serialize_i128(self, value: i128) -> Result<Self::Ok, Self::Error> {
Ok(Collection::I128(value))
}
fn serialize_u8(self, value: u8) -> Result<Self::Ok, Self::Error> {
Ok(Collection::U8(value))
}
fn serialize_u16(self, value: u16) -> Result<Self::Ok, Self::Error> {
Ok(Collection::U16(value))
}
fn serialize_u32(self, value: u32) -> Result<Self::Ok, Self::Error> {
Ok(Collection::U32(value))
}
fn serialize_u64(self, value: u64) -> Result<Self::Ok, Self::Error> {
Ok(Collection::U64(value))
}
fn serialize_u128(self, value: u128) -> Result<Self::Ok, Self::Error> {
Ok(Collection::U128(value))
}
fn serialize_f32(self, value: f32) -> Result<Self::Ok, Self::Error> {
Ok(Collection::F32(value))
}
fn serialize_f64(self, value: f64) -> Result<Self::Ok, Self::Error> {
Ok(Collection::F64(value))
}
fn serialize_char(self, value: char) -> Result<Self::Ok, Self::Error> {
Ok(Collection::Char(value))
}
fn serialize_str(self, value: &str) -> Result<Self::Ok, Self::Error> {
Ok(Collection::Str(From::from(value)))
}
fn serialize_bytes(self, value: &[u8]) -> Result<Self::Ok, Self::Error> {
Ok(Collection::Bytes(From::from(value)))
}
fn serialize_none(self) -> Result<Self::Ok, Self::Error> {
Ok(Collection::None)
}
fn serialize_some<T>(self, value: &T) -> Result<Self::Ok, Self::Error>
where
T: Serialize + ?Sized,
{
value.serialize(self).map(|it| Collection::Some(Box::new(it)))
}
fn serialize_unit(self) -> Result<Self::Ok, Self::Error> {
Ok(Collection::Unit)
}
fn serialize_unit_struct(
self,
name: &'static str,
) -> Result<Self::Ok, Self::Error> {
Ok(Collection::UnitStruct {
name
})
}
fn serialize_unit_variant(
self,
name: &'static str,
variant_index: u32,
variant: &'static str,
) -> Result<Self::Ok, Self::Error> {
Ok(Collection::UnitVariant {
name, variant_index, variant
})
}
fn serialize_newtype_struct<T>(
self,
name: &'static str,
value: &T,
) -> Result<Self::Ok, Self::Error>
where
T: Serialize + ?Sized,
{
value.serialize(self).map(|it| Collection::NewtypeStruct {
name, value: Box::new(it)
})
}
fn serialize_newtype_variant<T>(
self,
name: &'static str,
variant_index: u32,
variant: &'static str,
value: &T,
) -> Result<Self::Ok, Self::Error>
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<usize>,
) -> Result<Self::SerializeSeq, Self::Error> {
Ok(CollectSeq {
ser: self,
values: len.map_or_else(Vec::new, Vec::with_capacity),
})
}
fn serialize_tuple(
self,
len: usize,
) -> Result<Self::SerializeTuple, Self::Error> {
Ok(CollectTuple {
ser: self,
len: len,
values: Vec::with_capacity(len),
})
}
fn serialize_tuple_struct(
self,
name: &'static str,
len: usize
) -> Result<Self::SerializeTupleStruct, Self::Error> {
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<Self::SerializeTupleVariant, Self::Error> {
Ok(CollectTupleVariant {
ser: self,
len, name, variant_index, variant,
values: Vec::with_capacity(len),
})
}
fn serialize_map(
self,
len: Option<usize>,
) -> Result<Self::SerializeMap, Self::Error> {
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<Self::SerializeStruct, Self::Error> {
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<Self::SerializeStructVariant, Self::Error> {
Ok(CollectStructVariant {
ser: self,
len, name, variant_index, variant,
values: Vec::with_capacity(len),
})
}
}
struct CollectSeq<'settings> {
ser: Collect<'settings>,
values: Vec<Collection>,
}
struct CollectTuple<'settings> {
ser: Collect<'settings>,
len: usize,
values: Vec<Collection>,
}
struct CollectTupleStruct<'settings> {
ser: Collect<'settings>,
name: &'static str,
len: usize,
values: Vec<Collection>,
}
struct CollectTupleVariant<'settings> {
ser: Collect<'settings>,
name: &'static str,
variant: &'static str,
variant_index: u32,
len: usize,
values: Vec<Collection>,
}
struct CollectMap<'settings> {
ser: Collect<'settings>,
values: Vec<(Collection, Collection)>,
key: Result<Collection, TransmuteError>,
}
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<T>(&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<Self::Ok, Self::Error> {
Ok(Collection::Seq(self.values.into_iter()))
}
}
impl<'settings> serde::ser::SerializeTuple for CollectTuple<'settings> {
type Ok = Collection;
type Error = TransmuteError;
fn serialize_element<T>(&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<Self::Ok, Self::Error> {
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<T>(&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<Self::Ok, Self::Error> {
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<T>(&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<Self::Ok, Self::Error> {
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<T>(
&mut self,
key: &T,
) -> Result<(), Self::Error>
where
T: Serialize + ?Sized,
{
key.serialize(self.ser).map(|it| self.key = Ok(it))
}
fn serialize_value<T>(
&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<Self::Ok, Self::Error> {
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<T>(
&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<Self::Ok, Self::Error> {
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<T>(
&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<Self::Ok, Self::Error> {
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<str>),
Bytes(Box<[u8]>),
Some(Box<Collection>),
None,
Unit,
UnitStruct {
name: &'static str,
},
UnitVariant {
name: &'static str,
variant: &'static str,
variant_index: u32,
},
NewtypeStruct {
name: &'static str,
value: Box<Collection>,
},
NewtypeVariant {
name: &'static str,
variant: &'static str,
variant_index: u32,
value: Box<Collection>,
},
Seq(std::vec::IntoIter<Collection>),
Tuple(std::vec::IntoIter<Collection>),
TupleStruct {
name: &'static str,
values: std::vec::IntoIter<Collection>,
},
TupleVariant {
name: &'static str,
variant: &'static str,
variant_index: u32,
values: std::vec::IntoIter<Collection>,
},
// 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)>,
},
}