use super::Object;
use crate::{Error, Map, Result};
use serde::{
de::{
self, DeserializeOwned, DeserializeSeed, EnumAccess, IntoDeserializer, MapAccess,
SeqAccess, VariantAccess, Visitor,
},
forward_to_deserialize_any, Deserialize,
};
use std::{convert::TryFrom, fmt, result, vec};
pub fn from_object<T>(object: Object) -> Result<T>
where
T: DeserializeOwned,
{
T::deserialize(object)
}
impl<'de> Deserialize<'de> for Object {
fn deserialize<D>(deserializer: D) -> result::Result<Object, D::Error>
where
D: de::Deserializer<'de>,
{
struct ObjectVisitor;
impl<'de> Visitor<'de> for ObjectVisitor {
type Value = Object;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("any valid BDF object")
}
fn visit_bool<E>(self, value: bool) -> result::Result<Object, E>
where
E: de::Error,
{
Ok(Object::Boolean(value))
}
fn visit_i64<E>(self, value: i64) -> result::Result<Object, E>
where
E: de::Error,
{
Ok(Object::Integer(value))
}
fn visit_u64<E>(self, value: u64) -> result::Result<Object, E>
where
E: de::Error,
{
let value = i64::try_from(value).map_err(|_| {
de::Error::invalid_value(de::Unexpected::Unsigned(value), &self)
})?;
self.visit_i64(value)
}
fn visit_f64<E>(self, value: f64) -> result::Result<Object, E>
where
E: de::Error,
{
Ok(Object::Float(value))
}
fn visit_str<E>(self, value: &str) -> result::Result<Object, E>
where
E: de::Error,
{
self.visit_string(String::from(value))
}
fn visit_string<E>(self, value: String) -> result::Result<Object, E>
where
E: de::Error,
{
Ok(Object::String(value))
}
fn visit_bytes<E>(self, value: &[u8]) -> result::Result<Object, E>
where
E: de::Error,
{
self.visit_byte_buf(Vec::from(value))
}
fn visit_byte_buf<E>(self, value: Vec<u8>) -> result::Result<Object, E>
where
E: de::Error,
{
Ok(Object::Raw(value))
}
fn visit_none<E>(self) -> result::Result<Object, E>
where
E: de::Error,
{
Ok(Object::Null)
}
fn visit_some<D>(self, deserializer: D) -> result::Result<Object, D::Error>
where
D: de::Deserializer<'de>,
{
Deserialize::deserialize(deserializer)
}
fn visit_unit<E>(self) -> result::Result<Object, E>
where
E: de::Error,
{
Ok(Object::Null)
}
fn visit_seq<V>(self, mut visitor: V) -> result::Result<Object, V::Error>
where
V: SeqAccess<'de>,
{
let mut list = Vec::new();
while let Some(elem) = visitor.next_element()? {
list.push(elem);
}
Ok(Object::List(list))
}
fn visit_map<V>(self, mut visitor: V) -> result::Result<Object, V::Error>
where
V: MapAccess<'de>,
{
let mut map = Map::new();
while let Some((key, value)) = visitor.next_entry()? {
map.insert(key, value);
}
Ok(Object::Map(map))
}
}
deserializer.deserialize_any(ObjectVisitor)
}
}
impl<'de> de::Deserializer<'de> for Object {
type Error = Error;
fn deserialize_any<V>(self, visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
match self {
Object::Null => visitor.visit_unit(),
Object::Boolean(value) => visitor.visit_bool(value),
Object::Integer(value) => visitor.visit_i64(value),
Object::Float(value) => visitor.visit_f64(value),
Object::String(value) => visitor.visit_string(value),
Object::Raw(value) => visitor.visit_byte_buf(value),
Object::List(value) => visit_list(value, visitor),
Object::Map(value) => visit_map(value, visitor),
}
}
fn deserialize_bool<V>(self, visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
visitor.visit_bool(self.as_boolean()?)
}
fn deserialize_i8<V>(self, visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
match self {
Object::Integer(value) => visitor.visit_i8(i8::try_from(value)?),
_ => Err(Error::WrongType),
}
}
fn deserialize_i16<V>(self, visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
match self {
Object::Integer(value) => visitor.visit_i16(i16::try_from(value)?),
_ => Err(Error::WrongType),
}
}
fn deserialize_i32<V>(self, visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
match self {
Object::Integer(value) => visitor.visit_i32(i32::try_from(value)?),
_ => Err(Error::WrongType),
}
}
fn deserialize_i64<V>(self, visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
match self {
Object::Integer(value) => visitor.visit_i64(value),
_ => Err(Error::WrongType),
}
}
fn deserialize_u8<V>(self, visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
match self {
Object::Integer(value) => visitor.visit_u8(u8::try_from(value)?),
_ => Err(Error::WrongType),
}
}
fn deserialize_u16<V>(self, visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
match self {
Object::Integer(value) => visitor.visit_u16(u16::try_from(value)?),
_ => Err(Error::WrongType),
}
}
fn deserialize_u32<V>(self, visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
match self {
Object::Integer(value) => visitor.visit_u32(u32::try_from(value)?),
_ => Err(Error::WrongType),
}
}
fn deserialize_u64<V>(self, visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
match self {
Object::Integer(value) => visitor.visit_u64(u64::try_from(value)?),
_ => Err(Error::WrongType),
}
}
fn deserialize_f32<V>(self, visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
match self {
Object::Float(value) => visitor.visit_f32(value as f32),
_ => Err(Error::WrongType),
}
}
fn deserialize_f64<V>(self, visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
match self {
Object::Float(value) => visitor.visit_f64(value),
_ => Err(Error::WrongType),
}
}
fn deserialize_char<V>(self, visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
match self {
Object::Integer(value) => visitor.visit_char(char::try_from(u32::try_from(value)?)?),
_ => Err(Error::WrongType),
}
}
fn deserialize_str<V>(self, visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
self.deserialize_string(visitor)
}
fn deserialize_string<V>(self, visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
match self {
Object::String(value) => visitor.visit_string(value),
_ => Err(Error::WrongType),
}
}
fn deserialize_bytes<V>(self, visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
self.deserialize_byte_buf(visitor)
}
fn deserialize_byte_buf<V>(self, visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
match self {
Object::Raw(value) => visitor.visit_byte_buf(value),
_ => Err(Error::WrongType),
}
}
fn deserialize_option<V>(self, visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
match &self {
Object::Null => visitor.visit_none(),
_ => visitor.visit_some(self),
}
}
fn deserialize_unit<V>(self, visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
match self {
Object::Null => visitor.visit_unit(),
_ => Err(Error::WrongType),
}
}
fn deserialize_unit_struct<V>(self, _name: &'static str, visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
self.deserialize_unit(visitor)
}
fn deserialize_newtype_struct<V>(self, _name: &'static str, visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
visitor.visit_newtype_struct(self)
}
fn deserialize_seq<V>(self, visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
match self {
Object::List(value) => visit_list(value, visitor),
_ => Err(Error::WrongType),
}
}
fn deserialize_tuple<V>(self, _len: usize, visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
self.deserialize_seq(visitor)
}
fn deserialize_tuple_struct<V>(
self,
_name: &'static str,
_len: usize,
visitor: V,
) -> Result<V::Value>
where
V: Visitor<'de>,
{
self.deserialize_seq(visitor)
}
fn deserialize_map<V>(self, visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
match self {
Object::Map(value) => visit_map(value, visitor),
_ => Err(Error::WrongType),
}
}
fn deserialize_struct<V>(
self,
_name: &'static str,
fields: &'static [&'static str],
visitor: V,
) -> Result<V::Value>
where
V: Visitor<'de>,
{
self.deserialize_tuple(fields.len(), visitor)
}
fn deserialize_enum<V>(
self,
_name: &'static str,
_variants: &'static [&'static str],
visitor: V,
) -> Result<V::Value>
where
V: Visitor<'de>,
{
visitor.visit_enum(self)
}
fn deserialize_identifier<V>(self, visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
self.deserialize_string(visitor)
}
fn deserialize_ignored_any<V>(self, visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
self.deserialize_any(visitor)
}
}
impl<'de> EnumAccess<'de> for Object {
type Error = Error;
type Variant = Self;
fn variant_seed<V>(self, seed: V) -> Result<(V::Value, Self::Variant)>
where
V: DeserializeSeed<'de>,
{
match self {
Object::Integer(value) => {
let variant_index = u32::try_from(value)?;
let value: Result<_> = seed.deserialize(variant_index.into_deserializer());
Ok((value?, self))
}
Object::List(mut list) => {
if list.is_empty() {
return Err(Error::InvalidValue);
}
let variant_index = u32::try_from(list[0].as_integer()?)?;
let value: Result<_> = seed.deserialize(variant_index.into_deserializer());
Ok((value?, list.remove(1)))
}
_ => Err(Error::WrongType),
}
}
}
impl<'de> VariantAccess<'de> for Object {
type Error = Error;
fn unit_variant(self) -> Result<()> {
Ok(())
}
fn newtype_variant_seed<T>(self, seed: T) -> Result<T::Value>
where
T: DeserializeSeed<'de>,
{
seed.deserialize(self)
}
fn tuple_variant<V>(self, len: usize, visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
de::Deserializer::deserialize_tuple(self, len, visitor)
}
fn struct_variant<V>(self, fields: &'static [&'static str], visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
de::Deserializer::deserialize_tuple(self, fields.len(), visitor)
}
}
fn visit_list<'de, V>(list: Vec<Object>, visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
let mut deserializer = SeqDeserializer::new(list);
let seq = visitor.visit_seq(&mut deserializer)?;
let remaining = deserializer.iter.len();
if remaining == 0 {
Ok(seq)
} else {
Err(Error::InvalidLength)
}
}
fn visit_map<'de, V>(map: Map, visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
let mut deserializer = MapDeserializer::new(map);
let map = visitor.visit_map(&mut deserializer)?;
let remaining = deserializer.iter.len();
if remaining == 0 {
Ok(map)
} else {
Err(Error::InvalidLength)
}
}
struct SeqDeserializer {
iter: vec::IntoIter<Object>,
}
impl SeqDeserializer {
fn new(vec: Vec<Object>) -> Self {
SeqDeserializer {
iter: vec.into_iter(),
}
}
}
impl<'de> de::Deserializer<'de> for SeqDeserializer {
type Error = Error;
#[inline]
fn deserialize_any<V>(mut self, visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
let ret = visitor.visit_seq(&mut self)?;
let remaining = self.iter.len();
if remaining == 0 {
Ok(ret)
} else {
Err(Error::InvalidLength)
}
}
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 ignored_any
}
}
impl<'de> SeqAccess<'de> for SeqDeserializer {
type Error = Error;
fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>>
where
T: DeserializeSeed<'de>,
{
match self.iter.next() {
Some(value) => seed.deserialize(value).map(Some),
None => Ok(None),
}
}
fn size_hint(&self) -> Option<usize> {
match self.iter.size_hint() {
(lower, Some(upper)) if lower == upper => Some(upper),
_ => None,
}
}
}
struct MapDeserializer {
iter: <Map as IntoIterator>::IntoIter,
value: Option<Object>,
}
impl MapDeserializer {
fn new(map: Map) -> Self {
MapDeserializer {
iter: map.into_iter(),
value: None,
}
}
}
impl<'de> de::Deserializer<'de> for MapDeserializer {
type Error = Error;
#[inline]
fn deserialize_any<V>(self, visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
visitor.visit_map(self)
}
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 ignored_any
}
}
impl<'de> MapAccess<'de> for MapDeserializer {
type Error = Error;
fn next_key_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>>
where
T: DeserializeSeed<'de>,
{
match self.iter.next() {
Some((key, value)) => {
self.value = Some(value);
let key_de = key.into_deserializer();
seed.deserialize(key_de).map(Some)
}
None => Ok(None),
}
}
fn next_value_seed<T>(&mut self, seed: T) -> Result<T::Value>
where
T: DeserializeSeed<'de>,
{
match self.value.take() {
Some(value) => seed.deserialize(value),
None => Err(Error::InvalidValue),
}
}
fn size_hint(&self) -> Option<usize> {
match self.iter.size_hint() {
(lower, Some(upper)) if lower == upper => Some(upper),
_ => None,
}
}
}
#[cfg(test)]
mod test {
use super::*;
use serde::Deserialize;
use std::collections::HashMap;
#[test]
fn from_object_maps() {
let mut map = Map::new();
map.insert("foo".to_string(), Object::Integer(123));
map.insert("bar".to_string(), Object::Integer(456));
let obj = Object::Map(map);
let map = from_object(obj).unwrap();
let mut expected = HashMap::new();
expected.insert("foo".to_string(), 123u32);
expected.insert("bar".to_string(), 456u32);
assert_eq!(expected, map);
}
#[test]
fn from_object_structs() {
#[derive(Deserialize, Debug, PartialEq, Eq)]
struct Test {
x: bool,
y: u32,
z: Vec<String>,
}
let obj = Object::List(vec![
Object::Boolean(true),
Object::Integer(17),
Object::List(vec![
Object::String("foo".into()),
Object::String("bar".into()),
]),
]);
let s = from_object(obj).unwrap();
let expected = Test {
x: true,
y: 17,
z: vec!["foo".into(), "bar".into()],
};
assert_eq!(expected, s);
}
#[test]
fn from_object_enums() {
#[derive(Deserialize, Debug, PartialEq, Eq)]
enum Test {
UnitVariant,
NewTypeVariant(u32),
TupleVariant(bool, u32),
StructVariant { x: bool, y: u32 },
}
let obj = Object::Integer(0);
let e = from_object(obj).unwrap();
let expected = Test::UnitVariant;
assert_eq!(expected, e);
let obj = Object::List(vec![Object::Integer(1), Object::Integer(17)]);
let e = from_object(obj).unwrap();
let expected = Test::NewTypeVariant(17);
assert_eq!(expected, e);
let obj = Object::List(vec![
Object::Integer(2),
Object::List(vec![Object::Boolean(true), Object::Integer(17)]),
]);
let e = from_object(obj).unwrap();
let expected = Test::TupleVariant(true, 17);
assert_eq!(expected, e);
let obj = Object::List(vec![
Object::Integer(3),
Object::List(vec![Object::Boolean(true), Object::Integer(17)]),
]);
let e = from_object(obj).unwrap();
let expected = Test::StructVariant { x: true, y: 17 };
assert_eq!(expected, e);
}
#[test]
fn from_object_options() {
let obj = Object::Null;
let e = from_object(obj).unwrap();
let expected: Option<u32> = None;
assert_eq!(expected, e);
let obj = Object::Integer(17);
let e = from_object(obj).unwrap();
let expected = Some(17);
assert_eq!(expected, e);
}
}