Skip to content

Commit 1ff4288

Browse files
committed
improve idiomacity of serialization and deserialization for structs
1 parent 143afa6 commit 1ff4288

File tree

1 file changed

+77
-6
lines changed

1 file changed

+77
-6
lines changed

src/serde.rs

Lines changed: 77 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,10 @@
1-
use serde::{ser::Serialize, Deserialize};
1+
use std::{fmt, marker::PhantomData};
2+
3+
use serde::{
4+
de::{self, MapAccess, Visitor},
5+
ser::{Serialize, SerializeStruct},
6+
Deserialize, Deserializer,
7+
};
28

39
use crate::{NodeId, NodeRef, Tree};
410

@@ -21,7 +27,10 @@ impl<'a, T: Serialize> Serialize for SerNode<'a, T> {
2127
where
2228
S: serde::Serializer,
2329
{
24-
(&self.value, &self.children).serialize(serializer)
30+
let mut state = serializer.serialize_struct("SerNode", 2)?;
31+
state.serialize_field("value", &self.value)?;
32+
state.serialize_field("children", &self.children)?;
33+
state.end()
2534
}
2635
}
2736

@@ -66,16 +75,78 @@ impl<T> From<DeserNode<T>> for Tree<T> {
6675
}
6776
}
6877

69-
impl<'de, T: Deserialize<'de>> Deserialize<'de> for DeserNode<T> {
70-
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
78+
struct DeserNodeVisitor<T> {
79+
marker: PhantomData<fn() -> DeserNode<T>>,
80+
}
81+
82+
impl<T> DeserNodeVisitor<T> {
83+
fn new() -> Self {
84+
DeserNodeVisitor {
85+
marker: PhantomData,
86+
}
87+
}
88+
}
89+
90+
impl<'de, T> Visitor<'de> for DeserNodeVisitor<T>
91+
where
92+
T: Deserialize<'de>,
93+
{
94+
type Value = DeserNode<T>;
95+
96+
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
97+
formatter.write_str("struct DeserNode")
98+
}
99+
100+
fn visit_map<M>(self, mut map: M) -> Result<Self::Value, M::Error>
71101
where
72-
D: serde::Deserializer<'de>,
102+
M: MapAccess<'de>,
73103
{
74-
let (value, children) = <(T, Vec<DeserNode<T>>)>::deserialize(deserializer)?;
104+
let mut value = None;
105+
let mut children = None;
106+
107+
while let Some(key) = map.next_key()? {
108+
match key {
109+
"value" => {
110+
if value.is_some() {
111+
return Err(de::Error::duplicate_field("value"));
112+
}
113+
value = Some(map.next_value()?);
114+
}
115+
"children" => {
116+
if children.is_some() {
117+
return Err(de::Error::duplicate_field("children"));
118+
}
119+
children = Some(map.next_value()?);
120+
}
121+
_ => {
122+
return Err(de::Error::unknown_field(key, &["value", "children"]));
123+
}
124+
}
125+
}
126+
127+
let value = value.ok_or_else(|| de::Error::missing_field("value"))?;
128+
let children = children.ok_or_else(|| de::Error::missing_field("children"))?;
129+
75130
Ok(DeserNode { value, children })
76131
}
77132
}
78133

134+
impl<'de, T> Deserialize<'de> for DeserNode<T>
135+
where
136+
T: Deserialize<'de>,
137+
{
138+
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
139+
where
140+
D: Deserializer<'de>,
141+
{
142+
deserializer.deserialize_struct(
143+
"DeserNode",
144+
&["value", "children"],
145+
DeserNodeVisitor::new(),
146+
)
147+
}
148+
}
149+
79150
impl<'de, T: Deserialize<'de>> Deserialize<'de> for Tree<T> {
80151
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
81152
where

0 commit comments

Comments
 (0)