Skip to content

Commit 52528a7

Browse files
RUST-503 Support serializing directly to Document (#210)
1 parent 3773666 commit 52528a7

File tree

5 files changed

+86
-5
lines changed

5 files changed

+86
-5
lines changed

src/de/mod.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -355,3 +355,11 @@ where
355355
let de = Deserializer::new(bson);
356356
Deserialize::deserialize(de)
357357
}
358+
359+
/// Decode a BSON `Document` into a `T` Deserializable.
360+
pub fn from_document<T>(doc: Document) -> Result<T>
361+
where
362+
T: DeserializeOwned,
363+
{
364+
from_bson(Bson::Document(doc))
365+
}

src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -196,9 +196,9 @@ pub use self::{
196196
Regex,
197197
Timestamp,
198198
},
199-
de::{from_bson, Deserializer},
199+
de::{from_bson, from_document, Deserializer},
200200
decimal128::Decimal128,
201-
ser::{to_bson, Serializer},
201+
ser::{to_bson, to_document, Serializer},
202202
};
203203

204204
#[macro_use]

src/ser/mod.rs

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ use chrono::Timelike;
3636
#[cfg(feature = "decimal128")]
3737
use crate::decimal128::Decimal128;
3838
use crate::{
39-
bson::{Binary, Bson, DbPointer, JavaScriptCodeWithScope, Regex},
39+
bson::{Binary, Bson, DbPointer, Document, JavaScriptCodeWithScope, Regex},
4040
spec::BinarySubtype,
4141
};
4242
use ::serde::Serialize;
@@ -189,3 +189,19 @@ where
189189
let ser = Serializer::new();
190190
value.serialize(ser)
191191
}
192+
193+
/// Encode a `T` Serializable into a BSON `Document`.
194+
pub fn to_document<T: ?Sized>(value: &T) -> Result<Document>
195+
where
196+
T: Serialize,
197+
{
198+
match to_bson(value)? {
199+
Bson::Document(doc) => Ok(doc),
200+
bson => Err(Error::SerializationError {
201+
message: format!(
202+
"Could not be serialized to Document, got {:?} instead",
203+
bson.element_type()
204+
),
205+
}),
206+
}
207+
}

src/tests/modules/ser.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1+
use std::{collections::BTreeMap, u16, u32, u64, u8};
2+
3+
use assert_matches::assert_matches;
4+
15
#[cfg(feature = "decimal128")]
26
use crate::decimal128::Decimal128;
37
use crate::{from_bson, oid::ObjectId, ser, tests::LOCK, to_bson, Bson};
4-
use assert_matches::assert_matches;
5-
use std::{collections::BTreeMap, u16, u32, u64, u8};
68

79
#[test]
810
#[allow(clippy::float_cmp)]

src/tests/modules/serializer_deserializer.rs

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,18 @@ use std::{
33
io::{Cursor, Write},
44
};
55

6+
use serde::{Deserialize, Serialize};
7+
68
#[cfg(feature = "decimal128")]
79
use crate::decimal128::Decimal128;
810
use crate::{
11+
de::from_document,
912
doc,
1013
oid::ObjectId,
14+
ser::Error,
1115
spec::BinarySubtype,
1216
tests::LOCK,
17+
to_document,
1318
Binary,
1419
Bson,
1520
Document,
@@ -470,3 +475,53 @@ fn test_serialize_deserialize_db_pointer() {
470475
let deserialized = Document::from_reader(&mut Cursor::new(buf)).unwrap();
471476
assert_eq!(deserialized, doc);
472477
}
478+
479+
#[test]
480+
fn test_serialize_deserialize_document() {
481+
let _guard = LOCK.run_concurrently();
482+
483+
#[derive(Debug, Deserialize, Serialize, PartialEq)]
484+
struct Point {
485+
x: i32,
486+
y: i32,
487+
}
488+
let src = Point { x: 1, y: 2 };
489+
490+
let doc = to_document(&src).unwrap();
491+
assert_eq!(doc, doc! { "x": 1, "y": 2 });
492+
493+
let point: Point = from_document(doc).unwrap();
494+
assert_eq!(src, point);
495+
496+
#[derive(Debug, Deserialize, Serialize, PartialEq)]
497+
struct Line {
498+
p1: Point,
499+
p2: Point,
500+
}
501+
let src = Line {
502+
p1: Point { x: 0, y: 0 },
503+
p2: Point { x: 1, y: 1 },
504+
};
505+
506+
let doc = to_document(&src).unwrap();
507+
assert_eq!(
508+
doc,
509+
doc! { "p1": { "x": 0, "y": 0 }, "p2": { "x": 1, "y": 1 } }
510+
);
511+
512+
let line: Line = from_document(doc).unwrap();
513+
assert_eq!(src, line);
514+
515+
let x = 1;
516+
let err = to_document(&x).unwrap_err();
517+
match err {
518+
Error::SerializationError { message } => {
519+
assert!(message.contains("Could not be serialized to Document"));
520+
}
521+
e => panic!("expected SerializationError, got {}", e),
522+
}
523+
524+
let bad_point = doc! { "x": "one", "y": "two" };
525+
let bad_point: Result<Point, crate::de::Error> = from_document(bad_point);
526+
assert!(bad_point.is_err());
527+
}

0 commit comments

Comments
 (0)