use super::*;
use serde::Deserializer;
impl<'de> serde::de::IntoDeserializer<'de> for &grammar::Expr
{
type Deserializer = Self;
fn into_deserializer(self) -> Self { self }
}
impl<'de> serde::Deserializer<'de> for &grammar::Expr
{
type Error = serde::de::value::Error;
fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where V: serde::de::Visitor<'de>
{
match self
{
grammar::Expr::Null => visitor.visit_none(),
grammar::Expr::Bool(b) => visitor.visit_bool(*b),
grammar::Expr::Int(i) => visitor.visit_i64(*i),
grammar::Expr::Float(f) => visitor.visit_f64(*f),
grammar::Expr::Str(s) => visitor.visit_string(s.clone()),
grammar::Expr::List(list) =>
serde::de::value::SeqDeserializer::new(list.iter())
.deserialize_any(visitor),
grammar::Expr::Map(map) =>
serde::de::value::MapDeserializer::new(
map.into_iter().map(|(k, v)| (k.as_str(), v))
)
.deserialize_any(visitor),
grammar::Expr::Enum(e) =>
serde::de::value::EnumAccessDeserializer::new(e)
.deserialize_any(visitor),
grammar::Expr::Path(p) =>
visitor.visit_bytes(p.as_os_str().as_encoded_bytes())
}
}
fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where V: serde::de::Visitor<'de>
{
if matches!(self, grammar::Expr::Null)
{
visitor.visit_none()
}
else
{
visitor.visit_some(self)
}
}
serde::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 newtype_struct seq tuple
tuple_struct map struct enum identifier ignored_any
}
}
impl<'de> serde::Deserializer<'de> for &grammar::BlockInfo
{
type Error = serde::de::value::Error;
fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where V: serde::de::Visitor<'de>
{
serde::de::value::MapDeserializer::new(
self.properties.iter().map(|(k, v)| (k.as_str(), v))
)
.deserialize_any(visitor)
}
serde::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> serde::de::EnumAccess<'de> for &grammar::Enum
{
type Error = serde::de::value::Error;
type Variant = Self;
fn variant_seed<V>(self, seed: V)
-> Result<(V::Value, Self::Variant), Self::Error>
where V: serde::de::DeserializeSeed<'de>
{
let name = seed.deserialize(
serde::de::value::StrDeserializer::new(&self.name)
)?;
Ok((name, self))
}
}
impl<'de> serde::de::VariantAccess<'de> for &grammar::Enum
{
type Error = serde::de::value::Error;
fn unit_variant(self) -> Result<(), Self::Error>
{
match &self.value
{
None => Ok(()),
Some(_) => Err(serde::de::Error::invalid_type(
serde::de::Unexpected::NewtypeVariant, &"unit variant"
))
}
}
fn newtype_variant_seed<T>(self, seed: T) -> Result<T::Value, Self::Error>
where T: serde::de::DeserializeSeed<'de>
{
match &self.value
{
None => Err(serde::de::Error::invalid_type(
serde::de::Unexpected::UnitVariant, &"newtype variant"
)),
Some(data) => seed.deserialize(data.as_ref())
}
}
fn tuple_variant<V>(self, _len: usize, visitor: V)
-> Result<V::Value, Self::Error>
where V: serde::de::Visitor<'de>
{
match &self.value
{
None => Err(serde::de::Error::invalid_type(
serde::de::Unexpected::UnitVariant, &"tuple variant"
)),
Some(data) => data.deserialize_any(visitor)
}
}
fn struct_variant<V>(self, _fields: &'static [&'static str], visitor: V)
-> Result<V::Value, Self::Error>
where V: serde::de::Visitor<'de>
{
match &self.value
{
None => Err(serde::de::Error::invalid_type(
serde::de::Unexpected::UnitVariant, &"struct variant"
)),
Some(data) => data.deserialize_any(visitor)
}
}
}
#[cfg(test)]
fn assert_deserializes_to<T>(s: &str, exp: T)
where T: for<'de> serde::Deserialize<'de> + std::fmt::Debug + PartialEq
{
let expr = grammar::expr(s, "/".as_ref()).unwrap();
use serde::Deserialize;
assert_eq!(T::deserialize(&expr).unwrap(), exp);
}
#[test]
fn test_deser_structure()
{
#[derive(serde::Deserialize, Debug, PartialEq)]
struct ToDeser
{
b: bool,
i: i32,
f: f32,
s: String
}
assert_deserializes_to(
r#"{ b = true, i = 1, f = 2.0, s = "Hello" }"#,
ToDeser { b: true, i: 1, f: 2.0, s: "Hello".to_owned() }
);
}
#[test]
fn test_deser_block_to_structure()
{
#[derive(serde::Deserialize, Debug, PartialEq)]
struct ToDeser
{
b: bool,
i: i32,
f: f32,
s: String
}
let block = grammar::block(
r#": block { b = true, i = 1, f = 2.0, s = "Hello" }"#,
"/".as_ref()
)
.unwrap();
use serde::Deserialize;
assert_eq!(
ToDeser::deserialize(block.as_ref()).unwrap(),
ToDeser { b: true, i: 1, f: 2.0, s: "Hello".to_owned() }
);
}
#[test]
fn test_deser_enum()
{
#[derive(serde::Deserialize, Debug, PartialEq)]
enum ToDeser
{
Unit,
NewType(bool),
Tuple(i32, i32),
Struct { s: String }
}
assert_deserializes_to(r#"!Unit"#, ToDeser::Unit);
assert_deserializes_to(r#"!NewType true"#, ToDeser::NewType(true));
assert_deserializes_to(r#"!Tuple [1, 2]"#, ToDeser::Tuple(1, 2));
assert_deserializes_to(
r#"!Struct { s = "Hello" }"#,
ToDeser::Struct { s: "Hello".to_owned() }
);
}
#[test]
fn test_deser_list()
{
assert_deserializes_to(r#"[1, 2, 3]"#, vec![1, 2, 3]);
}
#[test]
fn test_deser_map()
{
let map: HashMap<String, String> =
[("k1", "v1"), ("k2", "v2")].into_iter()
.map(|(k, v)| (k.to_owned(), v.to_owned()))
.collect();
assert_deserializes_to(r#"{ k1 = "v1", k2 = "v2" }"#, map);
}
#[test]
fn test_deser_path()
{
use std::path::PathBuf;
use serde::Deserialize;
assert_eq!(
PathBuf::deserialize(
&grammar::expr("./test.txt", "/".as_ref()).unwrap()
)
.unwrap(),
PathBuf::from("/test.txt")
);
assert_eq!(
PathBuf::deserialize(
&grammar::expr("./test.txt", "/root".as_ref()).unwrap()
)
.unwrap(),
PathBuf::from("/root/test.txt")
);
}
#[test]
fn test_deser_option()
{
#[derive(serde::Deserialize, Debug, PartialEq)]
struct Test { opt: Option<String> }
assert_deserializes_to(
r#"{ opt = "MEOW" }"#,
Test { opt: Some(String::from("MEOW")) }
);
}