Skip to content

Commit f896bf9

Browse files
committed
create binary error type
1 parent f940c01 commit f896bf9

File tree

7 files changed

+108
-79
lines changed

7 files changed

+108
-79
lines changed

src/binary.rs

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
pub mod error;
2+
use std::fmt::{self, Display};
3+
use crate::{spec::BinarySubtype, RawBinaryRef, Document, binary::error::{Result, Error}};
4+
use std::convert::TryFrom;
5+
6+
/// Represents a BSON binary value.
7+
#[derive(Debug, Clone, PartialEq)]
8+
pub struct Binary {
9+
/// The subtype of the bytes.
10+
pub subtype: BinarySubtype,
11+
12+
/// The binary bytes.
13+
pub bytes: Vec<u8>,
14+
}
15+
16+
impl Display for Binary {
17+
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
18+
write!(
19+
fmt,
20+
"Binary({:#x}, {})",
21+
u8::from(self.subtype),
22+
base64::encode(&self.bytes)
23+
)
24+
}
25+
}
26+
27+
impl Binary {
28+
/// Creates a [`Binary`] from a base64 string and optional [`BinarySubtype`]. If the
29+
/// `subtype` argument is `None`, the [`Binary`] constructed will default to
30+
/// [`BinarySubtype::Generic`].
31+
pub fn from_base64(
32+
input: &str,
33+
subtype: impl Into<Option<BinarySubtype>>,
34+
) -> Result<Self> {
35+
let bytes = base64::decode(input).map_err(|_| Error::DecodingError)?;
36+
let subtype = match subtype.into() {
37+
Some(s) => s,
38+
None => BinarySubtype::Generic,
39+
};
40+
Ok(Binary { subtype, bytes })
41+
}
42+
43+
pub(crate) fn from_extended_doc(doc: &Document) -> Option<Self> {
44+
let binary_doc = doc.get_document("$binary").ok()?;
45+
46+
if let Ok(bytes) = binary_doc.get_str("base64") {
47+
let bytes = base64::decode(bytes).ok()?;
48+
let subtype = binary_doc.get_str("subType").ok()?;
49+
let subtype = hex::decode(subtype).ok()?;
50+
if subtype.len() == 1 {
51+
Some(Self {
52+
bytes,
53+
subtype: subtype[0].into(),
54+
})
55+
} else {
56+
None
57+
}
58+
} else {
59+
// in non-human-readable mode, RawBinary will serialize as
60+
// { "$binary": { "bytes": <bytes>, "subType": <i32> } };
61+
let binary = binary_doc.get_binary_generic("bytes").ok()?;
62+
let subtype = binary_doc.get_i32("subType").ok()?;
63+
64+
Some(Self {
65+
bytes: binary.clone(),
66+
subtype: u8::try_from(subtype).ok()?.into(),
67+
})
68+
}
69+
}
70+
71+
pub(crate) fn as_raw_binary(&self) -> RawBinaryRef<'_> {
72+
RawBinaryRef {
73+
bytes: self.bytes.as_slice(),
74+
subtype: self.subtype,
75+
}
76+
}
77+
}

src/binary/error.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
use std::{error, fmt};
2+
3+
/// Possible errors that can arise during [`Binary`] construction.
4+
#[derive(Clone, Debug)]
5+
#[non_exhaustive]
6+
pub enum Error {
7+
/// While trying to decode from base64, an error was returned.
8+
DecodingError,
9+
}
10+
11+
impl error::Error for Error {}
12+
13+
impl std::fmt::Display for Error {
14+
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
15+
match *self {
16+
Error::DecodingError => fmt.write_str("couldn't decode to binary"),
17+
}
18+
}
19+
}
20+
21+
pub type Result<T> = std::result::Result<T, Error>;

src/bson.rs

Lines changed: 1 addition & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -26,15 +26,14 @@ use std::{
2626
fmt::{self, Debug, Display, Formatter},
2727
};
2828

29-
use base64::DecodeError;
3029
use serde_json::{json, Value};
3130

3231
pub use crate::document::Document;
3332
use crate::{
3433
oid::{self, ObjectId},
3534
spec::{BinarySubtype, ElementType},
3635
Decimal128,
37-
RawBinaryRef,
36+
binary::Binary,
3837
};
3938

4039
/// Possible BSON value types.
@@ -1081,79 +1080,6 @@ impl Display for JavaScriptCodeWithScope {
10811080
}
10821081
}
10831082

1084-
/// Represents a BSON binary value.
1085-
#[derive(Debug, Clone, PartialEq)]
1086-
pub struct Binary {
1087-
/// The subtype of the bytes.
1088-
pub subtype: BinarySubtype,
1089-
1090-
/// The binary bytes.
1091-
pub bytes: Vec<u8>,
1092-
}
1093-
1094-
impl Display for Binary {
1095-
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
1096-
write!(
1097-
fmt,
1098-
"Binary({:#x}, {})",
1099-
u8::from(self.subtype),
1100-
base64::encode(&self.bytes)
1101-
)
1102-
}
1103-
}
1104-
1105-
impl Binary {
1106-
/// Creates a [`Binary`] from a base64 string and optional [`BinarySubtype`]. If the
1107-
/// `subtype` argument is `None`, the [`Binary`] constructed will default to
1108-
/// [`BinarySubtype::Generic`].
1109-
pub fn from_base64(
1110-
input: &str,
1111-
subtype: impl Into<Option<BinarySubtype>>,
1112-
) -> Result<Self, DecodeError> {
1113-
let bytes = base64::decode(input)?;
1114-
let subtype = match subtype.into() {
1115-
Some(s) => s,
1116-
None => BinarySubtype::Generic,
1117-
};
1118-
Ok(Binary { subtype, bytes })
1119-
}
1120-
1121-
pub(crate) fn from_extended_doc(doc: &Document) -> Option<Self> {
1122-
let binary_doc = doc.get_document("$binary").ok()?;
1123-
1124-
if let Ok(bytes) = binary_doc.get_str("base64") {
1125-
let bytes = base64::decode(bytes).ok()?;
1126-
let subtype = binary_doc.get_str("subType").ok()?;
1127-
let subtype = hex::decode(subtype).ok()?;
1128-
if subtype.len() == 1 {
1129-
Some(Self {
1130-
bytes,
1131-
subtype: subtype[0].into(),
1132-
})
1133-
} else {
1134-
None
1135-
}
1136-
} else {
1137-
// in non-human-readable mode, RawBinary will serialize as
1138-
// { "$binary": { "bytes": <bytes>, "subType": <i32> } };
1139-
let binary = binary_doc.get_binary_generic("bytes").ok()?;
1140-
let subtype = binary_doc.get_i32("subType").ok()?;
1141-
1142-
Some(Self {
1143-
bytes: binary.clone(),
1144-
subtype: u8::try_from(subtype).ok()?.into(),
1145-
})
1146-
}
1147-
}
1148-
1149-
pub(crate) fn as_raw_binary(&self) -> RawBinaryRef<'_> {
1150-
RawBinaryRef {
1151-
bytes: self.bytes.as_slice(),
1152-
subtype: self.subtype,
1153-
}
1154-
}
1155-
}
1156-
11571083
/// Represents a DBPointer. (Deprecated)
11581084
#[derive(Debug, Clone, PartialEq)]
11591085
pub struct DbPointer {

src/de/mod.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,8 @@ pub use self::{
3333
use std::io::Read;
3434

3535
use crate::{
36-
bson::{Array, Binary, Bson, DbPointer, Document, JavaScriptCodeWithScope, Regex, Timestamp},
36+
bson::{Array, Bson, DbPointer, Document, JavaScriptCodeWithScope, Regex, Timestamp},
37+
binary::Binary,
3738
oid::{self, ObjectId},
3839
raw::RawBinaryRef,
3940
ser::write_i32,

src/de/serde.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@ use serde::de::{
2121
use serde_bytes::ByteBuf;
2222

2323
use crate::{
24-
bson::{Binary, Bson, DbPointer, JavaScriptCodeWithScope, Regex, Timestamp},
24+
bson::{Bson, DbPointer, JavaScriptCodeWithScope, Regex, Timestamp},
25+
binary::Binary,
2526
datetime::DateTime,
2627
document::{Document, IntoIter},
2728
oid::ObjectId,

src/document.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,9 @@ use indexmap::IndexMap;
1313
use serde::de::Error;
1414

1515
use crate::{
16-
bson::{Array, Binary, Bson, Timestamp},
16+
bson::{Array, Bson, Timestamp},
1717
de::{deserialize_bson_kvp, ensure_read_exactly, read_i32, MIN_BSON_DOCUMENT_SIZE},
18+
binary::Binary,
1819
oid::ObjectId,
1920
ser::{serialize_bson, write_i32},
2021
spec::BinarySubtype,

src/lib.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -269,8 +269,9 @@
269269

270270
#[doc(inline)]
271271
pub use self::{
272-
bson::{Array, Binary, Bson, DbPointer, Document, JavaScriptCodeWithScope, Regex, Timestamp},
272+
bson::{Array, Bson, DbPointer, Document, JavaScriptCodeWithScope, Regex, Timestamp},
273273
datetime::DateTime,
274+
binary::Binary,
274275
de::{
275276
from_bson, from_bson_with_options, from_document, from_document_with_options, from_reader,
276277
from_reader_utf8_lossy, from_slice, from_slice_utf8_lossy, Deserializer,
@@ -291,6 +292,7 @@ pub use self::{
291292
#[macro_use]
292293
mod macros;
293294
mod bson;
295+
pub mod binary;
294296
pub mod datetime;
295297
pub mod de;
296298
pub mod decimal128;

0 commit comments

Comments
 (0)