Skip to content

Commit e170a44

Browse files
authored
RUST-1022 Support configuring Serializer and Deserializer to be non-human-readable (#321)
1 parent a272464 commit e170a44

File tree

11 files changed

+676
-67
lines changed

11 files changed

+676
-67
lines changed

serde-tests/options.rs

Lines changed: 216 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,216 @@
1+
use std::collections::HashMap;
2+
3+
use bson::{doc, Bson, DeserializerOptions, SerializerOptions};
4+
5+
use serde::{
6+
ser::{
7+
SerializeMap,
8+
SerializeSeq,
9+
SerializeStruct,
10+
SerializeStructVariant,
11+
SerializeTupleStruct,
12+
SerializeTupleVariant,
13+
},
14+
Deserialize,
15+
Serialize,
16+
};
17+
18+
/// Type whose serialize and deserialize implementations assert that the (de)serializer
19+
/// is not human readable.
20+
#[derive(Deserialize)]
21+
struct Foo {
22+
a: i32,
23+
unit: Unit,
24+
tuple: Tuple,
25+
map: Map,
26+
unit_variant: Bar,
27+
tuple_variant: Bar,
28+
struct_variant: Bar,
29+
seq: Seq,
30+
}
31+
32+
impl Serialize for Foo {
33+
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
34+
where
35+
S: serde::Serializer,
36+
{
37+
assert!(!serializer.is_human_readable());
38+
39+
let mut state = serializer.serialize_struct("Foo", 7)?;
40+
state.serialize_field("a", &self.a)?;
41+
state.serialize_field("unit", &self.unit)?;
42+
state.serialize_field("tuple", &self.tuple)?;
43+
state.serialize_field("map", &self.map)?;
44+
state.serialize_field("unit_variant", &self.unit_variant)?;
45+
state.serialize_field("tuple_variant", &self.tuple_variant)?;
46+
state.serialize_field("struct_variant", &self.struct_variant)?;
47+
state.serialize_field("seq", &self.seq)?;
48+
state.end()
49+
}
50+
}
51+
52+
#[derive(Deserialize)]
53+
enum Bar {
54+
Unit,
55+
Tuple(Unit),
56+
Struct { a: Unit },
57+
}
58+
59+
impl Serialize for Bar {
60+
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
61+
where
62+
S: serde::Serializer,
63+
{
64+
assert!(!serializer.is_human_readable());
65+
match self {
66+
Self::Unit => serializer.serialize_unit_variant("Bar", 0, "Unit"),
67+
Self::Tuple(t) => {
68+
let mut state = serializer.serialize_tuple_variant("Bar", 1, "Tuple", 1)?;
69+
state.serialize_field(t)?;
70+
state.end()
71+
}
72+
Self::Struct { a } => {
73+
let mut state = serializer.serialize_struct_variant("Foo", 2, "Struct", 1)?;
74+
state.serialize_field("a", a)?;
75+
state.end()
76+
}
77+
}
78+
}
79+
}
80+
81+
struct Unit;
82+
83+
impl Serialize for Unit {
84+
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
85+
where
86+
S: serde::Serializer,
87+
{
88+
assert!(!serializer.is_human_readable());
89+
serializer.serialize_unit_struct("Unit")
90+
}
91+
}
92+
93+
impl<'de> Deserialize<'de> for Unit {
94+
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
95+
where
96+
D: serde::Deserializer<'de>,
97+
{
98+
assert!(!deserializer.is_human_readable());
99+
Ok(Unit)
100+
}
101+
}
102+
103+
#[derive(Deserialize)]
104+
struct Tuple(Unit);
105+
106+
impl Serialize for Tuple {
107+
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
108+
where
109+
S: serde::Serializer,
110+
{
111+
assert!(!serializer.is_human_readable());
112+
let mut state = serializer.serialize_tuple_struct("Tuple", 1)?;
113+
state.serialize_field(&self.0)?;
114+
state.end()
115+
}
116+
}
117+
118+
struct Map {
119+
map: HashMap<String, Unit>,
120+
}
121+
122+
impl Serialize for Map {
123+
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
124+
where
125+
S: serde::Serializer,
126+
{
127+
assert!(!serializer.is_human_readable());
128+
129+
let mut state = serializer.serialize_map(Some(self.map.len()))?;
130+
for (k, v) in self.map.iter() {
131+
state.serialize_entry(k, &v)?;
132+
}
133+
state.end()
134+
}
135+
}
136+
137+
impl<'de> Deserialize<'de> for Map {
138+
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
139+
where
140+
D: serde::Deserializer<'de>,
141+
{
142+
assert!(!deserializer.is_human_readable());
143+
let map = Deserialize::deserialize(deserializer)?;
144+
Ok(Self { map })
145+
}
146+
}
147+
148+
struct Seq {
149+
seq: Vec<Unit>,
150+
}
151+
152+
impl Serialize for Seq {
153+
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
154+
where
155+
S: serde::Serializer,
156+
{
157+
assert!(!serializer.is_human_readable());
158+
159+
let mut state = serializer.serialize_seq(Some(self.seq.len()))?;
160+
for v in self.seq.iter() {
161+
state.serialize_element(&v)?;
162+
}
163+
state.end()
164+
}
165+
}
166+
167+
impl<'de> Deserialize<'de> for Seq {
168+
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
169+
where
170+
D: serde::Deserializer<'de>,
171+
{
172+
assert!(!deserializer.is_human_readable());
173+
let v = Vec::<Unit>::deserialize(deserializer)?;
174+
Ok(Self { seq: v })
175+
}
176+
}
177+
178+
#[test]
179+
fn to_bson_with_options() {
180+
let options = SerializerOptions::builder().human_readable(false).build();
181+
182+
let mut hm = HashMap::new();
183+
hm.insert("ok".to_string(), Unit);
184+
hm.insert("other".to_string(), Unit);
185+
let f = Foo {
186+
a: 5,
187+
unit: Unit,
188+
tuple: Tuple(Unit),
189+
unit_variant: Bar::Unit,
190+
tuple_variant: Bar::Tuple(Unit),
191+
struct_variant: Bar::Struct { a: Unit },
192+
map: Map { map: hm },
193+
seq: Seq {
194+
seq: vec![Unit, Unit],
195+
},
196+
};
197+
bson::to_bson_with_options(&f, options).unwrap();
198+
}
199+
200+
#[test]
201+
fn from_bson_with_options() {
202+
let options = DeserializerOptions::builder().human_readable(false).build();
203+
204+
let doc = doc! {
205+
"a": 5,
206+
"unit": Bson::Null,
207+
"tuple": [Bson::Null],
208+
"unit_variant": { "Unit": Bson::Null },
209+
"tuple_variant": { "Tuple": [Bson::Null] },
210+
"struct_variant": { "Struct": { "a": Bson::Null } },
211+
"map": { "a": Bson::Null, "b": Bson::Null },
212+
"seq": [Bson::Null, Bson::Null],
213+
};
214+
215+
let _: Foo = bson::from_bson_with_options(doc.into(), options).unwrap();
216+
}

serde-tests/test.rs

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
#![allow(clippy::cognitive_complexity)]
22
#![allow(clippy::vec_init_then_push)]
33

4+
mod options;
5+
46
use pretty_assertions::assert_eq;
57
use serde::{
68
self,
@@ -15,6 +17,7 @@ use std::{
1517
};
1618

1719
use bson::{
20+
bson,
1821
doc,
1922
oid::ObjectId,
2023
spec::BinarySubtype,
@@ -23,6 +26,7 @@ use bson::{
2326
DateTime,
2427
Decimal128,
2528
Deserializer,
29+
DeserializerOptions,
2630
Document,
2731
JavaScriptCodeWithScope,
2832
RawArray,
@@ -34,6 +38,7 @@ use bson::{
3438
RawJavaScriptCodeWithScope,
3539
RawRegex,
3640
Regex,
41+
SerializerOptions,
3742
Timestamp,
3843
Uuid,
3944
};
@@ -75,6 +80,23 @@ where
7580
description
7681
);
7782

83+
let non_human_readable_doc = bson::to_document_with_options(
84+
&expected_value,
85+
SerializerOptions::builder().human_readable(false).build(),
86+
)
87+
.expect(description);
88+
assert_eq!(&non_human_readable_doc, expected_doc, "{}", description);
89+
assert_eq!(
90+
expected_value,
91+
&bson::from_document_with_options::<T>(
92+
non_human_readable_doc,
93+
DeserializerOptions::builder().human_readable(false).build()
94+
)
95+
.expect(description),
96+
"{}",
97+
description
98+
);
99+
78100
assert_eq!(
79101
&bson::from_reader::<_, T>(expected_bytes.as_slice()).expect(description),
80102
expected_value,
@@ -1240,3 +1262,58 @@ fn hint_cleared() {
12401262

12411263
assert_eq!(round_doc, doc! { "doc": doc_value, "binary": binary_value });
12421264
}
1265+
1266+
#[test]
1267+
fn non_human_readable() {
1268+
let bytes = vec![1, 2, 3, 4];
1269+
let binary = RawBinary {
1270+
bytes: &bytes,
1271+
subtype: BinarySubtype::BinaryOld,
1272+
};
1273+
1274+
let doc_bytes = bson::to_vec(&doc! { "a": "b", "array": [1, 2, 3] }).unwrap();
1275+
let doc = RawDocument::new(doc_bytes.as_slice()).unwrap();
1276+
let arr = doc.get_array("array").unwrap();
1277+
let oid = ObjectId::new();
1278+
let uuid = Uuid::new();
1279+
1280+
#[derive(Debug, Deserialize, Serialize)]
1281+
struct Foo<'a> {
1282+
#[serde(borrow)]
1283+
binary: RawBinary<'a>,
1284+
#[serde(borrow)]
1285+
doc: &'a RawDocument,
1286+
#[serde(borrow)]
1287+
arr: &'a RawArray,
1288+
oid: ObjectId,
1289+
uuid: Uuid,
1290+
}
1291+
1292+
let val = Foo {
1293+
binary,
1294+
doc,
1295+
arr,
1296+
oid,
1297+
uuid,
1298+
};
1299+
1300+
let human_readable = bson::to_bson(&val).unwrap();
1301+
let non_human_readable = bson::to_bson_with_options(
1302+
&val,
1303+
SerializerOptions::builder().human_readable(false).build(),
1304+
)
1305+
.unwrap();
1306+
1307+
let expected = bson!({
1308+
"binary": Binary { bytes: bytes.clone(), subtype: BinarySubtype::BinaryOld },
1309+
"doc": {
1310+
"a": "b",
1311+
"array": [1, 2, 3],
1312+
},
1313+
"arr": [1, 2, 3],
1314+
"oid": oid,
1315+
"uuid": uuid
1316+
});
1317+
assert_eq!(human_readable, expected);
1318+
assert_eq!(human_readable, non_human_readable);
1319+
}

src/bson.rs

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1062,19 +1062,30 @@ impl Display for Binary {
10621062

10631063
impl Binary {
10641064
pub(crate) fn from_extended_doc(doc: &Document) -> Option<Self> {
1065-
let binary = doc.get_document("$binary").ok()?;
1066-
let bytes = binary.get_str("base64").ok()?;
1067-
let bytes = base64::decode(bytes).ok()?;
1068-
let subtype = binary.get_str("subType").ok()?;
1069-
let subtype = hex::decode(subtype).ok()?;
1065+
let binary_doc = doc.get_document("$binary").ok()?;
1066+
1067+
if let Ok(bytes) = binary_doc.get_str("base64") {
1068+
let bytes = base64::decode(bytes).ok()?;
1069+
let subtype = binary_doc.get_str("subType").ok()?;
1070+
let subtype = hex::decode(subtype).ok()?;
1071+
if subtype.len() == 1 {
1072+
Some(Self {
1073+
bytes,
1074+
subtype: subtype[0].into(),
1075+
})
1076+
} else {
1077+
None
1078+
}
1079+
} else {
1080+
// in non-human-readable mode, RawBinary will serialize as
1081+
// { "$binary": { "bytes": <bytes>, "subType": <i32> } };
1082+
let binary = binary_doc.get_binary_generic("bytes").ok()?;
1083+
let subtype = binary_doc.get_i32("subType").ok()?;
10701084

1071-
if subtype.len() == 1 {
10721085
Some(Self {
1073-
bytes,
1074-
subtype: subtype[0].into(),
1086+
bytes: binary.clone(),
1087+
subtype: u8::try_from(subtype).ok()?.into(),
10751088
})
1076-
} else {
1077-
None
10781089
}
10791090
}
10801091
}

0 commit comments

Comments
 (0)