1use core::convert::Infallible;
14use core::num::TryFromIntError;
15
16use encode::combinators::{FromError, Iter, LengthPrefix, LE};
17use encode::encoders::InsufficientSpace;
18use encode::{Encodable, EncodableSize};
19
20#[derive(Debug, Clone, PartialEq)]
29pub enum BsonError {
30 TooLarge(TryFromIntError),
31 InsufficientSpace(InsufficientSpace),
32}
33
34impl core::error::Error for BsonError {}
35impl core::fmt::Display for BsonError {
36 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
37 match self {
38 BsonError::TooLarge(_) => write!(f, "failed to encode BSON because it is too large"),
39 BsonError::InsufficientSpace(err) => core::fmt::Display::fmt(err, f),
40 }
41 }
42}
43impl From<TryFromIntError> for BsonError {
44 fn from(err: TryFromIntError) -> Self {
45 BsonError::TooLarge(err)
46 }
47}
48impl From<InsufficientSpace> for BsonError {
49 fn from(err: InsufficientSpace) -> Self {
50 BsonError::InsufficientSpace(err)
51 }
52}
53impl From<Infallible> for BsonError {
54 fn from(_: Infallible) -> Self {
55 unreachable!("infallible cannot be constructed")
56 }
57}
58
59#[derive(Debug, Clone, PartialEq)]
61pub struct BsonDocument {
62 pub e_list: Vec<BsonElement>,
64}
65
66impl<Encoder> Encodable<Encoder> for BsonDocument
67where
68 Encoder: encode::ByteEncoder,
69 BsonError: From<Encoder::Error>,
70{
71 type Error = BsonError;
72
73 fn encode(&self, encoder: &mut Encoder) -> Result<(), Self::Error> {
74 let document = (
75 Iter::new(&self.e_list),
76 FromError::<_, Self::Error>::new(0u8),
79 );
80 let size = document.encoded_size()? + (i32::BITS / 8) as usize;
83 LE::<i32>::try_from(size)?.encode(encoder)?;
84 document.encode(encoder)?;
85 Ok(())
86 }
87}
88
89#[derive(Debug, Clone, PartialEq)]
90pub struct BsonElement {
91 pub e_value: String,
93 pub variant: BsonElementVariant,
95}
96
97#[derive(Debug, Clone, PartialEq)]
98pub enum BsonElementVariant {
99 Double(f64),
100 String(String),
101 Document(BsonDocument),
102 Array(BsonDocument),
103 Binary { subtype: u8, data: Vec<u8> },
104 Undefined,
105 ObjectId([u8; 12]),
106 Boolean(bool),
107 DateTime(i64),
108 Null,
109 Regex(String, String),
110 DBPointer(String, [u8; 12]),
111 JavaScriptCode(String),
112 Symbol(String),
113 JavaScriptCodeWithScope(String, BsonDocument),
114 Int32(i32),
115 Int64(i64),
116 Timestamp(u64),
117 Decimal128([u8; 16]), MinKey,
119 MaxKey,
120}
121
122impl<Encoder> Encodable<Encoder> for BsonElement
123where
124 Encoder: encode::ByteEncoder,
125 BsonError: From<Encoder::Error>,
126{
127 type Error = BsonError;
128
129 fn encode(&self, encoder: &mut Encoder) -> Result<(), Self::Error> {
130 let e_name = (&self.e_value, 0u8);
131
132 match &self.variant {
133 BsonElementVariant::Double(x) => (1i8, e_name, LE::new(*x)).encode(encoder)?,
136 BsonElementVariant::String(x) => {
139 2i8.encode(encoder)?;
140 e_name.encode(encoder)?;
141 BsonString(x).encode(encoder)?;
142 }
143 BsonElementVariant::Document(x) => {
144 3i8.encode(encoder)?;
145 e_name.encode(encoder)?;
146 x.encode(encoder)?;
147 }
148 BsonElementVariant::Array(x) => {
149 4i8.encode(encoder)?;
150 e_name.encode(encoder)?;
151 x.encode(encoder)?;
152 }
153 BsonElementVariant::Binary { subtype, data } => {
154 (5i8, e_name, LE::<i32>::try_from(data.len())?, subtype, data).encode(encoder)?
155 }
156 BsonElementVariant::Undefined => (6i8, e_name).encode(encoder)?,
157 BsonElementVariant::ObjectId(x) => (7i8, e_name, x).encode(encoder)?,
158 BsonElementVariant::Boolean(x) => (8i8, e_name, x).encode(encoder)?,
159 BsonElementVariant::DateTime(x) => (9i8, e_name, LE::new(*x)).encode(encoder)?,
160 BsonElementVariant::Null => (10i8, e_name).encode(encoder)?,
161 BsonElementVariant::Regex(x, y) => (11i8, e_name, x, 0u8, y, 0u8).encode(encoder)?,
162 BsonElementVariant::DBPointer(x, y) => {
163 (12i8, e_name).encode(encoder)?;
164 BsonString(x).encode(encoder)?;
165 y.encode(encoder)?;
166 }
167 BsonElementVariant::JavaScriptCode(x) => (13i8, e_name, x).encode(encoder)?,
168 BsonElementVariant::Symbol(x) => {
169 (14i8, e_name).encode(encoder)?;
170 BsonString(x).encode(encoder)?;
171 }
172 BsonElementVariant::JavaScriptCodeWithScope(x, y) => {
173 (15i8, e_name).encode(encoder)?;
174 let content = (BsonString(x), y);
175 let len = content.encoded_size()? + (i32::BITS / 8) as usize;
178 LE::<i32>::try_from(len)?.encode(encoder)?;
179 content.encode(encoder)?;
180 }
181 BsonElementVariant::Int32(x) => (16i8, e_name, LE::new(*x)).encode(encoder)?,
182 BsonElementVariant::Timestamp(x) => (17i8, e_name, LE::new(*x)).encode(encoder)?,
183 BsonElementVariant::Int64(x) => (18i8, e_name, LE::new(*x)).encode(encoder)?,
184 BsonElementVariant::Decimal128(x) => (19i8, e_name, x).encode(encoder)?,
185 BsonElementVariant::MinKey => (-1i8, e_name).encode(encoder)?,
186 BsonElementVariant::MaxKey => (127i8, e_name).encode(encoder)?,
187 };
188 Ok(())
189 }
190}
191
192struct BsonString<S>(S);
193
194impl<S, Encoder> Encodable<Encoder> for BsonString<S>
195where
196 S: AsRef<str>,
197 Encoder: encode::ByteEncoder,
198 BsonError: From<Encoder::Error>,
199{
200 type Error = BsonError;
201
202 fn encode(&self, encoder: &mut Encoder) -> Result<(), Self::Error> {
203 LengthPrefix::<_, LE<i32>, BsonError>::new((self.0.as_ref(), 0u8)).encode(encoder)?;
204 Ok(())
205 }
206}
207
208fn main() -> Result<(), BsonError> {
209 let document = BsonDocument {
210 e_list: vec![
211 BsonElement {
212 e_value: "hello".into(),
213 variant: BsonElementVariant::Double(1.0),
214 },
215 BsonElement {
216 e_value: "world".into(),
217 variant: BsonElementVariant::String("hello".into()),
218 },
219 BsonElement {
220 e_value: "sub document".into(),
221 variant: BsonElementVariant::Document(BsonDocument {
222 e_list: vec![BsonElement {
223 e_value: "hello".into(),
224 variant: BsonElementVariant::Double(1.0),
225 }],
226 }),
227 },
228 BsonElement {
229 e_value: "array".into(),
230 variant: BsonElementVariant::Array(BsonDocument {
231 e_list: vec![BsonElement {
232 e_value: "0".into(), variant: BsonElementVariant::Double(1.0),
234 }],
235 }),
236 },
237 ],
238 };
239 let size = document.encoded_size()?;
240 println!("Expected BSON size: {}", size);
241
242 let mut buf = Vec::with_capacity(size);
245 document.encode(&mut buf)?;
246
247 println!("{:?}", document);
248 println!("{:?}", buf.as_slice());
249 Ok(())
250}
251
252#[cfg(test)]
253mod official_examples {
254 use super::*;
256
257 #[test]
258 fn assert_that_hello_world_example_is_encoded_right() {
259 let expected = b"\x16\x00\x00\x00\x02hello\x00\x06\x00\x00\x00world\x00\x00";
261 let document = BsonDocument {
262 e_list: vec![BsonElement {
263 e_value: "hello".into(),
264 variant: BsonElementVariant::String("world".into()),
265 }],
266 };
267
268 let mut buf = Vec::new();
269 document.encode(&mut buf).unwrap();
270
271 assert_eq!(buf.as_slice(), expected);
272 }
273 #[test]
274 fn assert_that_awesome_example_is_encoded_right() {
275 let expected = b"\x31\x00\x00\x00\x04BSON\x00\x26\x00\x00\x00\x02\x30\x00\x08\x00\x00\x00awesome\x00\x01\x31\x00\x33\x33\x33\x33\x33\x33\x14\x40\x10\x32\x00\xc2\x07\x00\x00\x00\x00";
277 let document = BsonDocument {
278 e_list: vec![BsonElement {
279 e_value: "BSON".into(),
280 variant: BsonElementVariant::Array(BsonDocument {
281 e_list: vec![
282 BsonElement {
283 e_value: "0".into(),
284 variant: BsonElementVariant::String("awesome".into()),
285 },
286 BsonElement {
287 e_value: "1".into(),
288 variant: BsonElementVariant::Double(5.05),
289 },
290 BsonElement {
291 e_value: "2".into(),
292 variant: BsonElementVariant::Int32(1986),
293 },
294 ],
295 }),
296 }],
297 };
298
299 let mut buf = Vec::new();
300 document.encode(&mut buf).unwrap();
301
302 assert_eq!(buf.as_slice(), expected);
303 }
304}