use crate::error::{Error, Result};
use crate::parse::{parse, Value};
use indexmap::IndexMap;
use serde::de::{
self, DeserializeOwned, DeserializeSeed, EnumAccess, IntoDeserializer, MapAccess, SeqAccess,
VariantAccess, Visitor,
};
pub fn from_str<T: DeserializeOwned>(input: &str) -> Result<T> {
let value = parse(input)?;
T::deserialize(ValueDeserializer(value))
}
pub fn from_value<T: DeserializeOwned>(value: Value) -> Result<T> {
T::deserialize(ValueDeserializer(value))
}
struct ValueDeserializer(Value);
impl<'de> de::Deserializer<'de> for ValueDeserializer {
type Error = Error;
fn deserialize_any<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
match self.0 {
Value::Scalar(s) => {
if s == "null" {
return visitor.visit_unit();
}
if s == "true" {
return visitor.visit_bool(true);
}
if s == "false" {
return visitor.visit_bool(false);
}
if let Ok(n) = s.parse::<i64>() {
return visitor.visit_i64(n);
}
if let Ok(n) = s.parse::<f64>() {
return visitor.visit_f64(n);
}
visitor.visit_string(s)
}
Value::Array(items) => visitor.visit_seq(SeqDe::new(items)),
Value::Object(map) => visitor.visit_map(MapDe::new(map)),
}
}
fn deserialize_bool<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
match &self.0 {
Value::Scalar(s) => match s.as_str() {
"true" => visitor.visit_bool(true),
"false" => visitor.visit_bool(false),
other => Err(Error::Parse(format!("expected bool, got '{other}'"))),
},
_ => Err(Error::Parse("expected scalar for bool".into())),
}
}
fn deserialize_i8<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
let n = parse_int(&self.0)?;
visitor.visit_i8(
i8::try_from(n).map_err(|_| Error::Parse(format!("value {n} out of range for i8")))?,
)
}
fn deserialize_i16<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
let n = parse_int(&self.0)?;
visitor.visit_i16(
i16::try_from(n)
.map_err(|_| Error::Parse(format!("value {n} out of range for i16")))?,
)
}
fn deserialize_i32<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
let n = parse_int(&self.0)?;
visitor.visit_i32(
i32::try_from(n)
.map_err(|_| Error::Parse(format!("value {n} out of range for i32")))?,
)
}
fn deserialize_i64<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
visitor.visit_i64(parse_int(&self.0)?)
}
fn deserialize_u8<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
let n = parse_uint(&self.0)?;
visitor.visit_u8(
u8::try_from(n).map_err(|_| Error::Parse(format!("value {n} out of range for u8")))?,
)
}
fn deserialize_u16<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
let n = parse_uint(&self.0)?;
visitor.visit_u16(
u16::try_from(n)
.map_err(|_| Error::Parse(format!("value {n} out of range for u16")))?,
)
}
fn deserialize_u32<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
let n = parse_uint(&self.0)?;
visitor.visit_u32(
u32::try_from(n)
.map_err(|_| Error::Parse(format!("value {n} out of range for u32")))?,
)
}
fn deserialize_u64<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
visitor.visit_u64(parse_uint(&self.0)?)
}
fn deserialize_f32<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
#[allow(clippy::cast_possible_truncation)]
visitor.visit_f32(parse_float(&self.0)? as f32)
}
fn deserialize_f64<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
visitor.visit_f64(parse_float(&self.0)?)
}
fn deserialize_char<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
if let Value::Scalar(s) = &self.0 {
let mut chars = s.chars();
if let Some(c) = chars.next() {
if chars.next().is_none() {
return visitor.visit_char(c);
}
}
}
Err(Error::Parse("expected single-character scalar".into()))
}
fn deserialize_str<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
if let Value::Scalar(s) = self.0 {
visitor.visit_string(s)
} else {
Err(Error::Parse("expected scalar string".into()))
}
}
fn deserialize_string<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
self.deserialize_str(visitor)
}
fn deserialize_bytes<V: Visitor<'de>>(self, _visitor: V) -> Result<V::Value> {
Err(Error::UnsupportedType("bytes"))
}
fn deserialize_byte_buf<V: Visitor<'de>>(self, _visitor: V) -> Result<V::Value> {
Err(Error::UnsupportedType("byte_buf"))
}
fn deserialize_option<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
if self.0.is_null() {
visitor.visit_none()
} else {
visitor.visit_some(self)
}
}
fn deserialize_unit<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
if self.0.is_null() {
visitor.visit_unit()
} else {
Err(Error::Parse(format!(
"expected null, found {}",
self.0.type_name()
)))
}
}
fn deserialize_unit_struct<V: Visitor<'de>>(
self,
_name: &'static str,
visitor: V,
) -> Result<V::Value> {
self.deserialize_unit(visitor)
}
fn deserialize_newtype_struct<V: Visitor<'de>>(
self,
_name: &'static str,
visitor: V,
) -> Result<V::Value> {
visitor.visit_newtype_struct(self)
}
fn deserialize_seq<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
match self.0 {
Value::Array(items) => visitor.visit_seq(SeqDe::new(items)),
_ => Err(Error::Parse("expected array value".into())),
}
}
fn deserialize_tuple<V: Visitor<'de>>(self, _len: usize, visitor: V) -> Result<V::Value> {
self.deserialize_seq(visitor)
}
fn deserialize_tuple_struct<V: Visitor<'de>>(
self,
_name: &'static str,
_len: usize,
visitor: V,
) -> Result<V::Value> {
self.deserialize_seq(visitor)
}
fn deserialize_map<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
match self.0 {
Value::Object(map) => visitor.visit_map(MapDe::new(map)),
_ => Err(Error::Parse("expected object value".into())),
}
}
fn deserialize_struct<V: Visitor<'de>>(
self,
_name: &'static str,
_fields: &'static [&'static str],
visitor: V,
) -> Result<V::Value> {
self.deserialize_map(visitor)
}
fn deserialize_enum<V: Visitor<'de>>(
self,
_name: &'static str,
_variants: &'static [&'static str],
visitor: V,
) -> Result<V::Value> {
match self.0 {
Value::Scalar(s) => {
visitor.visit_enum(s.into_deserializer())
}
Value::Object(map) => {
if map.len() != 1 {
return Err(Error::Parse("enum object must have exactly one key".into()));
}
let (variant, payload) = map
.into_iter()
.next()
.ok_or_else(|| Error::Parse("enum object must have exactly one key".into()))?;
visitor.visit_enum(EnumDe { variant, payload })
}
Value::Array(_) => Err(Error::Parse("expected scalar or object for enum".into())),
}
}
fn deserialize_identifier<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
self.deserialize_str(visitor)
}
fn deserialize_ignored_any<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
self.deserialize_any(visitor)
}
}
struct SeqDe {
iter: std::vec::IntoIter<Value>,
}
impl SeqDe {
fn new(items: Vec<Value>) -> Self {
SeqDe {
iter: items.into_iter(),
}
}
}
impl<'de> SeqAccess<'de> for SeqDe {
type Error = Error;
fn next_element_seed<T: DeserializeSeed<'de>>(&mut self, seed: T) -> Result<Option<T::Value>> {
match self.iter.next() {
None => Ok(None),
Some(v) => seed.deserialize(ValueDeserializer(v)).map(Some),
}
}
}
struct MapDe {
iter: indexmap::map::IntoIter<String, Value>,
current_value: Option<Value>,
}
impl MapDe {
fn new(map: IndexMap<String, Value>) -> Self {
MapDe {
iter: map.into_iter(),
current_value: None,
}
}
}
impl<'de> MapAccess<'de> for MapDe {
type Error = Error;
fn next_key_seed<K: DeserializeSeed<'de>>(&mut self, seed: K) -> Result<Option<K::Value>> {
match self.iter.next() {
None => Ok(None),
Some((k, v)) => {
self.current_value = Some(v);
seed.deserialize(ValueDeserializer(Value::Scalar(k)))
.map(Some)
}
}
}
fn next_value_seed<V2: DeserializeSeed<'de>>(&mut self, seed: V2) -> Result<V2::Value> {
match self.current_value.take() {
None => Err(Error::Parse("value missing".into())),
Some(v) => seed.deserialize(ValueDeserializer(v)),
}
}
}
struct EnumDe {
variant: String,
payload: Value,
}
impl<'de> EnumAccess<'de> for EnumDe {
type Error = Error;
type Variant = VariantDe;
fn variant_seed<V: DeserializeSeed<'de>>(self, seed: V) -> Result<(V::Value, Self::Variant)> {
let variant_val = seed.deserialize(ValueDeserializer(Value::Scalar(self.variant)))?;
Ok((variant_val, VariantDe(self.payload)))
}
}
struct VariantDe(Value);
impl<'de> VariantAccess<'de> for VariantDe {
type Error = Error;
fn unit_variant(self) -> Result<()> {
Ok(())
}
fn newtype_variant_seed<T: DeserializeSeed<'de>>(self, seed: T) -> Result<T::Value> {
seed.deserialize(ValueDeserializer(self.0))
}
fn tuple_variant<V: Visitor<'de>>(self, _len: usize, visitor: V) -> Result<V::Value> {
de::Deserializer::deserialize_seq(ValueDeserializer(self.0), visitor)
}
fn struct_variant<V: Visitor<'de>>(
self,
_fields: &'static [&'static str],
visitor: V,
) -> Result<V::Value> {
de::Deserializer::deserialize_map(ValueDeserializer(self.0), visitor)
}
}
fn parse_int(v: &Value) -> Result<i64> {
if let Value::Scalar(s) = v {
s.parse::<i64>()
.map_err(|_| Error::Parse(format!("expected integer, got '{s}'")))
} else {
Err(Error::Parse("expected scalar for integer".into()))
}
}
fn parse_uint(v: &Value) -> Result<u64> {
if let Value::Scalar(s) = v {
s.parse::<u64>()
.map_err(|_| Error::Parse(format!("expected unsigned integer, got '{s}'")))
} else {
Err(Error::Parse("expected scalar for unsigned integer".into()))
}
}
fn parse_float(v: &Value) -> Result<f64> {
if let Value::Scalar(s) = v {
s.parse::<f64>()
.map_err(|_| Error::Parse(format!("expected float, got '{s}'")))
} else {
Err(Error::Parse("expected scalar for float".into()))
}
}