Skip to content

Commit 11cd91b

Browse files
RUST-2003 Binary vector subtype support
1 parent 04d1549 commit 11cd91b

File tree

7 files changed

+83
-9
lines changed

7 files changed

+83
-9
lines changed

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ criterion = "0.3.0"
8282
pretty_assertions = "0.6.1"
8383
proptest = "1.0.0"
8484
serde_bytes = "0.11"
85+
serde_path_to_error = "0.1.16"
8586
chrono = { version = "0.4", features = ["serde", "clock", "std"], default-features = false }
8687
[target.'cfg(all(target_arch = "wasm32", target_os = "unknown"))'.dev-dependencies]
8788
getrandom = { version = "0.2", features = ["js"] }

src/binary.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,16 @@
1+
#! Module containing functionality related to BSON binary values.
2+
3+
mod vector;
4+
15
use crate::{spec::BinarySubtype, Document, RawBinaryRef};
26
use std::{
37
convert::TryFrom,
48
error,
59
fmt::{self, Display},
610
};
711

12+
pub use vector::{PackedBitVector, Vector};
13+
814
/// Represents a BSON binary value.
915
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
1016
pub struct Binary {
@@ -98,14 +104,18 @@ impl Binary {
98104
pub enum Error {
99105
/// While trying to decode from base64, an error was returned.
100106
DecodingError { message: String },
107+
108+
/// Invalid bytes were provided to construct a [`Binary`] of subtype [`BinarySubtype::Vector`].
109+
Vector { message: String },
101110
}
102111

103112
impl error::Error for Error {}
104113

105114
impl std::fmt::Display for Error {
106115
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
107116
match self {
108-
Error::DecodingError { message: m } => fmt.write_str(m),
117+
Error::DecodingError { message } => fmt.write_str(message),
118+
Error::Vector { message } => fmt.write_str(message),
109119
}
110120
}
111121
}

src/spec.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ const BINARY_SUBTYPE_MD5: u8 = 0x05;
6262
const BINARY_SUBTYPE_ENCRYPTED: u8 = 0x06;
6363
const BINARY_SUBTYPE_COLUMN: u8 = 0x07;
6464
const BINARY_SUBTYPE_SENSITIVE: u8 = 0x08;
65+
const BINARY_SUBTYPE_VECTOR: u8 = 0x09;
6566
const BINARY_SUBTYPE_USER_DEFINED: u8 = 0x80;
6667

6768
/// All available BSON element types.
@@ -162,6 +163,7 @@ pub enum BinarySubtype {
162163
Encrypted,
163164
Column,
164165
Sensitive,
166+
Vector,
165167
UserDefined(u8),
166168
Reserved(u8),
167169
}
@@ -179,6 +181,7 @@ impl From<BinarySubtype> for u8 {
179181
BinarySubtype::Encrypted => BINARY_SUBTYPE_ENCRYPTED,
180182
BinarySubtype::Column => BINARY_SUBTYPE_COLUMN,
181183
BinarySubtype::Sensitive => BINARY_SUBTYPE_SENSITIVE,
184+
BinarySubtype::Vector => BINARY_SUBTYPE_VECTOR,
182185
BinarySubtype::UserDefined(x) => x,
183186
BinarySubtype::Reserved(x) => x,
184187
}
@@ -198,6 +201,7 @@ impl From<u8> for BinarySubtype {
198201
BINARY_SUBTYPE_ENCRYPTED => BinarySubtype::Encrypted,
199202
BINARY_SUBTYPE_COLUMN => BinarySubtype::Column,
200203
BINARY_SUBTYPE_SENSITIVE => BinarySubtype::Sensitive,
204+
BINARY_SUBTYPE_VECTOR => BinarySubtype::Vector,
201205
_ if t < BINARY_SUBTYPE_USER_DEFINED => BinarySubtype::Reserved(t),
202206
_ => BinarySubtype::UserDefined(t),
203207
}

src/tests/spec/json/bson-corpus/binary.json

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,36 @@
7474
"description": "$type query operator (conflicts with legacy $binary form with $type field)",
7575
"canonical_bson": "180000000378001000000010247479706500020000000000",
7676
"canonical_extjson": "{\"x\" : { \"$type\" : {\"$numberInt\": \"2\"}}}"
77+
},
78+
{
79+
"description": "subtype 0x09 Vector FLOAT32",
80+
"canonical_bson": "170000000578000A0000000927000000FE420000E04000",
81+
"canonical_extjson": "{\"x\": {\"$binary\": {\"base64\": \"JwAAAP5CAADgQA==\", \"subType\": \"09\"}}}"
82+
},
83+
{
84+
"description": "subtype 0x09 Vector INT8",
85+
"canonical_bson": "11000000057800040000000903007F0700",
86+
"canonical_extjson": "{\"x\": {\"$binary\": {\"base64\": \"AwB/Bw==\", \"subType\": \"09\"}}}"
87+
},
88+
{
89+
"description": "subtype 0x09 Vector PACKED_BIT",
90+
"canonical_bson": "11000000057800040000000910007F0700",
91+
"canonical_extjson": "{\"x\": {\"$binary\": {\"base64\": \"EAB/Bw==\", \"subType\": \"09\"}}}"
92+
},
93+
{
94+
"description": "subtype 0x09 Vector (Zero-length) FLOAT32",
95+
"canonical_bson": "0F0000000578000200000009270000",
96+
"canonical_extjson": "{\"x\": {\"$binary\": {\"base64\": \"JwA=\", \"subType\": \"09\"}}}"
97+
},
98+
{
99+
"description": "subtype 0x09 Vector (Zero-length) INT8",
100+
"canonical_bson": "0F0000000578000200000009030000",
101+
"canonical_extjson": "{\"x\": {\"$binary\": {\"base64\": \"AwA=\", \"subType\": \"09\"}}}"
102+
},
103+
{
104+
"description": "subtype 0x09 Vector (Zero-length) PACKED_BIT",
105+
"canonical_bson": "0F0000000578000200000009100000",
106+
"canonical_extjson": "{\"x\": {\"$binary\": {\"base64\": \"EAA=\", \"subType\": \"09\"}}}"
77107
}
78108
],
79109
"decodeErrors": [

src/tests/spec/json/bson-corpus/datetime.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
{
2525
"description" : "Y10K",
2626
"canonical_bson" : "1000000009610000DC1FD277E6000000",
27+
"relaxed_extjson" : "{\"a\":{\"$date\":{\"$numberLong\":\"253402300800000\"}}}",
2728
"canonical_extjson" : "{\"a\":{\"$date\":{\"$numberLong\":\"253402300800000\"}}}"
2829
},
2930
{

src/tests/spec/json/bson-corpus/decimal128-1.json

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -312,6 +312,30 @@
312312
"canonical_bson": "18000000136400000000000a5bc138938d44c64d31cc3700",
313313
"degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\"}}",
314314
"canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.000000000000000000000000000000000E+999\"}}"
315+
},
316+
{
317+
"description": "Clamped zeros with a large positive exponent",
318+
"canonical_bson": "180000001364000000000000000000000000000000FE5F00",
319+
"degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"0E+2147483647\"}}",
320+
"canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0E+6111\"}}"
321+
},
322+
{
323+
"description": "Clamped zeros with a large negative exponent",
324+
"canonical_bson": "180000001364000000000000000000000000000000000000",
325+
"degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"0E-2147483647\"}}",
326+
"canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0E-6176\"}}"
327+
},
328+
{
329+
"description": "Clamped negative zeros with a large positive exponent",
330+
"canonical_bson": "180000001364000000000000000000000000000000FEDF00",
331+
"degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"-0E+2147483647\"}}",
332+
"canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-0E+6111\"}}"
333+
},
334+
{
335+
"description": "Clamped negative zeros with a large negative exponent",
336+
"canonical_bson": "180000001364000000000000000000000000000000008000",
337+
"degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"-0E-2147483647\"}}",
338+
"canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-0E-6176\"}}"
315339
}
316340
]
317341
}

src/tests/spec/mod.rs

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
mod corpus;
2+
mod vector;
23

34
use std::{
45
any::type_name,
@@ -7,7 +8,7 @@ use std::{
78
path::PathBuf,
89
};
910

10-
use crate::RawDocumentBuf;
11+
use crate::Bson;
1112
use serde::de::DeserializeOwned;
1213

1314
pub(crate) fn run_spec_test<T, F>(spec: &[&str], run_test_file: F)
@@ -31,13 +32,16 @@ where
3132
let file = File::open(&path)
3233
.unwrap_or_else(|e| panic!("Failed to open file at {:?}: {}", path, e));
3334

34-
let test_bson: RawDocumentBuf = serde_json::from_reader(file).unwrap_or_else(|e| {
35-
panic!(
36-
"Failed to deserialize test JSON to BSON in {:?}: {}",
37-
path, e
38-
)
39-
});
40-
let test: T = crate::from_slice(test_bson.as_bytes()).unwrap_or_else(|e| {
35+
let mut json_deserializer = serde_json::Deserializer::from_reader(file);
36+
let test_bson: Bson = serde_path_to_error::deserialize(&mut json_deserializer)
37+
.unwrap_or_else(|e| {
38+
panic!(
39+
"Failed to deserialize test JSON to BSON in {:?}: {}",
40+
path, e
41+
)
42+
});
43+
let bson_deserializer = crate::Deserializer::new(test_bson);
44+
let test: T = serde_path_to_error::deserialize(bson_deserializer).unwrap_or_else(|e| {
4145
panic!(
4246
"Failed to deserialize test BSON to {} in {:?}: {}",
4347
type_name::<T>(),

0 commit comments

Comments
 (0)