Skip to content

Commit 0ed3635

Browse files
authored
RUST-1773 Merge duplicate extjson map parsing between OwnedOrBorrowedRawBsonVisitor and SeededVisitor (#480)
1 parent f525546 commit 0ed3635

File tree

4 files changed

+261
-262
lines changed

4 files changed

+261
-262
lines changed

src/datetime.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -405,6 +405,10 @@ impl crate::DateTime {
405405
self.checked_duration_since(earlier)
406406
.unwrap_or(Duration::ZERO)
407407
}
408+
409+
pub(crate) fn as_le_bytes(&self) -> [u8; 8] {
410+
self.0.to_le_bytes()
411+
}
408412
}
409413

410414
impl fmt::Debug for crate::DateTime {

src/raw/serde.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,18 @@ pub(crate) enum OwnedOrBorrowedRawBson<'a> {
3333
Borrowed(RawBsonRef<'a>),
3434
}
3535

36+
impl<'a> OwnedOrBorrowedRawBson<'a> {
37+
pub(crate) fn as_ref<'b>(&'b self) -> RawBsonRef<'b>
38+
where
39+
'a: 'b,
40+
{
41+
match self {
42+
Self::Borrowed(r) => *r,
43+
Self::Owned(bson) => bson.as_raw_bson_ref(),
44+
}
45+
}
46+
}
47+
3648
impl<'a, 'de: 'a> Deserialize<'de> for OwnedOrBorrowedRawBson<'a> {
3749
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
3850
where

src/raw/serde/bson_visitor.rs

Lines changed: 157 additions & 139 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,160 @@ use super::{
4444
/// A visitor used to deserialize types backed by raw BSON.
4545
pub(crate) struct OwnedOrBorrowedRawBsonVisitor;
4646

47+
pub(super) enum MapParse<'de> {
48+
Leaf(OwnedOrBorrowedRawBson<'de>),
49+
Aggregate(CowStr<'de>),
50+
}
51+
52+
impl OwnedOrBorrowedRawBsonVisitor {
53+
pub(super) fn parse_map<'de, A>(map: &mut A) -> Result<MapParse<'de>, A::Error>
54+
where
55+
A: serde::de::MapAccess<'de>,
56+
{
57+
let first_key = match map.next_key::<CowStr>()? {
58+
Some(k) => k,
59+
None => {
60+
return Ok(MapParse::Leaf(
61+
RawBson::Document(RawDocumentBuf::new()).into(),
62+
))
63+
}
64+
};
65+
Ok(MapParse::Leaf(match first_key.0.as_ref() {
66+
"$oid" => {
67+
let oid: ObjectId = map.next_value()?;
68+
RawBsonRef::ObjectId(oid).into()
69+
}
70+
"$symbol" => {
71+
let s: CowStr = map.next_value()?;
72+
match s.0 {
73+
Cow::Borrowed(s) => RawBsonRef::Symbol(s).into(),
74+
Cow::Owned(s) => RawBson::Symbol(s).into(),
75+
}
76+
}
77+
"$numberDecimalBytes" => {
78+
let bytes: ByteBuf = map.next_value()?;
79+
RawBsonRef::Decimal128(Decimal128::deserialize_from_slice(bytes.as_ref())?).into()
80+
}
81+
"$regularExpression" => {
82+
let body: BorrowedRegexBody = map.next_value()?;
83+
84+
match (body.pattern, body.options) {
85+
(Cow::Borrowed(p), Cow::Borrowed(o)) => {
86+
RawBsonRef::RegularExpression(RawRegexRef {
87+
pattern: p,
88+
options: o,
89+
})
90+
.into()
91+
}
92+
(p, o) => RawBson::RegularExpression(Regex {
93+
pattern: p.into_owned(),
94+
options: o.into_owned(),
95+
})
96+
.into(),
97+
}
98+
}
99+
"$undefined" => {
100+
let _: bool = map.next_value()?;
101+
RawBsonRef::Undefined.into()
102+
}
103+
"$binary" => {
104+
let v: BorrowedBinaryBody = map.next_value()?;
105+
106+
if let Cow::Borrowed(bytes) = v.bytes {
107+
RawBsonRef::Binary(RawBinaryRef {
108+
bytes,
109+
subtype: v.subtype.into(),
110+
})
111+
.into()
112+
} else {
113+
RawBson::Binary(Binary {
114+
bytes: v.bytes.into_owned(),
115+
subtype: v.subtype.into(),
116+
})
117+
.into()
118+
}
119+
}
120+
"$date" => {
121+
let date: i64 = map.next_value()?;
122+
RawBsonRef::DateTime(DateTime::from_millis(date)).into()
123+
}
124+
"$timestamp" => {
125+
let timestamp: TimestampBody = map.next_value()?;
126+
RawBsonRef::Timestamp(Timestamp {
127+
time: timestamp.t,
128+
increment: timestamp.i,
129+
})
130+
.into()
131+
}
132+
"$minKey" => {
133+
let _ = map.next_value::<i32>()?;
134+
RawBsonRef::MinKey.into()
135+
}
136+
"$maxKey" => {
137+
let _ = map.next_value::<i32>()?;
138+
RawBsonRef::MaxKey.into()
139+
}
140+
"$code" => {
141+
let code = map.next_value::<CowStr>()?;
142+
if let Some(key) = map.next_key::<CowStr>()? {
143+
if key.0.as_ref() == "$scope" {
144+
let scope = map.next_value::<OwnedOrBorrowedRawDocument>()?;
145+
match (code.0, scope) {
146+
(Cow::Borrowed(code), OwnedOrBorrowedRawDocument::Borrowed(scope)) => {
147+
RawBsonRef::JavaScriptCodeWithScope(RawJavaScriptCodeWithScopeRef {
148+
code,
149+
scope,
150+
})
151+
.into()
152+
}
153+
(code, scope) => {
154+
RawBson::JavaScriptCodeWithScope(RawJavaScriptCodeWithScope {
155+
code: code.into_owned(),
156+
scope: scope.into_owned(),
157+
})
158+
.into()
159+
}
160+
}
161+
} else {
162+
return Err(SerdeError::unknown_field(&key.0, &["$scope"]));
163+
}
164+
} else if let Cow::Borrowed(code) = code.0 {
165+
RawBsonRef::JavaScriptCode(code).into()
166+
} else {
167+
RawBson::JavaScriptCode(code.0.into_owned()).into()
168+
}
169+
}
170+
"$dbPointer" => {
171+
let db_pointer: BorrowedDbPointerBody = map.next_value()?;
172+
if let Cow::Borrowed(ns) = db_pointer.ns.0 {
173+
RawBsonRef::DbPointer(RawDbPointerRef {
174+
namespace: ns,
175+
id: db_pointer.id,
176+
})
177+
.into()
178+
} else {
179+
RawBson::DbPointer(DbPointer {
180+
namespace: db_pointer.ns.0.into_owned(),
181+
id: db_pointer.id,
182+
})
183+
.into()
184+
}
185+
}
186+
RAW_DOCUMENT_NEWTYPE => {
187+
let bson = map.next_value::<&[u8]>()?;
188+
let doc = RawDocument::from_bytes(bson).map_err(SerdeError::custom)?;
189+
RawBsonRef::Document(doc).into()
190+
}
191+
RAW_ARRAY_NEWTYPE => {
192+
let bson = map.next_value::<&[u8]>()?;
193+
let doc = RawDocument::from_bytes(bson).map_err(SerdeError::custom)?;
194+
RawBsonRef::Array(RawArray::from_doc(doc)).into()
195+
}
196+
_ => return Ok(MapParse::Aggregate(first_key)),
197+
}))
198+
}
199+
}
200+
47201
impl<'de> Visitor<'de> for OwnedOrBorrowedRawBsonVisitor {
48202
type Value = OwnedOrBorrowedRawBson<'de>;
49203

@@ -209,145 +363,9 @@ impl<'de> Visitor<'de> for OwnedOrBorrowedRawBsonVisitor {
209363
where
210364
A: serde::de::MapAccess<'de>,
211365
{
212-
let first_key = match map.next_key::<CowStr>()? {
213-
Some(k) => k,
214-
None => return Ok(RawBson::Document(RawDocumentBuf::new()).into()),
215-
};
216-
217-
match first_key.0.as_ref() {
218-
"$oid" => {
219-
let oid: ObjectId = map.next_value()?;
220-
Ok(RawBsonRef::ObjectId(oid).into())
221-
}
222-
"$symbol" => {
223-
let s: CowStr = map.next_value()?;
224-
match s.0 {
225-
Cow::Borrowed(s) => Ok(RawBsonRef::Symbol(s).into()),
226-
Cow::Owned(s) => Ok(RawBson::Symbol(s).into()),
227-
}
228-
}
229-
"$numberDecimalBytes" => {
230-
let bytes: ByteBuf = map.next_value()?;
231-
return Ok(RawBsonRef::Decimal128(Decimal128::deserialize_from_slice(
232-
bytes.as_ref(),
233-
)?)
234-
.into());
235-
}
236-
"$regularExpression" => {
237-
let body: BorrowedRegexBody = map.next_value()?;
238-
239-
match (body.pattern, body.options) {
240-
(Cow::Borrowed(p), Cow::Borrowed(o)) => {
241-
Ok(RawBsonRef::RegularExpression(RawRegexRef {
242-
pattern: p,
243-
options: o,
244-
})
245-
.into())
246-
}
247-
(p, o) => Ok(RawBson::RegularExpression(Regex {
248-
pattern: p.into_owned(),
249-
options: o.into_owned(),
250-
})
251-
.into()),
252-
}
253-
}
254-
"$undefined" => {
255-
let _: bool = map.next_value()?;
256-
Ok(RawBsonRef::Undefined.into())
257-
}
258-
"$binary" => {
259-
let v: BorrowedBinaryBody = map.next_value()?;
260-
261-
if let Cow::Borrowed(bytes) = v.bytes {
262-
Ok(RawBsonRef::Binary(RawBinaryRef {
263-
bytes,
264-
subtype: v.subtype.into(),
265-
})
266-
.into())
267-
} else {
268-
Ok(RawBson::Binary(Binary {
269-
bytes: v.bytes.into_owned(),
270-
subtype: v.subtype.into(),
271-
})
272-
.into())
273-
}
274-
}
275-
"$date" => {
276-
let date: i64 = map.next_value()?;
277-
Ok(RawBsonRef::DateTime(DateTime::from_millis(date)).into())
278-
}
279-
"$timestamp" => {
280-
let timestamp: TimestampBody = map.next_value()?;
281-
Ok(RawBsonRef::Timestamp(Timestamp {
282-
time: timestamp.t,
283-
increment: timestamp.i,
284-
})
285-
.into())
286-
}
287-
"$minKey" => {
288-
let _ = map.next_value::<i32>()?;
289-
Ok(RawBsonRef::MinKey.into())
290-
}
291-
"$maxKey" => {
292-
let _ = map.next_value::<i32>()?;
293-
Ok(RawBsonRef::MaxKey.into())
294-
}
295-
"$code" => {
296-
let code = map.next_value::<CowStr>()?;
297-
if let Some(key) = map.next_key::<CowStr>()? {
298-
if key.0.as_ref() == "$scope" {
299-
let scope = map.next_value::<OwnedOrBorrowedRawDocument>()?;
300-
match (code.0, scope) {
301-
(Cow::Borrowed(code), OwnedOrBorrowedRawDocument::Borrowed(scope)) => {
302-
Ok(RawBsonRef::JavaScriptCodeWithScope(
303-
RawJavaScriptCodeWithScopeRef { code, scope },
304-
)
305-
.into())
306-
}
307-
(code, scope) => Ok(RawBson::JavaScriptCodeWithScope(
308-
RawJavaScriptCodeWithScope {
309-
code: code.into_owned(),
310-
scope: scope.into_owned(),
311-
},
312-
)
313-
.into()),
314-
}
315-
} else {
316-
Err(SerdeError::unknown_field(&key.0, &["$scope"]))
317-
}
318-
} else if let Cow::Borrowed(code) = code.0 {
319-
Ok(RawBsonRef::JavaScriptCode(code).into())
320-
} else {
321-
Ok(RawBson::JavaScriptCode(code.0.into_owned()).into())
322-
}
323-
}
324-
"$dbPointer" => {
325-
let db_pointer: BorrowedDbPointerBody = map.next_value()?;
326-
if let Cow::Borrowed(ns) = db_pointer.ns.0 {
327-
Ok(RawBsonRef::DbPointer(RawDbPointerRef {
328-
namespace: ns,
329-
id: db_pointer.id,
330-
})
331-
.into())
332-
} else {
333-
Ok(RawBson::DbPointer(DbPointer {
334-
namespace: db_pointer.ns.0.into_owned(),
335-
id: db_pointer.id,
336-
})
337-
.into())
338-
}
339-
}
340-
RAW_DOCUMENT_NEWTYPE => {
341-
let bson = map.next_value::<&[u8]>()?;
342-
let doc = RawDocument::from_bytes(bson).map_err(SerdeError::custom)?;
343-
Ok(RawBsonRef::Document(doc).into())
344-
}
345-
RAW_ARRAY_NEWTYPE => {
346-
let bson = map.next_value::<&[u8]>()?;
347-
let doc = RawDocument::from_bytes(bson).map_err(SerdeError::custom)?;
348-
Ok(RawBsonRef::Array(RawArray::from_doc(doc)).into())
349-
}
350-
_ => {
366+
match Self::parse_map(&mut map)? {
367+
MapParse::Leaf(value) => Ok(value),
368+
MapParse::Aggregate(first_key) => {
351369
let mut buffer = CowByteBuffer::new();
352370
let seeded_visitor = SeededVisitor::new(&mut buffer);
353371
seeded_visitor.iterate_map(first_key, map)?;

0 commit comments

Comments
 (0)