summary refs log blame commit diff stats
path: root/src/lib.rs
blob: c15c45bb48197aaa6bf95e5084096365e67b60a2 (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15














                                                                               
                          

                                                                     





                                                                    
                                                              







                                                                       

                                                          




                              




















                                                                    
                           
                             




                                             
                           

 




                                    
                                    



         










                                                                             
                                                           



















                                                                             













                                                         
 




















                                                                           







































































                                                                 












                                                                            




























































































































































































                                                                              














































































































































































































































































                                                                             
                                                    















                                                                            
                                                          


















                                                                                    
                                               





















                                                                                      
                                               

































                                                                            
                                                        






















                                                                          
                                               

























                                                                                        
                                               





                                                                 
                  















                  
                     




















                               

                                          

                           
                                               




                              
                                               

                                   
                                                      

                           
                                                               




                              
                                                               

      
// 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)>,
    },
}