1mod vector;
4
5use std::fmt::{self, Display};
6
7use crate::{
8 base64,
9 error::{Error, Result},
10 spec::BinarySubtype,
11 RawBinaryRef,
12};
13
14pub use vector::{PackedBitVector, Vector};
15
16#[derive(Debug, Clone, Eq, PartialEq, Hash)]
18pub struct Binary {
19 pub subtype: BinarySubtype,
21
22 pub bytes: Vec<u8>,
24}
25
26impl Display for Binary {
27 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
28 write!(
29 fmt,
30 "Binary({:#x}, {})",
31 u8::from(self.subtype),
32 base64::encode(&self.bytes)
33 )
34 }
35}
36
37impl Binary {
38 pub fn from_base64(
53 input: impl AsRef<str>,
54 subtype: impl Into<Option<BinarySubtype>>,
55 ) -> Result<Self> {
56 let bytes = base64::decode(input.as_ref()).map_err(Error::binary)?;
57 let subtype = match subtype.into() {
58 Some(s) => s,
59 None => BinarySubtype::Generic,
60 };
61 Ok(Binary { subtype, bytes })
62 }
63
64 #[cfg(feature = "serde")]
65 pub(crate) fn from_extended_doc(doc: &crate::Document) -> Option<Self> {
66 use std::convert::TryFrom;
67
68 let binary_doc = doc.get_document("$binary").ok()?;
69
70 if let Ok(bytes) = binary_doc.get_str("base64") {
71 let bytes = base64::decode(bytes).ok()?;
72 let subtype = binary_doc.get_str("subType").ok()?;
73 let subtype = hex::decode(subtype).ok()?;
74 if subtype.len() == 1 {
75 Some(Self {
76 bytes,
77 subtype: subtype[0].into(),
78 })
79 } else {
80 None
81 }
82 } else {
83 let binary = binary_doc.get_binary_generic("bytes").ok()?;
86 let subtype = binary_doc.get_i32("subType").ok()?;
87
88 Some(Self {
89 bytes: binary.clone(),
90 subtype: u8::try_from(subtype).ok()?.into(),
91 })
92 }
93 }
94
95 pub fn as_raw_binary(&self) -> RawBinaryRef<'_> {
97 RawBinaryRef {
98 bytes: self.bytes.as_slice(),
99 subtype: self.subtype,
100 }
101 }
102}