Skip to content

Commit 0897133

Browse files
committed
support deserializing RawBson from Bson
1 parent a25bf3c commit 0897133

File tree

7 files changed

+171
-112
lines changed

7 files changed

+171
-112
lines changed

serde-tests/test.rs

Lines changed: 27 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ use bson::{
3939
RawDbPointerRef,
4040
RawDocument,
4141
RawDocumentBuf,
42+
RawJavaScriptCodeWithScope,
4243
RawJavaScriptCodeWithScopeRef,
4344
RawRegexRef,
4445
Regex,
@@ -52,9 +53,9 @@ use bson::{
5253
/// - serializing the `expected_value` to a `Document` matches the `expected_doc`
5354
/// - deserializing from the serialized document produces `expected_value`
5455
/// - round trip through raw BSON:
55-
/// - deserializing a `T` from the raw BSON version of `expected_doc` produces `expected_value`
56-
/// - deserializing a `Document` from the raw BSON version of `expected_doc` produces
57-
/// `expected_doc`
56+
/// - serializering `expected_value` to BSON bytes matches the raw BSON bytes of `expected_doc`
57+
/// - deserializing a `T` from the serialized bytes produces `expected_value`
58+
/// - deserializing a `Document` from the serialized bytes produces `expected_doc`
5859
/// - `bson::to_writer` and `Document::to_writer` produce the same result given the same input
5960
fn run_test<T>(expected_value: &T, expected_doc: &Document, description: &str)
6061
where
@@ -1244,17 +1245,34 @@ fn owned_raw_types() {
12441245

12451246
let oid = ObjectId::new();
12461247
let dt = DateTime::now();
1248+
let d128 = Decimal128::from_bytes([1; 16]);
1249+
1250+
let raw_code_w_scope = RawJavaScriptCodeWithScope {
1251+
code: "code".to_string(),
1252+
scope: RawDocumentBuf::new(),
1253+
};
1254+
let code_w_scope = JavaScriptCodeWithScope {
1255+
code: "code".to_string(),
1256+
scope: doc! {},
1257+
};
12471258

12481259
let f = Foo {
12491260
subdoc: RawDocumentBuf::from_iter([
12501261
("a key", RawBson::String("a value".to_string())),
12511262
("an objectid", RawBson::ObjectId(oid)),
12521263
("a date", RawBson::DateTime(dt)),
1264+
(
1265+
"code_w_scope",
1266+
RawBson::JavaScriptCodeWithScope(raw_code_w_scope.clone()),
1267+
),
1268+
("decimal128", RawBson::Decimal128(d128)),
12531269
]),
12541270
array: RawArrayBuf::from_iter([
12551271
RawBson::String("a string".to_string()),
12561272
RawBson::ObjectId(oid),
12571273
RawBson::DateTime(dt),
1274+
RawBson::JavaScriptCodeWithScope(raw_code_w_scope),
1275+
RawBson::Decimal128(d128),
12581276
]),
12591277
};
12601278

@@ -1263,28 +1281,19 @@ fn owned_raw_types() {
12631281
"a key": "a value",
12641282
"an objectid": oid,
12651283
"a date": dt,
1284+
"code_w_scope": code_w_scope.clone(),
1285+
"decimal128": d128,
12661286
},
12671287
"array": [
12681288
"a string",
12691289
oid,
1270-
dt
1290+
dt,
1291+
code_w_scope,
1292+
d128,
12711293
]
12721294
};
12731295

1274-
// TODO: RUST-1111
1275-
// can't use run_test here because deserializing RawDocumentBuf and RawArrayBuf
1276-
// from Bson or Document currently don't work.
1277-
1278-
let bytes = bson::to_vec(&expected).unwrap();
1279-
1280-
let deserialized: Foo = bson::from_slice(bytes.as_slice()).unwrap();
1281-
assert_eq!(deserialized, f);
1282-
1283-
let serialized = bson::to_document(&deserialized).unwrap();
1284-
assert_eq!(serialized, expected);
1285-
1286-
let serialized_bytes = bson::to_vec(&deserialized).unwrap();
1287-
assert_eq!(serialized_bytes, bytes);
1296+
run_test(&f, &expected, "owned_raw_types");
12881297
}
12891298

12901299
#[test]

src/bson.rs

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -529,7 +529,7 @@ impl Bson {
529529
/// This function mainly used for [extended JSON format](https://docs.mongodb.com/manual/reference/mongodb-extended-json/).
530530
// TODO RUST-426: Investigate either removing this from the serde implementation or unifying
531531
// with the extended JSON implementation.
532-
pub(crate) fn into_extended_document(self) -> Document {
532+
pub(crate) fn into_extended_document(self, rawbson: bool) -> Document {
533533
match self {
534534
Bson::RegularExpression(Regex {
535535
ref pattern,
@@ -566,12 +566,21 @@ impl Bson {
566566
}
567567
}
568568
}
569-
Bson::Binary(Binary { subtype, ref bytes }) => {
569+
Bson::Binary(Binary { subtype, bytes }) => {
570570
let tval: u8 = From::from(subtype);
571-
doc! {
572-
"$binary": {
573-
"base64": base64::encode(bytes),
574-
"subType": hex::encode([tval]),
571+
if rawbson {
572+
doc! {
573+
"$binary": {
574+
"bytes": Binary { subtype: BinarySubtype::Generic, bytes },
575+
"subType": Bson::Int32(tval.into())
576+
}
577+
}
578+
} else {
579+
doc! {
580+
"$binary": {
581+
"base64": base64::encode(bytes),
582+
"subType": hex::encode([tval]),
583+
}
575584
}
576585
}
577586
}
@@ -580,6 +589,9 @@ impl Bson {
580589
"$oid": v.to_string(),
581590
}
582591
}
592+
Bson::DateTime(v) if rawbson => doc! {
593+
"$date": v.timestamp_millis(),
594+
},
583595
Bson::DateTime(v) if v.timestamp_millis() >= 0 && v.to_chrono().year() <= 9999 => {
584596
doc! {
585597
"$date": v.to_rfc3339_string(),

src/de/mod.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,22 @@ pub(crate) const MIN_BSON_DOCUMENT_SIZE: i32 = 4 + 1; // 4 bytes for length, one
5656
pub(crate) const MIN_BSON_STRING_SIZE: i32 = 4 + 1; // 4 bytes for length, one byte for null terminator
5757
pub(crate) const MIN_CODE_WITH_SCOPE_SIZE: i32 = 4 + MIN_BSON_STRING_SIZE + MIN_BSON_DOCUMENT_SIZE;
5858

59+
/// Hint provided to the deserializer via `deserialize_newtype_struct` as to the type of thing
60+
/// being deserialized.
61+
#[derive(Debug, Clone, Copy)]
62+
enum DeserializerHint {
63+
/// No hint provided, deserialize normally.
64+
None,
65+
66+
/// The type being deserialized expects the BSON to contain a binary value with the provided
67+
/// subtype. This is currently used to deserialize `bson::Uuid` values.
68+
BinarySubtype(BinarySubtype),
69+
70+
/// The type being deserialized is raw BSON, meaning no allocations should occur as part of
71+
/// deserializing and everything should be visited via borrowing or `Copy` if possible.
72+
RawBson,
73+
}
74+
5975
/// Run the provided closure, ensuring that over the course of its execution, exactly `length` bytes
6076
/// were read from the reader.
6177
pub(crate) fn ensure_read_exactly<F, R>(

src/de/raw.rs

Lines changed: 12 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ use crate::{
1919
Bson,
2020
DateTime,
2121
Decimal128,
22+
DeserializerOptions,
2223
RawDocument,
2324
Timestamp,
2425
};
@@ -31,29 +32,14 @@ use super::{
3132
read_i64,
3233
read_string,
3334
read_u8,
35+
DeserializerHint,
3436
Error,
3537
Result,
3638
MAX_BSON_SIZE,
3739
MIN_CODE_WITH_SCOPE_SIZE,
3840
};
3941
use crate::de::serde::MapDeserializer;
4042

41-
/// Hint provided to the deserializer via `deserialize_newtype_struct` as to the type of thing
42-
/// being deserialized.
43-
#[derive(Debug, Clone, Copy)]
44-
enum DeserializerHint {
45-
/// No hint provided, deserialize normally.
46-
None,
47-
48-
/// The type being deserialized expects the BSON to contain a binary value with the provided
49-
/// subtype. This is currently used to deserialize `bson::Uuid` values.
50-
BinarySubtype(BinarySubtype),
51-
52-
/// The type being deserialized is raw BSON, meaning no allocations should occur as part of
53-
/// deserializing and everything should be visited via borrowing or `Copy`.
54-
RawBson,
55-
}
56-
5743
/// Deserializer used to parse and deserialize raw BSON bytes.
5844
pub(crate) struct Deserializer<'de> {
5945
bytes: BsonBuf<'de>,
@@ -307,8 +293,11 @@ impl<'de> Deserializer<'de> {
307293
)),
308294
_ => {
309295
let code = read_string(&mut self.bytes, utf8_lossy)?;
310-
let doc = Bson::JavaScriptCode(code).into_extended_document();
311-
visitor.visit_map(MapDeserializer::new(doc))
296+
let doc = Bson::JavaScriptCode(code).into_extended_document(false);
297+
visitor.visit_map(MapDeserializer::new(
298+
doc,
299+
DeserializerOptions::builder().human_readable(false).build(),
300+
))
312301
}
313302
}
314303
}
@@ -361,8 +350,11 @@ impl<'de> Deserializer<'de> {
361350
)),
362351
_ => {
363352
let symbol = read_string(&mut self.bytes, utf8_lossy)?;
364-
let doc = Bson::Symbol(symbol).into_extended_document();
365-
visitor.visit_map(MapDeserializer::new(doc))
353+
let doc = Bson::Symbol(symbol).into_extended_document(false);
354+
visitor.visit_map(MapDeserializer::new(
355+
doc,
356+
DeserializerOptions::builder().human_readable(false).build(),
357+
))
366358
}
367359
}
368360
}

0 commit comments

Comments
 (0)