Skip to content

Commit 9c4b963

Browse files
authored
RUST-1764 Add HumanReadable convenience wrapper (#471)
1 parent c5be950 commit 9c4b963

File tree

8 files changed

+229
-7
lines changed

8 files changed

+229
-7
lines changed

Diff for: rustfmt.toml

-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ combine_control_expr = false
22
comment_width = 100
33
condense_wildcard_suffixes = true
44
format_strings = true
5-
normalize_comments = true
65
use_try_shorthand = true
76
wrap_comments = true
87
imports_layout = "HorizontalVertical"

Diff for: src/de/raw.rs

+14-1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ use serde::{
1414
use crate::{
1515
oid::ObjectId,
1616
raw::{RawBinaryRef, RAW_ARRAY_NEWTYPE, RAW_BSON_NEWTYPE, RAW_DOCUMENT_NEWTYPE},
17+
serde_helpers::HUMAN_READABLE_NEWTYPE,
1718
spec::{BinarySubtype, ElementType},
1819
uuid::UUID_NEWTYPE_NAME,
1920
Bson,
@@ -51,6 +52,8 @@ pub(crate) struct Deserializer<'de> {
5152
/// but given that there's no difference between deserializing an embedded document and a
5253
/// top level one, the distinction isn't necessary.
5354
current_type: ElementType,
55+
56+
human_readable: bool,
5457
}
5558

5659
/// Enum used to determine what the type of document being deserialized is in
@@ -65,6 +68,7 @@ impl<'de> Deserializer<'de> {
6568
Self {
6669
bytes: BsonBuf::new(buf, utf8_lossy),
6770
current_type: ElementType::EmbeddedDocument,
71+
human_readable: false,
6872
}
6973
}
7074

@@ -291,6 +295,7 @@ impl<'de> Deserializer<'de> {
291295
let doc = Bson::JavaScriptCode(code).into_extended_document(false);
292296
visitor.visit_map(MapDeserializer::new(
293297
doc,
298+
#[allow(deprecated)]
294299
DeserializerOptions::builder().human_readable(false).build(),
295300
))
296301
}
@@ -348,6 +353,7 @@ impl<'de> Deserializer<'de> {
348353
let doc = Bson::Symbol(symbol).into_extended_document(false);
349354
visitor.visit_map(MapDeserializer::new(
350355
doc,
356+
#[allow(deprecated)]
351357
DeserializerOptions::builder().human_readable(false).build(),
352358
))
353359
}
@@ -454,12 +460,19 @@ impl<'de, 'a> serde::de::Deserializer<'de> for &'a mut Deserializer<'de> {
454460

455461
self.deserialize_next(visitor, DeserializerHint::RawBson)
456462
}
463+
HUMAN_READABLE_NEWTYPE => {
464+
let old = self.human_readable;
465+
self.human_readable = true;
466+
let result = visitor.visit_newtype_struct(&mut *self);
467+
self.human_readable = old;
468+
result
469+
}
457470
_ => visitor.visit_newtype_struct(self),
458471
}
459472
}
460473

461474
fn is_human_readable(&self) -> bool {
462-
false
475+
self.human_readable
463476
}
464477

465478
forward_to_deserialize_any! {

Diff for: src/de/serde.rs

+11-1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ use crate::{
2626
document::{Document, IntoIter},
2727
oid::ObjectId,
2828
raw::{RawBsonRef, RAW_ARRAY_NEWTYPE, RAW_BSON_NEWTYPE, RAW_DOCUMENT_NEWTYPE},
29+
serde_helpers::HUMAN_READABLE_NEWTYPE,
2930
spec::BinarySubtype,
3031
uuid::UUID_NEWTYPE_NAME,
3132
Binary,
@@ -578,6 +579,7 @@ pub struct Deserializer {
578579
pub struct DeserializerOptions {
579580
/// Whether the [`Deserializer`] should present itself as human readable or not.
580581
/// The default is true.
582+
#[deprecated = "use bson::serde_helpers::HumanReadable"]
581583
pub human_readable: Option<bool>,
582584
}
583585

@@ -597,6 +599,8 @@ pub struct DeserializerOptionsBuilder {
597599

598600
impl DeserializerOptionsBuilder {
599601
/// Set the value for [`DeserializerOptions::human_readable`].
602+
#[deprecated = "use bson::serde_helpers::HumanReadable"]
603+
#[allow(deprecated)]
600604
pub fn human_readable(mut self, val: impl Into<Option<bool>>) -> Self {
601605
self.options.human_readable = val.into();
602606
self
@@ -716,6 +720,7 @@ macro_rules! forward_to_deserialize {
716720
impl<'de> de::Deserializer<'de> for Deserializer {
717721
type Error = crate::de::Error;
718722

723+
#[allow(deprecated)]
719724
fn is_human_readable(&self) -> bool {
720725
self.options.human_readable.unwrap_or(true)
721726
}
@@ -815,7 +820,7 @@ impl<'de> de::Deserializer<'de> for Deserializer {
815820

816821
#[inline]
817822
fn deserialize_newtype_struct<V>(
818-
self,
823+
mut self,
819824
name: &'static str,
820825
visitor: V,
821826
) -> crate::de::Result<V::Value>
@@ -848,6 +853,11 @@ impl<'de> de::Deserializer<'de> for Deserializer {
848853

849854
self.deserialize_next(visitor, DeserializerHint::RawBson)
850855
}
856+
#[allow(deprecated)]
857+
HUMAN_READABLE_NEWTYPE => {
858+
self.options.human_readable = Some(true);
859+
visitor.visit_newtype_struct(self)
860+
}
851861
_ => visitor.visit_newtype_struct(self),
852862
}
853863
}

Diff for: src/ser/raw/mod.rs

+12-1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ use super::{write_binary, write_cstring, write_f64, write_i32, write_i64, write_
1414
use crate::{
1515
raw::{RAW_ARRAY_NEWTYPE, RAW_DOCUMENT_NEWTYPE},
1616
ser::{Error, Result},
17+
serde_helpers::HUMAN_READABLE_NEWTYPE,
1718
spec::{BinarySubtype, ElementType},
1819
uuid::UUID_NEWTYPE_NAME,
1920
};
@@ -30,6 +31,8 @@ pub(crate) struct Serializer {
3031

3132
/// Hint provided by the type being serialized.
3233
hint: SerializerHint,
34+
35+
human_readable: bool,
3336
}
3437

3538
/// Various bits of information that the serialized type can provide to the serializer to
@@ -60,6 +63,7 @@ impl Serializer {
6063
bytes: Vec::new(),
6164
type_index: 0,
6265
hint: SerializerHint::None,
66+
human_readable: false,
6367
}
6468
}
6569

@@ -115,7 +119,7 @@ impl<'a> serde::Serializer for &'a mut Serializer {
115119
type SerializeStructVariant = VariantSerializer<'a>;
116120

117121
fn is_human_readable(&self) -> bool {
118-
false
122+
self.human_readable
119123
}
120124

121125
#[inline]
@@ -267,6 +271,13 @@ impl<'a> serde::Serializer for &'a mut Serializer {
267271
UUID_NEWTYPE_NAME => self.hint = SerializerHint::Uuid,
268272
RAW_DOCUMENT_NEWTYPE => self.hint = SerializerHint::RawDocument,
269273
RAW_ARRAY_NEWTYPE => self.hint = SerializerHint::RawArray,
274+
HUMAN_READABLE_NEWTYPE => {
275+
let old = self.human_readable;
276+
self.human_readable = true;
277+
let result = value.serialize(&mut *self);
278+
self.human_readable = old;
279+
return result;
280+
}
270281
_ => {}
271282
}
272283
value.serialize(self)

Diff for: src/ser/serde.rs

+11-1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ use crate::{
1818
extjson,
1919
oid::ObjectId,
2020
raw::{RawDbPointerRef, RawRegexRef, RAW_ARRAY_NEWTYPE, RAW_DOCUMENT_NEWTYPE},
21+
serde_helpers::HUMAN_READABLE_NEWTYPE,
2122
spec::BinarySubtype,
2223
uuid::UUID_NEWTYPE_NAME,
2324
Binary,
@@ -120,6 +121,7 @@ pub struct Serializer {
120121
pub struct SerializerOptions {
121122
/// Whether the [`Serializer`] should present itself as human readable or not.
122123
/// The default value is true.
124+
#[deprecated = "use bson::serde_helpers::HumanReadable"]
123125
pub human_readable: Option<bool>,
124126
}
125127

@@ -139,6 +141,8 @@ pub struct SerializerOptionsBuilder {
139141

140142
impl SerializerOptionsBuilder {
141143
/// Set the value for [`SerializerOptions::is_human_readable`].
144+
#[deprecated = "use bson::serde_helpers::HumanReadable"]
145+
#[allow(deprecated)]
142146
pub fn human_readable(mut self, value: impl Into<Option<bool>>) -> Self {
143147
self.options.human_readable = value.into();
144148
self
@@ -296,7 +300,7 @@ impl ser::Serializer for Serializer {
296300

297301
#[inline]
298302
fn serialize_newtype_struct<T: ?Sized>(
299-
self,
303+
mut self,
300304
name: &'static str,
301305
value: &T,
302306
) -> crate::ser::Result<Bson>
@@ -348,6 +352,11 @@ impl ser::Serializer for Serializer {
348352
b
349353
))),
350354
},
355+
#[allow(deprecated)]
356+
HUMAN_READABLE_NEWTYPE => {
357+
self.options.human_readable = Some(true);
358+
value.serialize(self)
359+
}
351360
_ => value.serialize(self),
352361
}
353362
}
@@ -447,6 +456,7 @@ impl ser::Serializer for Serializer {
447456
})
448457
}
449458

459+
#[allow(deprecated)]
450460
fn is_human_readable(&self) -> bool {
451461
self.options.human_readable.unwrap_or(true)
452462
}

Diff for: src/serde_helpers.rs

+43-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
//! Collection of helper functions for serializing to and deserializing from BSON using Serde
22
3-
use std::{convert::TryFrom, result::Result};
3+
use std::{convert::TryFrom, marker::PhantomData, result::Result};
44

5-
use serde::{ser, Serialize, Serializer};
5+
use serde::{de::Visitor, ser, Deserialize, Serialize, Serializer};
66

77
use crate::oid::ObjectId;
88

@@ -794,3 +794,44 @@ pub mod timestamp_as_u32 {
794794
Ok(Timestamp { time, increment: 0 })
795795
}
796796
}
797+
798+
/// Wrapping a type in `HumanReadable` signals to the BSON serde integration that it and all
799+
/// recursively contained types should be handled as if
800+
/// [`SerializerOptions::human_readable`](crate::SerializerOptions::human_readable) and
801+
/// [`DeserializerOptions::human_readable`](crate::DeserializerOptions::human_readable) are
802+
/// set to `true`.
803+
#[derive(PartialEq, Eq, PartialOrd, Ord, Debug)]
804+
pub struct HumanReadable<T>(pub T);
805+
806+
pub(crate) const HUMAN_READABLE_NEWTYPE: &str = "$__bson_private_human_readable";
807+
808+
impl<T: Serialize> Serialize for HumanReadable<T> {
809+
fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
810+
where
811+
S: serde::Serializer,
812+
{
813+
serializer.serialize_newtype_struct(HUMAN_READABLE_NEWTYPE, &self.0)
814+
}
815+
}
816+
817+
impl<'de, T: Deserialize<'de>> Deserialize<'de> for HumanReadable<T> {
818+
fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
819+
where
820+
D: serde::Deserializer<'de>,
821+
{
822+
struct V<T>(PhantomData<fn() -> T>);
823+
impl<'de, T: Deserialize<'de>> Visitor<'de> for V<T> {
824+
type Value = HumanReadable<T>;
825+
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
826+
formatter.write_str("HumanReadable wrapper")
827+
}
828+
fn visit_newtype_struct<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
829+
where
830+
D: serde::Deserializer<'de>,
831+
{
832+
T::deserialize(deserializer).map(HumanReadable)
833+
}
834+
}
835+
deserializer.deserialize_newtype_struct(HUMAN_READABLE_NEWTYPE, V(PhantomData))
836+
}
837+
}

Diff for: src/tests/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ mod binary_subtype;
22
mod datetime;
33
mod modules;
44
mod serde;
5+
mod serde_helpers;
56
mod spec;
67

78
use modules::TestLock;

0 commit comments

Comments
 (0)