Skip to content

Commit be2a107

Browse files
authored
RUST-1992 Consolidate binary encoding logic (#560)
1 parent 92364e9 commit be2a107

File tree

9 files changed

+141
-264
lines changed

9 files changed

+141
-264
lines changed

src/binary.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,7 @@
11
#! Module containing functionality related to BSON binary values.
22
mod vector;
33

4-
use std::{
5-
convert::TryFrom,
6-
fmt::{self, Display},
7-
};
4+
use std::fmt::{self, Display};
85

96
use crate::{
107
base64,
@@ -65,6 +62,8 @@ impl Binary {
6562

6663
#[cfg(feature = "serde")]
6764
pub(crate) fn from_extended_doc(doc: &crate::Document) -> Option<Self> {
65+
use std::convert::TryFrom;
66+
6867
let binary_doc = doc.get_document("$binary").ok()?;
6968

7069
if let Ok(bytes) = binary_doc.get_str("base64") {

src/de.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,6 @@ pub(crate) use self::serde::{convert_unsigned_to_signed_raw, BsonVisitor};
4646
#[cfg(test)]
4747
pub(crate) use self::raw::Deserializer as RawDeserializer;
4848

49-
pub(crate) const MAX_BSON_SIZE: i32 = i32::MAX;
50-
5149
/// Hint provided to the deserializer via `deserialize_newtype_struct` as to the type of thing
5250
/// being deserialized.
5351
#[derive(Debug, Clone, Copy)]

src/raw/bson_ref.rs

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use std::convert::{TryFrom, TryInto};
33
use super::{bson::RawBson, Error, RawArray, RawDocument, Result};
44
use crate::{
55
oid::{self, ObjectId},
6-
raw::RawJavaScriptCodeWithScope,
6+
raw::{write_cstring, write_string, RawJavaScriptCodeWithScope},
77
spec::{BinarySubtype, ElementType},
88
Binary,
99
Bson,
@@ -285,6 +285,50 @@ impl<'a> RawBsonRef<'a> {
285285
}),
286286
}
287287
}
288+
289+
#[inline]
290+
pub(crate) fn append_to(self, dest: &mut Vec<u8>) -> Result<()> {
291+
match self {
292+
Self::Int32(val) => dest.extend(val.to_le_bytes()),
293+
Self::Int64(val) => dest.extend(val.to_le_bytes()),
294+
Self::Double(val) => dest.extend(val.to_le_bytes()),
295+
Self::Binary(b @ RawBinaryRef { subtype, bytes }) => {
296+
let len = b.len();
297+
dest.extend(len.to_le_bytes());
298+
dest.push(subtype.into());
299+
if let BinarySubtype::BinaryOld = subtype {
300+
dest.extend((len - 4).to_le_bytes())
301+
}
302+
dest.extend(bytes);
303+
}
304+
Self::String(s) => write_string(dest, s),
305+
Self::Array(raw_array) => dest.extend(raw_array.as_bytes()),
306+
Self::Document(raw_document) => dest.extend(raw_document.as_bytes()),
307+
Self::Boolean(b) => dest.push(b as u8),
308+
Self::RegularExpression(re) => {
309+
write_cstring(dest, re.pattern)?;
310+
write_cstring(dest, re.options)?;
311+
}
312+
Self::JavaScriptCode(js) => write_string(dest, js),
313+
Self::JavaScriptCodeWithScope(code_w_scope) => {
314+
let len = code_w_scope.len();
315+
dest.extend(len.to_le_bytes());
316+
write_string(dest, code_w_scope.code);
317+
dest.extend(code_w_scope.scope.as_bytes());
318+
}
319+
Self::Timestamp(ts) => dest.extend(ts.to_le_bytes()),
320+
Self::ObjectId(oid) => dest.extend(oid.bytes()),
321+
Self::DateTime(dt) => dest.extend(dt.timestamp_millis().to_le_bytes()),
322+
Self::Symbol(s) => write_string(dest, s),
323+
Self::Decimal128(d) => dest.extend(d.bytes()),
324+
Self::DbPointer(dbp) => {
325+
write_string(dest, dbp.namespace);
326+
dest.extend(dbp.id.bytes());
327+
}
328+
Self::Null | Self::Undefined | Self::MinKey | Self::MaxKey => {}
329+
}
330+
Ok(())
331+
}
288332
}
289333

290334
#[cfg(feature = "serde")]

src/raw/document_buf/raw_writer.rs

Lines changed: 2 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,4 @@
1-
use crate::{
2-
raw::{write_cstring, write_string},
3-
spec::BinarySubtype,
4-
RawBsonRef,
5-
};
1+
use crate::{raw::write_cstring, RawBsonRef};
62

73
pub(super) struct RawWriter<'a> {
84
data: &'a mut Vec<u8>,
@@ -18,72 +14,7 @@ impl<'a> RawWriter<'a> {
1814
self.data[original_len - 1] = value.element_type() as u8;
1915

2016
write_cstring(self.data, key)?;
21-
22-
match value {
23-
RawBsonRef::Int32(i) => {
24-
self.data.extend(i.to_le_bytes());
25-
}
26-
RawBsonRef::String(s) => {
27-
write_string(self.data, s);
28-
}
29-
RawBsonRef::Document(d) => {
30-
self.data.extend(d.as_bytes());
31-
}
32-
RawBsonRef::Array(a) => {
33-
self.data.extend(a.as_bytes());
34-
}
35-
RawBsonRef::Binary(b) => {
36-
let len = b.len();
37-
self.data.extend(len.to_le_bytes());
38-
self.data.push(b.subtype.into());
39-
if let BinarySubtype::BinaryOld = b.subtype {
40-
self.data.extend((len - 4).to_le_bytes())
41-
}
42-
self.data.extend(b.bytes);
43-
}
44-
RawBsonRef::Boolean(b) => {
45-
self.data.push(b as u8);
46-
}
47-
RawBsonRef::DateTime(dt) => {
48-
self.data.extend(dt.timestamp_millis().to_le_bytes());
49-
}
50-
RawBsonRef::DbPointer(dbp) => {
51-
write_string(self.data, dbp.namespace);
52-
self.data.extend(dbp.id.bytes());
53-
}
54-
RawBsonRef::Decimal128(d) => {
55-
self.data.extend(d.bytes());
56-
}
57-
RawBsonRef::Double(d) => {
58-
self.data.extend(d.to_le_bytes());
59-
}
60-
RawBsonRef::Int64(i) => {
61-
self.data.extend(i.to_le_bytes());
62-
}
63-
RawBsonRef::RegularExpression(re) => {
64-
write_cstring(self.data, re.pattern)?;
65-
write_cstring(self.data, re.options)?;
66-
}
67-
RawBsonRef::JavaScriptCode(js) => {
68-
write_string(self.data, js);
69-
}
70-
RawBsonRef::JavaScriptCodeWithScope(code_w_scope) => {
71-
let len = code_w_scope.len();
72-
self.data.extend(len.to_le_bytes());
73-
write_string(self.data, code_w_scope.code);
74-
self.data.extend(code_w_scope.scope.as_bytes());
75-
}
76-
RawBsonRef::Timestamp(ts) => {
77-
self.data.extend(ts.to_le_bytes());
78-
}
79-
RawBsonRef::ObjectId(oid) => {
80-
self.data.extend(oid.bytes());
81-
}
82-
RawBsonRef::Symbol(s) => {
83-
write_string(self.data, s);
84-
}
85-
RawBsonRef::Null | RawBsonRef::Undefined | RawBsonRef::MinKey | RawBsonRef::MaxKey => {}
86-
}
17+
value.append_to(self.data)?;
8718

8819
// append trailing null byte
8920
self.data.push(0);

src/raw/serde/seeded_visitor.rs

Lines changed: 6 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -271,72 +271,12 @@ impl<'de> Visitor<'de> for SeededVisitor<'_, 'de> {
271271
Ok(ElementType::Array)
272272
}
273273
// Cases that don't
274-
_ => match bson.as_ref() {
275-
RawBsonRef::ObjectId(oid) => {
276-
self.buffer.append_bytes(&oid.bytes());
277-
Ok(ElementType::ObjectId)
278-
}
279-
RawBsonRef::Symbol(s) => {
280-
self.append_string(s);
281-
Ok(ElementType::Symbol)
282-
}
283-
RawBsonRef::Decimal128(d) => {
284-
self.buffer.append_bytes(&d.bytes);
285-
Ok(ElementType::Decimal128)
286-
}
287-
RawBsonRef::RegularExpression(re) => {
288-
self.append_cstring(re.pattern)
289-
.map_err(SerdeError::custom)?;
290-
self.append_cstring(re.options)
291-
.map_err(SerdeError::custom)?;
292-
Ok(ElementType::RegularExpression)
293-
}
294-
RawBsonRef::Undefined => Ok(ElementType::Undefined),
295-
RawBsonRef::DateTime(dt) => {
296-
self.buffer
297-
.append_bytes(&dt.timestamp_millis().to_le_bytes());
298-
Ok(ElementType::DateTime)
299-
}
300-
RawBsonRef::Timestamp(ts) => {
301-
self.buffer.append_bytes(&ts.increment.to_le_bytes());
302-
self.buffer.append_bytes(&ts.time.to_le_bytes());
303-
Ok(ElementType::Timestamp)
304-
}
305-
RawBsonRef::MinKey => Ok(ElementType::MinKey),
306-
RawBsonRef::MaxKey => Ok(ElementType::MaxKey),
307-
RawBsonRef::JavaScriptCode(s) => {
308-
self.append_string(s);
309-
Ok(ElementType::JavaScriptCode)
310-
}
311-
RawBsonRef::JavaScriptCodeWithScope(jsc) => {
312-
let length_index = self.pad_document_length();
313-
self.append_string(jsc.code);
314-
self.buffer.append_bytes(jsc.scope.as_bytes());
315-
316-
let length_bytes =
317-
((self.buffer.len() - length_index) as i32).to_le_bytes();
318-
self.buffer
319-
.copy_from_slice(length_index..length_index + 4, &length_bytes);
320-
321-
Ok(ElementType::JavaScriptCodeWithScope)
322-
}
323-
RawBsonRef::DbPointer(dbp) => {
324-
self.append_string(dbp.namespace);
325-
self.buffer.append_bytes(&dbp.id.bytes());
326-
Ok(ElementType::DbPointer)
327-
}
328-
RawBsonRef::Double(d) => self.visit_f64(d),
329-
RawBsonRef::String(s) => self.visit_str(s),
330-
RawBsonRef::Boolean(b) => self.visit_bool(b),
331-
RawBsonRef::Null => self.visit_none(),
332-
RawBsonRef::Int32(i) => self.visit_i32(i),
333-
RawBsonRef::Int64(i) => self.visit_i64(i),
334-
// These are always borrowed and are handled
335-
// at the top of the outer `match`.
336-
RawBsonRef::Array(_) | RawBsonRef::Document(_) | RawBsonRef::Binary(_) => {
337-
unreachable!()
338-
}
339-
},
274+
_ => {
275+
let bson = bson.as_ref();
276+
bson.append_to(self.buffer.get_owned_buffer())
277+
.map_err(A::Error::custom)?;
278+
Ok(bson.element_type())
279+
}
340280
}
341281
}
342282
MapParse::Aggregate(first_key) => {

src/ser.rs

Lines changed: 0 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -30,68 +30,15 @@ pub use self::{
3030
serde::Serializer,
3131
};
3232

33-
use std::io::Write;
34-
3533
#[rustfmt::skip]
3634
use ::serde::{ser::Error as SerdeError, Serialize};
3735

3836
use crate::{
3937
bson::{Bson, Document},
40-
de::MAX_BSON_SIZE,
4138
ser::serde::SerializerOptions,
42-
spec::BinarySubtype,
4339
RawDocumentBuf,
4440
};
4541

46-
#[inline]
47-
pub(crate) fn write_i32<W: Write + ?Sized>(writer: &mut W, val: i32) -> Result<()> {
48-
writer
49-
.write_all(&val.to_le_bytes())
50-
.map(|_| ())
51-
.map_err(From::from)
52-
}
53-
54-
#[inline]
55-
fn write_i64<W: Write + ?Sized>(writer: &mut W, val: i64) -> Result<()> {
56-
writer
57-
.write_all(&val.to_le_bytes())
58-
.map(|_| ())
59-
.map_err(From::from)
60-
}
61-
62-
#[inline]
63-
fn write_f64<W: Write + ?Sized>(writer: &mut W, val: f64) -> Result<()> {
64-
writer
65-
.write_all(&val.to_le_bytes())
66-
.map(|_| ())
67-
.map_err(From::from)
68-
}
69-
70-
#[inline]
71-
fn write_binary<W: Write>(mut writer: W, bytes: &[u8], subtype: BinarySubtype) -> Result<()> {
72-
let len = if let BinarySubtype::BinaryOld = subtype {
73-
bytes.len() + 4
74-
} else {
75-
bytes.len()
76-
};
77-
78-
if len > MAX_BSON_SIZE as usize {
79-
return Err(Error::custom(format!(
80-
"binary length {} exceeded maximum size",
81-
bytes.len()
82-
)));
83-
}
84-
85-
write_i32(&mut writer, len as i32)?;
86-
writer.write_all(&[subtype.into()])?;
87-
88-
if let BinarySubtype::BinaryOld = subtype {
89-
write_i32(&mut writer, len as i32 - 4)?;
90-
};
91-
92-
writer.write_all(bytes).map_err(From::from)
93-
}
94-
9542
/// Encode a `T` Serializable into a [`Bson`] value.
9643
///
9744
/// The [`Serializer`] used by this function presents itself as human readable, whereas the

0 commit comments

Comments
 (0)