use std::{fmt, vec}; use indexmap::IndexMap; use serde::{ de::{ self, Deserialize, DeserializeOwned, DeserializeSeed, EnumAccess, Error as DeError, IntoDeserializer, MapAccess, SeqAccess, Unexpected, VariantAccess, Visitor, }, forward_to_deserialize_any, }; use crate::{ConstValue, Name}; /// This type represents errors that can occur when deserializing. #[derive(Debug)] pub struct DeserializerError(String); impl de::Error for DeserializerError { #[inline] fn custom(msg: T) -> Self { DeserializerError(msg.to_string()) } } impl std::error::Error for DeserializerError { #[inline] fn description(&self) -> &str { "Value deserializer error" } } impl fmt::Display for DeserializerError { #[inline] fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { DeserializerError(msg) => write!(f, "{}", msg), } } } impl From for DeserializerError { #[inline] fn from(e: de::value::Error) -> DeserializerError { DeserializerError(e.to_string()) } } impl ConstValue { #[inline] fn unexpected(&self) -> Unexpected { match self { ConstValue::Null => Unexpected::Unit, ConstValue::Number(_) => Unexpected::Other("number"), ConstValue::String(v) => Unexpected::Str(v), ConstValue::Boolean(v) => Unexpected::Bool(*v), ConstValue::Binary(v) => Unexpected::Bytes(v), ConstValue::Enum(v) => Unexpected::Str(v), ConstValue::List(_) => Unexpected::Seq, ConstValue::Object(_) => Unexpected::Map, } } } fn visit_array<'de, V>(array: Vec, visitor: V) -> Result where V: Visitor<'de>, { let len = array.len(); let mut deserializer = SeqDeserializer::new(array); let seq = visitor.visit_seq(&mut deserializer)?; let remaining = deserializer.iter.len(); if remaining == 0 { Ok(seq) } else { Err(DeserializerError::invalid_length( len, &"fewer elements in array", )) } } fn visit_object<'de, V>( object: IndexMap, visitor: V, ) -> Result where V: Visitor<'de>, { let len = object.len(); let mut deserializer = MapDeserializer::new(object); let map = visitor.visit_map(&mut deserializer)?; let remaining = deserializer.iter.len(); if remaining == 0 { Ok(map) } else { Err(DeserializerError::invalid_length( len, &"fewer elements in map", )) } } impl<'de> de::Deserializer<'de> for ConstValue { type Error = DeserializerError; #[inline] fn deserialize_any(self, visitor: V) -> Result<>::Value, Self::Error> where V: Visitor<'de>, { match self { ConstValue::Null => visitor.visit_unit(), ConstValue::Number(v) => v .deserialize_any(visitor) .map_err(|err| DeserializerError(err.to_string())), ConstValue::String(v) => visitor.visit_str(&v), ConstValue::Boolean(v) => visitor.visit_bool(v), ConstValue::Binary(bytes) => visitor.visit_bytes(&*bytes), ConstValue::Enum(v) => visitor.visit_str(v.as_str()), ConstValue::List(v) => visit_array(v, visitor), ConstValue::Object(v) => visit_object(v, visitor), } } forward_to_deserialize_any! { bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string bytes byte_buf unit unit_struct seq tuple tuple_struct map struct identifier ignored_any } #[inline] fn deserialize_option(self, visitor: V) -> Result<>::Value, Self::Error> where V: Visitor<'de>, { match self { ConstValue::Null => visitor.visit_none(), _ => visitor.visit_some(self), } } #[inline] fn deserialize_newtype_struct( self, _name: &'static str, visitor: V, ) -> Result<>::Value, Self::Error> where V: Visitor<'de>, { visitor.visit_newtype_struct(self) } fn deserialize_enum( self, _name: &'static str, _variants: &'static [&'static str], visitor: V, ) -> Result<>::Value, Self::Error> where V: Visitor<'de>, { let (variant, value) = match self { ConstValue::Object(value) => { let mut iter = value.into_iter(); let (variant, value) = match iter.next() { Some(v) => v, None => { return Err(serde::de::Error::invalid_value( Unexpected::Map, &"map with a single key", )); } }; // enums are encoded in json as maps with a single key:value pair if iter.next().is_some() { return Err(serde::de::Error::invalid_value( Unexpected::Map, &"map with a single key", )); } (variant, Some(value)) } ConstValue::String(variant) => (Name::new(&variant), None), ConstValue::Enum(variant) => (variant, None), other => { return Err(DeserializerError::invalid_type( other.unexpected(), &"string or map", )); } }; visitor.visit_enum(EnumDeserializer { variant, value }) } #[inline] fn is_human_readable(&self) -> bool { true } } struct EnumDeserializer { variant: Name, value: Option, } impl<'de> EnumAccess<'de> for EnumDeserializer { type Error = DeserializerError; type Variant = VariantDeserializer; #[inline] fn variant_seed(self, seed: V) -> Result<(V::Value, VariantDeserializer), DeserializerError> where V: DeserializeSeed<'de>, { let variant = self.variant.into_deserializer(); let visitor = VariantDeserializer { value: self.value }; seed.deserialize(variant).map(|v| (v, visitor)) } } impl<'de> IntoDeserializer<'de, DeserializerError> for ConstValue { type Deserializer = Self; fn into_deserializer(self) -> Self::Deserializer { self } } struct VariantDeserializer { value: Option, } impl<'de> VariantAccess<'de> for VariantDeserializer { type Error = DeserializerError; #[inline] fn unit_variant(self) -> Result<(), DeserializerError> { match self.value { Some(value) => Deserialize::deserialize(value), None => Ok(()), } } #[inline] fn newtype_variant_seed(self, seed: T) -> Result where T: DeserializeSeed<'de>, { match self.value { Some(value) => seed.deserialize(value), None => Err(DeserializerError::invalid_type( Unexpected::UnitVariant, &"newtype variant", )), } } fn tuple_variant(self, _len: usize, visitor: V) -> Result where V: Visitor<'de>, { match self.value { Some(ConstValue::List(v)) => { serde::Deserializer::deserialize_any(SeqDeserializer::new(v), visitor) } Some(other) => Err(serde::de::Error::invalid_type( other.unexpected(), &"tuple variant", )), None => Err(DeserializerError::invalid_type( Unexpected::UnitVariant, &"tuple variant", )), } } fn struct_variant( self, _fields: &'static [&'static str], visitor: V, ) -> Result where V: Visitor<'de>, { match self.value { Some(ConstValue::Object(v)) => { serde::Deserializer::deserialize_any(MapDeserializer::new(v), visitor) } Some(other) => Err(DeserializerError::invalid_type( other.unexpected(), &"struct variant", )), None => Err(DeserializerError::invalid_type( Unexpected::UnitVariant, &"struct variant", )), } } } struct SeqDeserializer { iter: vec::IntoIter, } impl SeqDeserializer { fn new(vec: Vec) -> Self { SeqDeserializer { iter: vec.into_iter(), } } } impl<'de> serde::Deserializer<'de> for SeqDeserializer { type Error = DeserializerError; #[inline] fn deserialize_any(mut self, visitor: V) -> Result where V: Visitor<'de>, { let len = self.iter.len(); if len == 0 { visitor.visit_unit() } else { let ret = visitor.visit_seq(&mut self)?; let remaining = self.iter.len(); if remaining == 0 { Ok(ret) } else { Err(DeserializerError::invalid_length( len, &"fewer elements in array", )) } } } 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 = DeserializerError; fn next_element_seed(&mut self, seed: T) -> Result, DeserializerError> where T: DeserializeSeed<'de>, { match self.iter.next() { Some(value) => seed.deserialize(value).map(Some), None => Ok(None), } } #[inline] fn size_hint(&self) -> Option { match self.iter.size_hint() { (lower, Some(upper)) if lower == upper => Some(upper), _ => None, } } } struct MapDeserializer { iter: as IntoIterator>::IntoIter, value: Option, } impl MapDeserializer { #[inline] fn new(map: IndexMap) -> Self { MapDeserializer { iter: map.into_iter(), value: None, } } } impl<'de> MapAccess<'de> for MapDeserializer { type Error = DeserializerError; fn next_key_seed(&mut self, seed: T) -> Result, DeserializerError> where T: DeserializeSeed<'de>, { match self.iter.next() { Some((key, value)) => { self.value = Some(value); let key_de = MapKeyDeserializer { key }; seed.deserialize(key_de).map(Some) } None => Ok(None), } } #[inline] fn next_value_seed(&mut self, seed: T) -> Result where T: DeserializeSeed<'de>, { match self.value.take() { Some(value) => seed.deserialize(value), None => Err(serde::de::Error::custom("value is missing")), } } #[inline] fn size_hint(&self) -> Option { match self.iter.size_hint() { (lower, Some(upper)) if lower == upper => Some(upper), _ => None, } } } impl<'de> serde::Deserializer<'de> for MapDeserializer { type Error = DeserializerError; #[inline] fn deserialize_any(self, visitor: V) -> Result 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 } } struct MapKeyDeserializer { key: Name, } impl<'de> serde::Deserializer<'de> for MapKeyDeserializer { type Error = DeserializerError; #[inline] fn deserialize_any(self, visitor: V) -> Result where V: Visitor<'de>, { NameDeserializer::new(self.key).deserialize_any(visitor) } #[inline] fn deserialize_enum( self, name: &'static str, variants: &'static [&'static str], visitor: V, ) -> Result where V: Visitor<'de>, { self.key .into_deserializer() .deserialize_enum(name, variants, visitor) } forward_to_deserialize_any! { bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes byte_buf unit unit_struct seq tuple option newtype_struct tuple_struct map struct identifier ignored_any } } struct NameDeserializer { value: Name, } impl NameDeserializer { #[inline] fn new(value: Name) -> Self { NameDeserializer { value } } } impl<'de> de::Deserializer<'de> for NameDeserializer { type Error = DeserializerError; #[inline] fn deserialize_any(self, visitor: V) -> Result where V: de::Visitor<'de>, { visitor.visit_string(self.value.to_string()) } 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 enum tuple_struct map struct identifier ignored_any } } /// Interpret a `ConstValue` as an instance of type `T`. #[inline] pub fn from_value(value: ConstValue) -> Result { T::deserialize(value) }