// 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<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,
}
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<Vis: Visitor<'de>>(
self,
visitor: Vis,
) -> Result<Vis::Value, Self::Error> {
todo!()
}
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 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<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))
}
}
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))
}
}
}
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
})
}
}
}
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
})
}
}
}
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))
}
}
}
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
})
}
}
}
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
})
}
}
}
/// 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(Vec<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(Vec<Collection>),
Tuple(Vec<Collection>),
TupleStruct {
name: &'static str,
values: Vec<Collection>,
},
TupleVariant {
name: &'static str,
variant: &'static str,
variant_index: u32,
values: Vec<Collection>,
},
// 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)>,
},
}