use std::{collections::HashMap, fmt};
use kdl::KdlNode;
use serde::{
de::{self, MapAccess, SeqAccess, Visitor},
ser::SerializeStruct,
Deserialize, Deserializer, Serialize,
};
use crate::{value, Value};
#[derive(Default, Debug, Clone, PartialEq)]
pub struct Node(pub KdlNode);
impl Serialize for Node {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
let mut node = serializer.serialize_struct("Node", 4)?;
node.serialize_field("name", &self.0.name)?;
let values = value::from_kdl_vec(self.0.values.clone());
node.serialize_field("values", &values)?;
let properties = value::from_kdl_map(self.0.properties.clone());
node.serialize_field("properties", &properties)?;
let children = from_kdl_vec(self.0.children.clone());
node.serialize_field("children", &children)?;
node.end()
}
}
const FIELDS: &[&str] = &["name", "values", "properties", "children"];
enum Field {
Name,
Values,
Properties,
Children,
}
impl<'de> Deserialize<'de> for Field {
fn deserialize<D>(deserializer: D) -> Result<Field, D::Error>
where
D: Deserializer<'de>,
{
struct FieldVisitor;
impl<'de> Visitor<'de> for FieldVisitor {
type Value = Field;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("one of: `name`, `values`, `properties`, `children`")
}
fn visit_str<E>(self, value: &str) -> Result<Field, E>
where
E: de::Error,
{
match value {
"name" => Ok(Field::Name),
"values" => Ok(Field::Values),
"properties" => Ok(Field::Properties),
"children" => Ok(Field::Children),
_ => Err(de::Error::unknown_field(value, FIELDS)),
}
}
}
deserializer.deserialize_identifier(FieldVisitor)
}
}
impl<'de> Deserialize<'de> for Node {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
struct NodeVisitor;
impl<'de> Visitor<'de> for NodeVisitor {
type Value = Node;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("struct Node")
}
fn visit_seq<V>(self, mut seq: V) -> Result<Node, V::Error>
where
V: SeqAccess<'de>,
{
let name = seq
.next_element()?
.ok_or_else(|| de::Error::invalid_length(0, &self))?;
let values = seq
.next_element::<Vec<Value>>()?
.ok_or_else(|| de::Error::invalid_length(1, &self))?;
let properties = seq
.next_element::<HashMap<String, Value>>()?
.ok_or_else(|| de::Error::invalid_length(2, &self))?;
let children = seq
.next_element::<Vec<Node>>()?
.ok_or_else(|| de::Error::invalid_length(3, &self))?;
Ok(Node(KdlNode {
name,
values: value::into_kdl_vec(values),
properties: value::into_kdl_map(properties),
children: into_kdl_vec(children),
}))
}
fn visit_map<V>(self, mut map: V) -> Result<Node, V::Error>
where
V: MapAccess<'de>,
{
let mut name = None;
let mut values = None;
let mut properties = None;
let mut children = None;
while let Some(key) = map.next_key()? {
match key {
Field::Name => {
if name.is_some() {
return Err(de::Error::duplicate_field("name"));
}
name = Some(map.next_value()?);
}
Field::Values => {
if values.is_some() {
return Err(de::Error::duplicate_field("values"));
}
values = Some(map.next_value()?);
}
Field::Properties => {
if properties.is_some() {
return Err(de::Error::duplicate_field("properties"));
}
properties = Some(map.next_value()?);
}
Field::Children => {
if children.is_some() {
return Err(de::Error::duplicate_field("children"));
}
children = Some(map.next_value()?);
}
}
}
let name = name.ok_or_else(|| de::Error::missing_field("name"))?;
let values = values.ok_or_else(|| de::Error::missing_field("values"))?;
let properties =
properties.ok_or_else(|| de::Error::missing_field("properties"))?;
let children = children.ok_or_else(|| de::Error::missing_field("children"))?;
Ok(Node(KdlNode {
name,
values: value::into_kdl_vec(values),
properties: value::into_kdl_map(properties),
children: into_kdl_vec(children),
}))
}
}
deserializer.deserialize_struct("Node", FIELDS, NodeVisitor)
}
}
pub fn from_kdl_vec(v: Vec<KdlNode>) -> Vec<Node> {
v.into_iter().map(Node).collect()
}
pub fn into_kdl_vec(v: Vec<Node>) -> Vec<KdlNode> {
v.into_iter().map(|Node(v)| v).collect()
}