Skip to content

Commit ae93007

Browse files
authored
FIx: BoltMap enum deserialization (#242)
* add FromIterator for BoltType * fix: BoltMap enum deserialization * fix clippy warnings
1 parent 4962195 commit ae93007

File tree

3 files changed

+318
-2
lines changed

3 files changed

+318
-2
lines changed

lib/src/types/serde/map.rs

Lines changed: 309 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,309 @@
1+
use serde::{
2+
de::{
3+
value::{MapDeserializer, SeqDeserializer},
4+
DeserializeSeed, EnumAccess, Error as _, IntoDeserializer, Unexpected, VariantAccess,
5+
Visitor,
6+
},
7+
forward_to_deserialize_any, Deserialize, Deserializer,
8+
};
9+
10+
use crate::{BoltMap, BoltString, BoltType};
11+
12+
use super::DeError;
13+
14+
pub struct BoltMapDeserializer<'de> {
15+
map: &'de BoltMap,
16+
}
17+
18+
impl<'de> BoltMapDeserializer<'de> {
19+
pub fn new(map: &'de BoltMap) -> Self {
20+
BoltMapDeserializer { map }
21+
}
22+
}
23+
24+
impl<'de> serde::Deserializer<'de> for BoltMapDeserializer<'de> {
25+
type Error = DeError;
26+
27+
fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
28+
where
29+
V: Visitor<'de>,
30+
{
31+
let mut deserializer = MapDeserializer::new(self.map.value.iter());
32+
let map = visitor.visit_map(&mut deserializer)?;
33+
deserializer.end()?;
34+
Ok(map)
35+
}
36+
37+
fn deserialize_enum<V>(
38+
self,
39+
_name: &'static str,
40+
_variants: &'static [&'static str],
41+
visitor: V,
42+
) -> Result<V::Value, Self::Error>
43+
where
44+
V: Visitor<'de>,
45+
{
46+
let mut iter = self.map.value.iter();
47+
let (variant, value) = match iter.next() {
48+
Some(v) => v,
49+
None => {
50+
return Err(DeError::invalid_value(
51+
Unexpected::Map,
52+
&"map with a single key",
53+
));
54+
}
55+
};
56+
if iter.next().is_some() {
57+
return Err(serde::de::Error::invalid_value(
58+
Unexpected::Map,
59+
&"map with a single key",
60+
));
61+
}
62+
63+
visitor.visit_enum(EnumDeserializer { variant, value })
64+
}
65+
66+
fn deserialize_ignored_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
67+
where
68+
V: Visitor<'de>,
69+
{
70+
visitor.visit_unit()
71+
}
72+
73+
forward_to_deserialize_any! {
74+
bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string
75+
bytes byte_buf option unit unit_struct newtype_struct seq tuple
76+
tuple_struct map struct identifier
77+
}
78+
}
79+
80+
struct EnumDeserializer<'de> {
81+
variant: &'de BoltString,
82+
value: &'de BoltType,
83+
}
84+
85+
impl<'de> EnumAccess<'de> for EnumDeserializer<'de> {
86+
type Error = DeError;
87+
type Variant = VariantDeserializer<'de>;
88+
89+
fn variant_seed<V>(self, seed: V) -> Result<(V::Value, VariantDeserializer<'de>), DeError>
90+
where
91+
V: DeserializeSeed<'de>,
92+
{
93+
let variant = self.variant.into_deserializer();
94+
let visitor = VariantDeserializer { value: self.value };
95+
seed.deserialize(variant).map(|v| (v, visitor))
96+
}
97+
}
98+
99+
struct VariantDeserializer<'de> {
100+
value: &'de BoltType,
101+
}
102+
103+
impl<'de> VariantAccess<'de> for VariantDeserializer<'de> {
104+
type Error = DeError;
105+
106+
fn unit_variant(self) -> Result<(), Self::Error> {
107+
match self.value {
108+
BoltType::Null(_) => Ok(()),
109+
_ => Deserialize::deserialize(self.value.into_deserializer()),
110+
}
111+
}
112+
113+
fn newtype_variant_seed<T>(self, seed: T) -> Result<T::Value, Self::Error>
114+
where
115+
T: DeserializeSeed<'de>,
116+
{
117+
match self.value {
118+
BoltType::Null(_) => Err(DeError::invalid_type(
119+
Unexpected::UnitVariant,
120+
&"newtype variant",
121+
)),
122+
_ => seed.deserialize(self.value.into_deserializer()),
123+
}
124+
}
125+
126+
fn tuple_variant<V>(self, _len: usize, visitor: V) -> Result<V::Value, Self::Error>
127+
where
128+
V: Visitor<'de>,
129+
{
130+
match self.value {
131+
BoltType::List(v) => {
132+
if v.is_empty() {
133+
visitor.visit_unit()
134+
} else {
135+
let mut deserializer = SeqDeserializer::new(v.value.iter());
136+
let seq = visitor.visit_seq(&mut deserializer)?;
137+
deserializer.end()?;
138+
Ok(seq)
139+
}
140+
}
141+
_ => Err(serde::de::Error::invalid_type(
142+
Unexpected::UnitVariant,
143+
&"tuple variant",
144+
)),
145+
}
146+
}
147+
148+
fn struct_variant<V>(
149+
self,
150+
_fields: &'static [&'static str],
151+
visitor: V,
152+
) -> Result<V::Value, Self::Error>
153+
where
154+
V: Visitor<'de>,
155+
{
156+
match self.value {
157+
BoltType::Map(v) => MapDeserializer::new(v.value.iter()).deserialize_any(visitor),
158+
_ => Err(DeError::invalid_type(
159+
Unexpected::UnitVariant,
160+
&"struct variant",
161+
)),
162+
}
163+
}
164+
}
165+
166+
#[cfg(test)]
167+
mod tests {
168+
use serde::Deserialize;
169+
170+
use crate::{BoltMap, BoltNull, BoltString, BoltType};
171+
172+
#[test]
173+
fn deserialize_externally_tagged_enum() {
174+
#[derive(Deserialize, Debug, PartialEq)]
175+
pub enum TestEnum {
176+
Variant1 { value: String },
177+
Variant2 { value: String },
178+
}
179+
180+
let content = [(BoltString::from("value"), BoltType::from("test"))]
181+
.into_iter()
182+
.collect::<BoltMap>();
183+
let value = [(BoltString::from("Variant1"), BoltType::Map(content))]
184+
.into_iter()
185+
.collect::<BoltMap>();
186+
let actual = value.to::<TestEnum>().unwrap();
187+
assert_eq!(
188+
actual,
189+
TestEnum::Variant1 {
190+
value: "test".to_string()
191+
}
192+
);
193+
}
194+
195+
#[test]
196+
fn deserialize_adjacently_tagged_enum() {
197+
#[derive(Deserialize, Debug, PartialEq)]
198+
#[serde(tag = "type", content = "content")]
199+
pub enum TestEnum {
200+
Variant1 { value: String },
201+
Variant2 { value: String },
202+
}
203+
let content = [(BoltString::from("value"), BoltType::from("test"))]
204+
.into_iter()
205+
.collect::<BoltMap>();
206+
let value = [
207+
(BoltString::from("type"), BoltType::from("Variant1")),
208+
(BoltString::from("content"), BoltType::Map(content)),
209+
]
210+
.into_iter()
211+
.collect::<BoltMap>();
212+
let actual = value.to::<TestEnum>().unwrap();
213+
assert_eq!(
214+
actual,
215+
TestEnum::Variant1 {
216+
value: "test".to_string()
217+
}
218+
);
219+
}
220+
221+
#[test]
222+
fn deserialize_untagged_enum() {
223+
#[derive(Deserialize, Debug, PartialEq)]
224+
#[serde(untagged)]
225+
pub enum TestEnum {
226+
Variant1 { val1: String },
227+
Variant2 { val2: String },
228+
}
229+
let value = [(BoltString::from("val1"), BoltType::from("test"))]
230+
.into_iter()
231+
.collect::<BoltMap>();
232+
let actual = value.to::<TestEnum>().unwrap();
233+
assert_eq!(
234+
actual,
235+
TestEnum::Variant1 {
236+
val1: "test".to_string()
237+
}
238+
);
239+
}
240+
241+
#[test]
242+
fn deserialize_internally_tagged_enum() {
243+
#[derive(Deserialize, Debug, PartialEq)]
244+
#[serde(tag = "type")]
245+
pub enum TestEnum {
246+
Variant1 { value: String },
247+
Variant2 { value: String },
248+
}
249+
let value = [
250+
(BoltString::from("type"), BoltType::from("Variant1")),
251+
(BoltString::from("value"), BoltType::from("test")),
252+
]
253+
.into_iter()
254+
.collect::<BoltMap>();
255+
let actual = value.to::<TestEnum>().unwrap();
256+
assert_eq!(
257+
actual,
258+
TestEnum::Variant1 {
259+
value: "test".to_string()
260+
}
261+
);
262+
}
263+
264+
#[test]
265+
fn deserialize_newtype_enum() {
266+
#[derive(Deserialize, Debug, PartialEq)]
267+
pub enum TestEnum {
268+
Variant1(String),
269+
Variant2(String),
270+
}
271+
272+
let value = [(BoltString::from("Variant1"), "test".into())]
273+
.into_iter()
274+
.collect::<BoltMap>();
275+
let actual = value.to::<TestEnum>().unwrap();
276+
assert_eq!(actual, TestEnum::Variant1("test".to_string()));
277+
}
278+
279+
#[test]
280+
fn deserialize_tuple_enum() {
281+
#[derive(Deserialize, Debug, PartialEq)]
282+
pub enum TestEnum {
283+
Variant1(String, u64),
284+
Variant2(String),
285+
}
286+
287+
let content: Vec<BoltType> = vec!["test".into(), 10.into()];
288+
let value = [(BoltString::from("Variant1"), content.into())]
289+
.into_iter()
290+
.collect::<BoltMap>();
291+
let actual = value.to::<TestEnum>().unwrap();
292+
assert_eq!(actual, TestEnum::Variant1("test".to_string(), 10));
293+
}
294+
295+
#[test]
296+
fn deserialize_unit_enum() {
297+
#[derive(Deserialize, Debug, PartialEq)]
298+
pub enum TestEnum {
299+
Variant1,
300+
Variant2,
301+
}
302+
303+
let value = [(BoltString::from("Variant1"), BoltType::Null(BoltNull))]
304+
.into_iter()
305+
.collect::<BoltMap>();
306+
let actual = value.to::<TestEnum>().unwrap();
307+
assert_eq!(actual, TestEnum::Variant1);
308+
}
309+
}

lib/src/types/serde/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ mod duration;
1414
mod element;
1515
mod error;
1616
mod kind;
17+
mod map;
1718
mod node;
1819
mod path;
1920
mod point;

lib/src/types/serde/typ.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use crate::{
44
date_time::BoltDateTimeVisitor,
55
duration::BoltDurationVisitor,
66
element::ElementDataDeserializer,
7+
map::BoltMapDeserializer,
78
node::BoltNodeVisitor,
89
path::BoltPathVisitor,
910
point::{BoltPointDeserializer, BoltPointVisitor},
@@ -55,7 +56,7 @@ impl BoltMap {
5556
where
5657
T: Deserialize<'this>,
5758
{
58-
T::deserialize(MapDeserializer::new(self.value.iter()))
59+
T::deserialize(BoltMapDeserializer::new(self))
5960
}
6061
}
6162

@@ -694,7 +695,12 @@ impl<'de> Deserializer<'de> for BoltTypeDeserializer<'de> {
694695
where
695696
V: Visitor<'de>,
696697
{
697-
self.unexpected(visitor)
698+
match self.value {
699+
BoltType::String(_) => self.deserialize_str(visitor),
700+
BoltType::Integer(_) => self.deserialize_u64(visitor),
701+
BoltType::Bytes(_) => self.deserialize_bytes(visitor),
702+
_ => self.unexpected(visitor),
703+
}
698704
}
699705

700706
fn is_human_readable(&self) -> bool {

0 commit comments

Comments
 (0)