use crate::error::{Error, ErrorKind};
use crate::parser::{loads, Top};
use crate::value::Value;
use serde::de::{self, DeserializeSeed, IntoDeserializer, MapAccess, SeqAccess, Visitor};
use serde::Deserialize;
pub fn from_str<'de, T: Deserialize<'de>>(s: &'de str) -> Result<T, Error> {
let value = loads(s, Top::Any)?.unwrap_or(Value::String(String::new()));
T::deserialize(ValueDeserializer { value: &value })
}
struct ValueDeserializer<'a> {
value: &'a Value,
}
impl<'de, 'a> de::Deserializer<'de> for ValueDeserializer<'a> {
type Error = Error;
fn deserialize_any<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Error> {
match self.value {
Value::String(s) => visitor.visit_str(s),
Value::List(_) => self.deserialize_seq(visitor),
Value::Dict(_) => self.deserialize_map(visitor),
}
}
fn deserialize_bool<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Error> {
match self.value {
Value::String(s) => match s.as_str() {
"true" | "True" | "TRUE" | "yes" | "Yes" | "YES" => visitor.visit_bool(true),
"false" | "False" | "FALSE" | "no" | "No" | "NO" => visitor.visit_bool(false),
_ => Err(Error::new(
ErrorKind::UnsupportedType,
format!("cannot parse '{}' as boolean", s),
)),
},
_ => Err(Error::new(
ErrorKind::UnsupportedType,
"expected string for boolean",
)),
}
}
fn deserialize_i8<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Error> {
let s = self.expect_string()?;
let n: i8 = s.parse().map_err(|_| {
Error::new(ErrorKind::UnsupportedType, format!("cannot parse '{}' as i8", s))
})?;
visitor.visit_i8(n)
}
fn deserialize_i16<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Error> {
let s = self.expect_string()?;
let n: i16 = s.parse().map_err(|_| {
Error::new(ErrorKind::UnsupportedType, format!("cannot parse '{}' as i16", s))
})?;
visitor.visit_i16(n)
}
fn deserialize_i32<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Error> {
let s = self.expect_string()?;
let n: i32 = s.parse().map_err(|_| {
Error::new(ErrorKind::UnsupportedType, format!("cannot parse '{}' as i32", s))
})?;
visitor.visit_i32(n)
}
fn deserialize_i64<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Error> {
let s = self.expect_string()?;
let n: i64 = s.parse().map_err(|_| {
Error::new(ErrorKind::UnsupportedType, format!("cannot parse '{}' as i64", s))
})?;
visitor.visit_i64(n)
}
fn deserialize_u8<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Error> {
let s = self.expect_string()?;
let n: u8 = s.parse().map_err(|_| {
Error::new(ErrorKind::UnsupportedType, format!("cannot parse '{}' as u8", s))
})?;
visitor.visit_u8(n)
}
fn deserialize_u16<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Error> {
let s = self.expect_string()?;
let n: u16 = s.parse().map_err(|_| {
Error::new(ErrorKind::UnsupportedType, format!("cannot parse '{}' as u16", s))
})?;
visitor.visit_u16(n)
}
fn deserialize_u32<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Error> {
let s = self.expect_string()?;
let n: u32 = s.parse().map_err(|_| {
Error::new(ErrorKind::UnsupportedType, format!("cannot parse '{}' as u32", s))
})?;
visitor.visit_u32(n)
}
fn deserialize_u64<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Error> {
let s = self.expect_string()?;
let n: u64 = s.parse().map_err(|_| {
Error::new(ErrorKind::UnsupportedType, format!("cannot parse '{}' as u64", s))
})?;
visitor.visit_u64(n)
}
fn deserialize_f32<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Error> {
let s = self.expect_string()?;
let n: f32 = s.parse().map_err(|_| {
Error::new(ErrorKind::UnsupportedType, format!("cannot parse '{}' as f32", s))
})?;
visitor.visit_f32(n)
}
fn deserialize_f64<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Error> {
let s = self.expect_string()?;
let n: f64 = s.parse().map_err(|_| {
Error::new(ErrorKind::UnsupportedType, format!("cannot parse '{}' as f64", s))
})?;
visitor.visit_f64(n)
}
fn deserialize_char<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Error> {
let s = self.expect_string()?;
let mut chars = s.chars();
let c = chars.next().ok_or_else(|| {
Error::new(ErrorKind::UnsupportedType, "empty string for char")
})?;
if chars.next().is_some() {
return Err(Error::new(
ErrorKind::UnsupportedType,
"expected single character",
));
}
visitor.visit_char(c)
}
fn deserialize_str<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Error> {
let s = self.expect_string()?;
visitor.visit_str(s)
}
fn deserialize_string<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Error> {
let s = self.expect_string()?;
visitor.visit_string(s.to_string())
}
fn deserialize_bytes<V: Visitor<'de>>(self, _visitor: V) -> Result<V::Value, Error> {
Err(Error::new(
ErrorKind::UnsupportedType,
"NestedText does not support byte arrays",
))
}
fn deserialize_byte_buf<V: Visitor<'de>>(self, _visitor: V) -> Result<V::Value, Error> {
Err(Error::new(
ErrorKind::UnsupportedType,
"NestedText does not support byte arrays",
))
}
fn deserialize_option<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Error> {
match self.value {
Value::String(s) if s.is_empty() => visitor.visit_none(),
_ => visitor.visit_some(self),
}
}
fn deserialize_unit<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Error> {
match self.value {
Value::String(s) if s.is_empty() => visitor.visit_unit(),
_ => Err(Error::new(
ErrorKind::UnsupportedType,
"expected empty string for unit",
)),
}
}
fn deserialize_unit_struct<V: Visitor<'de>>(
self,
_name: &'static str,
visitor: V,
) -> Result<V::Value, Error> {
self.deserialize_unit(visitor)
}
fn deserialize_newtype_struct<V: Visitor<'de>>(
self,
_name: &'static str,
visitor: V,
) -> Result<V::Value, Error> {
visitor.visit_newtype_struct(self)
}
fn deserialize_seq<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Error> {
match self.value {
Value::List(items) => visitor.visit_seq(SeqDeserializer {
iter: items.iter(),
}),
_ => Err(Error::new(
ErrorKind::UnsupportedType,
"expected list for sequence",
)),
}
}
fn deserialize_tuple<V: Visitor<'de>>(self, _len: usize, visitor: V) -> Result<V::Value, Error> {
self.deserialize_seq(visitor)
}
fn deserialize_tuple_struct<V: Visitor<'de>>(
self,
_name: &'static str,
_len: usize,
visitor: V,
) -> Result<V::Value, Error> {
self.deserialize_seq(visitor)
}
fn deserialize_map<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Error> {
match self.value {
Value::Dict(pairs) => visitor.visit_map(MapDeserializer {
iter: pairs.iter(),
next_value: None,
}),
_ => Err(Error::new(
ErrorKind::UnsupportedType,
"expected dictionary for map",
)),
}
}
fn deserialize_struct<V: Visitor<'de>>(
self,
_name: &'static str,
_fields: &'static [&'static str],
visitor: V,
) -> Result<V::Value, Error> {
self.deserialize_map(visitor)
}
fn deserialize_enum<V: Visitor<'de>>(
self,
_name: &'static str,
_variants: &'static [&'static str],
visitor: V,
) -> Result<V::Value, Error> {
match self.value {
Value::String(s) => visitor.visit_enum(s.as_str().into_deserializer()),
Value::Dict(pairs) => {
if pairs.len() != 1 {
return Err(Error::new(
ErrorKind::UnsupportedType,
"enum must be a string or single-key dictionary",
));
}
let (variant, value) = &pairs[0];
visitor.visit_enum(EnumDeserializer {
variant,
value,
})
}
_ => Err(Error::new(
ErrorKind::UnsupportedType,
"expected string or dictionary for enum",
)),
}
}
fn deserialize_identifier<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Error> {
self.deserialize_str(visitor)
}
fn deserialize_ignored_any<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Error> {
self.deserialize_any(visitor)
}
}
impl<'a> ValueDeserializer<'a> {
fn expect_string(&self) -> Result<&'a str, Error> {
match self.value {
Value::String(s) => Ok(s.as_str()),
_ => Err(Error::new(
ErrorKind::UnsupportedType,
"expected string value",
)),
}
}
}
struct SeqDeserializer<'a> {
iter: std::slice::Iter<'a, Value>,
}
impl<'de, 'a> SeqAccess<'de> for SeqDeserializer<'a> {
type Error = Error;
fn next_element_seed<T: DeserializeSeed<'de>>(
&mut self,
seed: T,
) -> Result<Option<T::Value>, Error> {
match self.iter.next() {
Some(value) => seed
.deserialize(ValueDeserializer { value })
.map(Some),
None => Ok(None),
}
}
}
struct MapDeserializer<'a> {
iter: std::slice::Iter<'a, (String, Value)>,
next_value: Option<&'a Value>,
}
impl<'de, 'a> MapAccess<'de> for MapDeserializer<'a> {
type Error = Error;
fn next_key_seed<K: DeserializeSeed<'de>>(
&mut self,
seed: K,
) -> Result<Option<K::Value>, Error> {
match self.iter.next() {
Some((key, value)) => {
self.next_value = Some(value);
let key_value = Value::String(key.clone());
seed.deserialize(ValueDeserializer { value: &key_value })
.map(Some)
}
None => Ok(None),
}
}
fn next_value_seed<V: DeserializeSeed<'de>>(
&mut self,
seed: V,
) -> Result<V::Value, Error> {
let value = self.next_value.take().expect("next_value called before next_key");
seed.deserialize(ValueDeserializer { value })
}
}
struct EnumDeserializer<'a> {
variant: &'a str,
value: &'a Value,
}
impl<'de, 'a> de::EnumAccess<'de> for EnumDeserializer<'a> {
type Error = Error;
type Variant = VariantDeserializer<'a>;
fn variant_seed<V: DeserializeSeed<'de>>(
self,
seed: V,
) -> Result<(V::Value, Self::Variant), Error> {
let variant_value = Value::String(self.variant.to_string());
let v = seed.deserialize(ValueDeserializer {
value: &variant_value,
})?;
Ok((v, VariantDeserializer { value: self.value }))
}
}
struct VariantDeserializer<'a> {
value: &'a Value,
}
impl<'de, 'a> de::VariantAccess<'de> for VariantDeserializer<'a> {
type Error = Error;
fn unit_variant(self) -> Result<(), Error> {
Ok(())
}
fn newtype_variant_seed<T: DeserializeSeed<'de>>(
self,
seed: T,
) -> Result<T::Value, Error> {
seed.deserialize(ValueDeserializer { value: self.value })
}
fn tuple_variant<V: Visitor<'de>>(self, _len: usize, visitor: V) -> Result<V::Value, Error> {
match self.value {
Value::List(items) => visitor.visit_seq(SeqDeserializer {
iter: items.iter(),
}),
_ => Err(Error::new(
ErrorKind::UnsupportedType,
"expected list for tuple variant",
)),
}
}
fn struct_variant<V: Visitor<'de>>(
self,
_fields: &'static [&'static str],
visitor: V,
) -> Result<V::Value, Error> {
match self.value {
Value::Dict(pairs) => visitor.visit_map(MapDeserializer {
iter: pairs.iter(),
next_value: None,
}),
_ => Err(Error::new(
ErrorKind::UnsupportedType,
"expected dictionary for struct variant",
)),
}
}
}
impl de::Error for Error {
fn custom<T: std::fmt::Display>(msg: T) -> Self {
Error::new(ErrorKind::UnsupportedType, msg.to_string())
}
}
#[cfg(test)]
mod tests {
use super::*;
use serde::Deserialize;
#[test]
fn test_deserialize_struct() {
#[derive(Deserialize, Debug, PartialEq)]
struct Config {
name: String,
age: u32,
}
let input = "name: Alice\nage: 30";
let config: Config = from_str(input).unwrap();
assert_eq!(
config,
Config {
name: "Alice".to_string(),
age: 30,
}
);
}
#[test]
fn test_deserialize_vec() {
let input = "- hello\n- world";
let v: Vec<String> = from_str(input).unwrap();
assert_eq!(v, vec!["hello", "world"]);
}
#[test]
fn test_deserialize_nested() {
#[derive(Deserialize, Debug, PartialEq)]
struct Outer {
items: Vec<String>,
}
let input = "items:\n - a\n - b";
let v: Outer = from_str(input).unwrap();
assert_eq!(
v,
Outer {
items: vec!["a".to_string(), "b".to_string()],
}
);
}
#[test]
fn test_deserialize_bool() {
#[derive(Deserialize, Debug, PartialEq)]
struct Flags {
debug: bool,
verbose: bool,
}
let input = "debug: true\nverbose: false";
let v: Flags = from_str(input).unwrap();
assert_eq!(
v,
Flags {
debug: true,
verbose: false,
}
);
}
#[test]
fn test_deserialize_option() {
#[derive(Deserialize, Debug, PartialEq)]
struct MaybeValue {
present: Option<String>,
absent: Option<String>,
}
let input = "present: hello\nabsent:";
let v: MaybeValue = from_str(input).unwrap();
assert_eq!(
v,
MaybeValue {
present: Some("hello".to_string()),
absent: None,
}
);
}
#[test]
fn test_deserialize_enum() {
#[derive(Deserialize, Debug, PartialEq)]
enum Color {
Red,
Green,
Blue,
}
let input = "> Red";
let v: Color = from_str(input).unwrap();
assert_eq!(v, Color::Red);
}
#[test]
fn test_deserialize_hashmap() {
use std::collections::HashMap;
let input = "a: 1\nb: 2";
let v: HashMap<String, String> = from_str(input).unwrap();
assert_eq!(v.get("a").unwrap(), "1");
assert_eq!(v.get("b").unwrap(), "2");
}
}