/src/bson-rust/src/bson.rs
Line | Count | Source (jump to first uncovered line) |
1 | | // The MIT License (MIT) |
2 | | |
3 | | // Copyright (c) 2015 Y. T. Chung <zonyitoo@gmail.com> |
4 | | |
5 | | // Permission is hereby granted, free of charge, to any person obtaining a copy of |
6 | | // this software and associated documentation files (the "Software"), to deal in |
7 | | // the Software without restriction, including without limitation the rights to |
8 | | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of |
9 | | // the Software, and to permit persons to whom the Software is furnished to do so, |
10 | | // subject to the following conditions: |
11 | | |
12 | | // The above copyright notice and this permission notice shall be included in all |
13 | | // copies or substantial portions of the Software. |
14 | | |
15 | | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
16 | | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS |
17 | | // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR |
18 | | // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER |
19 | | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN |
20 | | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
21 | | |
22 | | //! BSON definition |
23 | | |
24 | | use std::{ |
25 | | collections::HashSet, |
26 | | convert::TryFrom, |
27 | | fmt::{self, Debug, Display, Formatter}, |
28 | | hash::Hash, |
29 | | ops::Index, |
30 | | }; |
31 | | |
32 | | pub use crate::document::Document; |
33 | | use crate::{ |
34 | | oid, |
35 | | raw::{doc_writer::DocWriter, CString}, |
36 | | spec::ElementType, |
37 | | Binary, |
38 | | Decimal128, |
39 | | RawBsonRef, |
40 | | }; |
41 | | |
42 | | /// Possible BSON value types. |
43 | | #[derive(Clone, Default, PartialEq)] |
44 | | pub enum Bson { |
45 | | /// 64-bit binary floating point |
46 | | Double(f64), |
47 | | /// UTF-8 string |
48 | | String(String), |
49 | | /// Array |
50 | | Array(Array), |
51 | | /// Embedded document |
52 | | Document(Document), |
53 | | /// Boolean value |
54 | | Boolean(bool), |
55 | | /// Null value |
56 | | #[default] |
57 | | Null, |
58 | | /// Regular expression |
59 | | RegularExpression(Regex), |
60 | | /// JavaScript code |
61 | | JavaScriptCode(String), |
62 | | /// JavaScript code w/ scope |
63 | | JavaScriptCodeWithScope(JavaScriptCodeWithScope), |
64 | | /// 32-bit signed integer |
65 | | Int32(i32), |
66 | | /// 64-bit signed integer |
67 | | Int64(i64), |
68 | | /// Timestamp |
69 | | Timestamp(Timestamp), |
70 | | /// Binary data |
71 | | Binary(Binary), |
72 | | /// [ObjectId](http://dochub.mongodb.org/core/objectids) |
73 | | ObjectId(oid::ObjectId), |
74 | | /// UTC datetime |
75 | | DateTime(crate::DateTime), |
76 | | /// Symbol (Deprecated) |
77 | | Symbol(String), |
78 | | /// [128-bit decimal floating point](https://github.com/mongodb/specifications/blob/master/source/bson-decimal128/decimal128.rst) |
79 | | Decimal128(Decimal128), |
80 | | /// Undefined value (Deprecated) |
81 | | Undefined, |
82 | | /// Max key |
83 | | MaxKey, |
84 | | /// Min key |
85 | | MinKey, |
86 | | /// DBPointer (Deprecated) |
87 | | DbPointer(DbPointer), |
88 | | } |
89 | | |
90 | | /// Alias for `Vec<Bson>`. |
91 | | pub type Array = Vec<Bson>; |
92 | | |
93 | | impl Hash for Bson { |
94 | 0 | fn hash<H: std::hash::Hasher>(&self, state: &mut H) { |
95 | 0 | match self { |
96 | 0 | Bson::Double(double) => { |
97 | 0 | if *double == 0.0_f64 { |
98 | 0 | // There are 2 zero representations, +0 and -0, which |
99 | 0 | // compare equal but have different bits. We use the +0 hash |
100 | 0 | // for both so that hash(+0) == hash(-0). |
101 | 0 | 0.0_f64.to_bits().hash(state); |
102 | 0 | } else { |
103 | 0 | double.to_bits().hash(state); |
104 | 0 | } |
105 | | } |
106 | 0 | Bson::String(x) => x.hash(state), |
107 | 0 | Bson::Array(x) => x.hash(state), |
108 | 0 | Bson::Document(x) => x.hash(state), |
109 | 0 | Bson::Boolean(x) => x.hash(state), |
110 | 0 | Bson::RegularExpression(x) => x.hash(state), |
111 | 0 | Bson::JavaScriptCode(x) => x.hash(state), |
112 | 0 | Bson::JavaScriptCodeWithScope(x) => x.hash(state), |
113 | 0 | Bson::Int32(x) => x.hash(state), |
114 | 0 | Bson::Int64(x) => x.hash(state), |
115 | 0 | Bson::Timestamp(x) => x.hash(state), |
116 | 0 | Bson::Binary(x) => x.hash(state), |
117 | 0 | Bson::ObjectId(x) => x.hash(state), |
118 | 0 | Bson::DateTime(x) => x.hash(state), |
119 | 0 | Bson::Symbol(x) => x.hash(state), |
120 | 0 | Bson::Decimal128(x) => x.hash(state), |
121 | 0 | Bson::DbPointer(x) => x.hash(state), |
122 | 0 | Bson::Null | Bson::Undefined | Bson::MaxKey | Bson::MinKey => (), |
123 | | } |
124 | 0 | } |
125 | | } |
126 | | |
127 | | impl Eq for Bson {} |
128 | | |
129 | | impl Display for Bson { |
130 | 26.6k | fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { |
131 | 26.6k | match *self { |
132 | 908 | Bson::Double(f) => write!(fmt, "{}", f), |
133 | 174 | Bson::String(ref s) => write!(fmt, "\"{}\"", s), |
134 | 1.16k | Bson::Array(ref vec) => { |
135 | 1.16k | fmt.write_str("[")?; |
136 | | |
137 | 1.16k | let indent = fmt.width().unwrap_or(2); |
138 | 1.16k | let indent_str = " ".repeat(indent); |
139 | 1.16k | |
140 | 1.16k | let mut first = true; |
141 | 25.1k | for bson in vec { |
142 | 24.0k | if !first { |
143 | 22.9k | fmt.write_str(", ")?; |
144 | 1.01k | } |
145 | 24.0k | if fmt.alternate() { |
146 | 0 | write!(fmt, "\n{indent_str}")?; |
147 | 0 | match bson { |
148 | 0 | Bson::Array(_arr) => { |
149 | 0 | let new_indent = indent + 2; |
150 | 0 | write!(fmt, "{bson:#new_indent$}")?; |
151 | | } |
152 | 0 | Bson::Document(ref doc) => { |
153 | 0 | let new_indent = indent + 2; |
154 | 0 | write!(fmt, "{doc:#new_indent$}")?; |
155 | | } |
156 | | _ => { |
157 | 0 | write!(fmt, "{}", bson)?; |
158 | | } |
159 | | } |
160 | | } else { |
161 | 24.0k | write!(fmt, "{}", bson)?; |
162 | | } |
163 | 24.0k | first = false; |
164 | | } |
165 | 1.16k | if fmt.alternate() && !vec.is_empty() { |
166 | 0 | let closing_bracket_indent_str = " ".repeat(indent - 2); |
167 | 0 | write!(fmt, "\n{closing_bracket_indent_str}]") |
168 | | } else { |
169 | 1.16k | fmt.write_str("]") |
170 | | } |
171 | | } |
172 | 378 | Bson::Document(ref doc) => { |
173 | 378 | if fmt.alternate() { |
174 | 0 | write!(fmt, "{doc:#}") |
175 | | } else { |
176 | 378 | write!(fmt, "{doc}") |
177 | | } |
178 | | } |
179 | 483 | Bson::Boolean(b) => write!(fmt, "{}", b), |
180 | 1.67k | Bson::Null => write!(fmt, "null"), |
181 | 2.28k | Bson::RegularExpression(ref x) => write!(fmt, "{}", x), |
182 | 164 | Bson::JavaScriptCode(ref code) |
183 | 148 | | Bson::JavaScriptCodeWithScope(JavaScriptCodeWithScope { ref code, .. }) => { |
184 | 312 | fmt.write_str(code) |
185 | | } |
186 | 429 | Bson::Int32(i) => write!(fmt, "{}", i), |
187 | 404 | Bson::Int64(i) => write!(fmt, "{}", i), |
188 | 344 | Bson::Timestamp(ref x) => write!(fmt, "{}", x), |
189 | 3.55k | Bson::Binary(ref x) => write!(fmt, "{}", x), |
190 | 364 | Bson::ObjectId(ref id) => write!(fmt, "ObjectId(\"{}\")", id), |
191 | 3.96k | Bson::DateTime(date_time) => write!(fmt, "DateTime(\"{}\")", date_time), |
192 | 200 | Bson::Symbol(ref sym) => write!(fmt, "Symbol(\"{}\")", sym), |
193 | 2.51k | Bson::Decimal128(ref d) => write!(fmt, "{}", d), |
194 | 3.92k | Bson::Undefined => write!(fmt, "undefined"), |
195 | 2.01k | Bson::MinKey => write!(fmt, "MinKey"), |
196 | 1.33k | Bson::MaxKey => write!(fmt, "MaxKey"), |
197 | | Bson::DbPointer(DbPointer { |
198 | 222 | ref namespace, |
199 | 222 | ref id, |
200 | 222 | }) => write!(fmt, "DbPointer({}, {})", namespace, id), |
201 | | } |
202 | 26.6k | } |
203 | | } |
204 | | |
205 | | impl Debug for Bson { |
206 | 0 | fn fmt(&self, fmt: &mut Formatter) -> fmt::Result { |
207 | 0 | match *self { |
208 | 0 | Bson::Double(f) => fmt.debug_tuple("Double").field(&f).finish(), |
209 | 0 | Bson::String(ref s) => fmt.debug_tuple("String").field(s).finish(), |
210 | 0 | Bson::Array(ref vec) => { |
211 | 0 | write!(fmt, "Array(")?; |
212 | 0 | Debug::fmt(vec, fmt)?; |
213 | 0 | write!(fmt, ")") |
214 | | } |
215 | 0 | Bson::Document(ref doc) => Debug::fmt(doc, fmt), |
216 | 0 | Bson::Boolean(b) => fmt.debug_tuple("Boolean").field(&b).finish(), |
217 | 0 | Bson::Null => write!(fmt, "Null"), |
218 | 0 | Bson::RegularExpression(ref regex) => Debug::fmt(regex, fmt), |
219 | 0 | Bson::JavaScriptCode(ref code) => { |
220 | 0 | fmt.debug_tuple("JavaScriptCode").field(code).finish() |
221 | | } |
222 | 0 | Bson::JavaScriptCodeWithScope(ref code) => Debug::fmt(code, fmt), |
223 | 0 | Bson::Int32(i) => fmt.debug_tuple("Int32").field(&i).finish(), |
224 | 0 | Bson::Int64(i) => fmt.debug_tuple("Int64").field(&i).finish(), |
225 | 0 | Bson::Timestamp(ref t) => Debug::fmt(t, fmt), |
226 | 0 | Bson::Binary(ref b) => Debug::fmt(b, fmt), |
227 | 0 | Bson::ObjectId(ref id) => Debug::fmt(id, fmt), |
228 | 0 | Bson::DateTime(ref date_time) => Debug::fmt(date_time, fmt), |
229 | 0 | Bson::Symbol(ref sym) => fmt.debug_tuple("Symbol").field(sym).finish(), |
230 | 0 | Bson::Decimal128(ref d) => Debug::fmt(d, fmt), |
231 | 0 | Bson::Undefined => write!(fmt, "Undefined"), |
232 | 0 | Bson::MinKey => write!(fmt, "MinKey"), |
233 | 0 | Bson::MaxKey => write!(fmt, "MaxKey"), |
234 | 0 | Bson::DbPointer(ref pointer) => Debug::fmt(pointer, fmt), |
235 | | } |
236 | 0 | } |
237 | | } |
238 | | |
239 | | impl Index<&str> for Bson { |
240 | | type Output = Bson; |
241 | | |
242 | 0 | fn index(&self, index: &str) -> &Self::Output { |
243 | 0 | match *self { |
244 | 0 | Bson::Document(ref doc) => match doc.get(index) { |
245 | 0 | Some(v) => v, |
246 | 0 | None => &Bson::Null, |
247 | | }, |
248 | 0 | _ => &Bson::Null, |
249 | | } |
250 | 0 | } |
251 | | } |
252 | | |
253 | | impl From<f32> for Bson { |
254 | 0 | fn from(a: f32) -> Bson { |
255 | 0 | Bson::Double(a.into()) |
256 | 0 | } |
257 | | } |
258 | | |
259 | | impl From<f64> for Bson { |
260 | 0 | fn from(a: f64) -> Bson { |
261 | 0 | Bson::Double(a) |
262 | 0 | } |
263 | | } |
264 | | |
265 | | impl From<&str> for Bson { |
266 | 0 | fn from(s: &str) -> Bson { |
267 | 0 | Bson::String(s.to_owned()) |
268 | 0 | } |
269 | | } |
270 | | |
271 | | impl From<String> for Bson { |
272 | 16.1k | fn from(a: String) -> Bson { |
273 | 16.1k | Bson::String(a) |
274 | 16.1k | } |
275 | | } |
276 | | |
277 | | impl From<crate::raw::CString> for Bson { |
278 | 0 | fn from(a: crate::raw::CString) -> Bson { |
279 | 0 | Bson::String(a.into_string()) |
280 | 0 | } |
281 | | } |
282 | | |
283 | | impl From<Document> for Bson { |
284 | 0 | fn from(a: Document) -> Bson { |
285 | 0 | Bson::Document(a) |
286 | 0 | } |
287 | | } |
288 | | |
289 | | impl From<bool> for Bson { |
290 | 0 | fn from(a: bool) -> Bson { |
291 | 0 | Bson::Boolean(a) |
292 | 0 | } |
293 | | } |
294 | | |
295 | | impl From<Regex> for Bson { |
296 | 0 | fn from(regex: Regex) -> Bson { |
297 | 0 | Bson::RegularExpression(regex) |
298 | 0 | } |
299 | | } |
300 | | |
301 | | impl From<JavaScriptCodeWithScope> for Bson { |
302 | 0 | fn from(code_with_scope: JavaScriptCodeWithScope) -> Bson { |
303 | 0 | Bson::JavaScriptCodeWithScope(code_with_scope) |
304 | 0 | } |
305 | | } |
306 | | |
307 | | impl From<Binary> for Bson { |
308 | 0 | fn from(binary: Binary) -> Bson { |
309 | 0 | Bson::Binary(binary) |
310 | 0 | } |
311 | | } |
312 | | |
313 | | impl From<Timestamp> for Bson { |
314 | 0 | fn from(ts: Timestamp) -> Bson { |
315 | 0 | Bson::Timestamp(ts) |
316 | 0 | } |
317 | | } |
318 | | |
319 | | impl<T> From<&T> for Bson |
320 | | where |
321 | | T: Clone + Into<Bson>, |
322 | | { |
323 | 0 | fn from(t: &T) -> Bson { |
324 | 0 | t.clone().into() |
325 | 0 | } Unexecuted instantiation: <bson::bson::Bson as core::convert::From<&alloc::string::String>>::from Unexecuted instantiation: <bson::bson::Bson as core::convert::From<&bson::raw::cstr::CString>>::from |
326 | | } |
327 | | |
328 | | impl<T> From<&mut T> for Bson |
329 | | where |
330 | | for<'a> &'a T: Into<Bson>, |
331 | | { |
332 | 0 | fn from(t: &mut T) -> Bson { |
333 | 0 | (&*t).into() |
334 | 0 | } |
335 | | } |
336 | | |
337 | | impl<T> From<Vec<T>> for Bson |
338 | | where |
339 | | T: Into<Bson>, |
340 | | { |
341 | 0 | fn from(v: Vec<T>) -> Bson { |
342 | 0 | Bson::Array(v.into_iter().map(|val| val.into()).collect()) |
343 | 0 | } |
344 | | } |
345 | | |
346 | | impl<T: Into<Bson>, S> From<HashSet<T, S>> for Bson { |
347 | 0 | fn from(s: HashSet<T, S>) -> Bson { |
348 | 0 | Bson::from_iter(s) |
349 | 0 | } |
350 | | } |
351 | | |
352 | | impl<T, const N: usize> From<[T; N]> for Bson |
353 | | where |
354 | | T: Into<Bson>, |
355 | | { |
356 | 0 | fn from(value: [T; N]) -> Self { |
357 | 0 | Bson::Array(value.into_iter().map(|v| v.into()).collect()) |
358 | 0 | } |
359 | | } |
360 | | |
361 | | impl<T> From<&[T]> for Bson |
362 | | where |
363 | | T: Clone + Into<Bson>, |
364 | | { |
365 | 0 | fn from(s: &[T]) -> Bson { |
366 | 0 | Bson::Array(s.iter().cloned().map(|val| val.into()).collect()) |
367 | 0 | } |
368 | | } |
369 | | |
370 | | impl<T: Into<Bson>> ::std::iter::FromIterator<T> for Bson { |
371 | | /// # Examples |
372 | | /// |
373 | | /// ``` |
374 | | /// use std::iter::FromIterator; |
375 | | /// use bson::Bson; |
376 | | /// |
377 | | /// let x: Bson = Bson::from_iter(vec!["lorem", "ipsum", "dolor"]); |
378 | | /// // or |
379 | | /// let x: Bson = vec!["lorem", "ipsum", "dolor"].into_iter().collect(); |
380 | | /// ``` |
381 | 0 | fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self { |
382 | 0 | Bson::Array(iter.into_iter().map(Into::into).collect()) |
383 | 0 | } |
384 | | } |
385 | | |
386 | | impl From<i32> for Bson { |
387 | 0 | fn from(a: i32) -> Bson { |
388 | 0 | Bson::Int32(a) |
389 | 0 | } |
390 | | } |
391 | | |
392 | | impl From<i64> for Bson { |
393 | 0 | fn from(a: i64) -> Bson { |
394 | 0 | Bson::Int64(a) |
395 | 0 | } |
396 | | } |
397 | | |
398 | | impl From<u32> for Bson { |
399 | 0 | fn from(a: u32) -> Bson { |
400 | 0 | if let Ok(i) = i32::try_from(a) { |
401 | 0 | Bson::Int32(i) |
402 | | } else { |
403 | 0 | Bson::Int64(a.into()) |
404 | | } |
405 | 0 | } |
406 | | } |
407 | | |
408 | | impl From<[u8; 12]> for Bson { |
409 | 0 | fn from(a: [u8; 12]) -> Bson { |
410 | 0 | Bson::ObjectId(oid::ObjectId::from_bytes(a)) |
411 | 0 | } |
412 | | } |
413 | | |
414 | | impl From<oid::ObjectId> for Bson { |
415 | 0 | fn from(a: oid::ObjectId) -> Bson { |
416 | 0 | Bson::ObjectId(a) |
417 | 0 | } |
418 | | } |
419 | | |
420 | | #[cfg(feature = "time-0_3")] |
421 | | impl From<time::OffsetDateTime> for Bson { |
422 | | fn from(a: time::OffsetDateTime) -> Bson { |
423 | | Bson::DateTime(crate::DateTime::from(a)) |
424 | | } |
425 | | } |
426 | | |
427 | | #[cfg(feature = "chrono-0_4")] |
428 | | impl<T: chrono::TimeZone> From<chrono::DateTime<T>> for Bson { |
429 | | fn from(a: chrono::DateTime<T>) -> Bson { |
430 | | Bson::DateTime(crate::DateTime::from(a)) |
431 | | } |
432 | | } |
433 | | |
434 | | #[cfg(feature = "jiff-0_2")] |
435 | | impl From<jiff::Timestamp> for Bson { |
436 | | fn from(a: jiff::Timestamp) -> Bson { |
437 | | Bson::DateTime(crate::DateTime::from(a)) |
438 | | } |
439 | | } |
440 | | |
441 | | #[cfg(feature = "uuid-1")] |
442 | | impl From<uuid::Uuid> for Bson { |
443 | | fn from(uuid: uuid::Uuid) -> Self { |
444 | | Bson::Binary(uuid.into()) |
445 | | } |
446 | | } |
447 | | |
448 | | impl From<crate::DateTime> for Bson { |
449 | 0 | fn from(dt: crate::DateTime) -> Self { |
450 | 0 | Bson::DateTime(dt) |
451 | 0 | } |
452 | | } |
453 | | |
454 | | impl From<DbPointer> for Bson { |
455 | 0 | fn from(a: DbPointer) -> Bson { |
456 | 0 | Bson::DbPointer(a) |
457 | 0 | } |
458 | | } |
459 | | |
460 | | impl From<Decimal128> for Bson { |
461 | 0 | fn from(d: Decimal128) -> Self { |
462 | 0 | Bson::Decimal128(d) |
463 | 0 | } |
464 | | } |
465 | | |
466 | | impl<T> From<Option<T>> for Bson |
467 | | where |
468 | | T: Into<Bson>, |
469 | | { |
470 | 0 | fn from(a: Option<T>) -> Bson { |
471 | 0 | match a { |
472 | 0 | None => Bson::Null, |
473 | 0 | Some(t) => t.into(), |
474 | | } |
475 | 0 | } |
476 | | } |
477 | | |
478 | | impl Bson { |
479 | | /// Get the [`ElementType`] of this value. |
480 | 405k | pub fn element_type(&self) -> ElementType { |
481 | 405k | match *self { |
482 | 11.1k | Bson::Double(..) => ElementType::Double, |
483 | 3.21k | Bson::String(..) => ElementType::String, |
484 | 10.6k | Bson::Array(..) => ElementType::Array, |
485 | 14.7k | Bson::Document(..) => ElementType::EmbeddedDocument, |
486 | 13.7k | Bson::Boolean(..) => ElementType::Boolean, |
487 | 62.6k | Bson::Null => ElementType::Null, |
488 | 55.9k | Bson::RegularExpression(..) => ElementType::RegularExpression, |
489 | 3.26k | Bson::JavaScriptCode(..) => ElementType::JavaScriptCode, |
490 | 2.82k | Bson::JavaScriptCodeWithScope(..) => ElementType::JavaScriptCodeWithScope, |
491 | 6.66k | Bson::Int32(..) => ElementType::Int32, |
492 | 3.54k | Bson::Int64(..) => ElementType::Int64, |
493 | 3.94k | Bson::Timestamp(..) => ElementType::Timestamp, |
494 | 25.0k | Bson::Binary(..) => ElementType::Binary, |
495 | 5.08k | Bson::ObjectId(..) => ElementType::ObjectId, |
496 | 22.5k | Bson::DateTime(..) => ElementType::DateTime, |
497 | 5.62k | Bson::Symbol(..) => ElementType::Symbol, |
498 | 3.69k | Bson::Decimal128(..) => ElementType::Decimal128, |
499 | 48.0k | Bson::Undefined => ElementType::Undefined, |
500 | 65.8k | Bson::MaxKey => ElementType::MaxKey, |
501 | 33.6k | Bson::MinKey => ElementType::MinKey, |
502 | 3.77k | Bson::DbPointer(..) => ElementType::DbPointer, |
503 | | } |
504 | 405k | } |
505 | | |
506 | | /// Converts to extended format. |
507 | | /// This function mainly used for [extended JSON format](https://www.mongodb.com/docs/manual/reference/mongodb-extended-json/). |
508 | | // TODO RUST-426: Investigate either removing this from the serde implementation or unifying |
509 | | // with the extended JSON implementation. |
510 | | #[cfg(feature = "serde")] |
511 | 0 | pub(crate) fn into_extended_document(self, rawbson: bool) -> Document { |
512 | 0 | match self { |
513 | | Bson::RegularExpression(Regex { |
514 | 0 | ref pattern, |
515 | 0 | ref options, |
516 | 0 | }) => { |
517 | 0 | let mut chars: Vec<_> = options.as_str().chars().collect(); |
518 | 0 | chars.sort_unstable(); |
519 | 0 |
|
520 | 0 | let options: String = chars.into_iter().collect(); |
521 | 0 |
|
522 | 0 | doc! { |
523 | 0 | "$regularExpression": { |
524 | 0 | "pattern": pattern, |
525 | 0 | "options": options, |
526 | 0 | } |
527 | 0 | } |
528 | | } |
529 | 0 | Bson::JavaScriptCode(ref code) => { |
530 | 0 | doc! { |
531 | 0 | "$code": code, |
532 | 0 | } |
533 | | } |
534 | 0 | Bson::JavaScriptCodeWithScope(JavaScriptCodeWithScope { code, scope }) => { |
535 | 0 | doc! { |
536 | 0 | "$code": code, |
537 | 0 | "$scope": scope, |
538 | 0 | } |
539 | | } |
540 | 0 | Bson::Timestamp(Timestamp { time, increment }) => { |
541 | 0 | doc! { |
542 | 0 | "$timestamp": { |
543 | 0 | "t": time, |
544 | 0 | "i": increment, |
545 | 0 | } |
546 | 0 | } |
547 | | } |
548 | 0 | Bson::Binary(Binary { subtype, bytes }) => { |
549 | 0 | let tval: u8 = From::from(subtype); |
550 | 0 | if rawbson { |
551 | 0 | doc! { |
552 | 0 | "$binary": { |
553 | 0 | "bytes": Binary { subtype: crate::spec::BinarySubtype::Generic, bytes }, |
554 | 0 | "subType": Bson::Int32(tval.into()) |
555 | 0 | } |
556 | 0 | } |
557 | | } else { |
558 | 0 | doc! { |
559 | 0 | "$binary": { |
560 | 0 | "base64": crate::base64::encode(bytes), |
561 | 0 | "subType": hex::encode([tval]), |
562 | 0 | } |
563 | 0 | } |
564 | | } |
565 | | } |
566 | 0 | Bson::ObjectId(ref v) => { |
567 | 0 | doc! { |
568 | 0 | "$oid": v.to_string(), |
569 | 0 | } |
570 | | } |
571 | 0 | Bson::DateTime(v) if rawbson => doc! { |
572 | 0 | "$date": v.timestamp_millis(), |
573 | 0 | }, |
574 | 0 | Bson::DateTime(v) if v.timestamp_millis() >= 0 && v.to_time_0_3().year() <= 9999 => { |
575 | 0 | doc! { |
576 | 0 | // Unwrap safety: timestamps in the guarded range can always be formatted. |
577 | 0 | "$date": v.try_to_rfc3339_string().unwrap(), |
578 | 0 | } |
579 | | } |
580 | 0 | Bson::DateTime(v) => doc! { |
581 | 0 | "$date": { "$numberLong": v.timestamp_millis().to_string() }, |
582 | 0 | }, |
583 | 0 | Bson::Symbol(ref v) => { |
584 | 0 | doc! { |
585 | 0 | "$symbol": v.to_owned(), |
586 | 0 | } |
587 | | } |
588 | | Bson::Undefined => { |
589 | 0 | doc! { |
590 | 0 | "$undefined": true, |
591 | 0 | } |
592 | | } |
593 | | Bson::MinKey => { |
594 | 0 | doc! { |
595 | 0 | "$minKey": 1, |
596 | 0 | } |
597 | | } |
598 | | Bson::MaxKey => { |
599 | 0 | doc! { |
600 | 0 | "$maxKey": 1, |
601 | 0 | } |
602 | | } |
603 | | Bson::DbPointer(DbPointer { |
604 | 0 | ref namespace, |
605 | 0 | ref id, |
606 | 0 | }) => { |
607 | 0 | doc! { |
608 | 0 | "$dbPointer": { |
609 | 0 | "$ref": namespace, |
610 | 0 | "$id": { |
611 | 0 | "$oid": id.to_string() |
612 | 0 | } |
613 | 0 | } |
614 | 0 | } |
615 | | } |
616 | 0 | _ => panic!("Attempted conversion of invalid data type: {}", self), |
617 | | } |
618 | 0 | } |
619 | | |
620 | | #[cfg(feature = "serde")] |
621 | 0 | pub(crate) fn from_extended_document(doc: Document) -> Bson { |
622 | 0 | if doc.len() > 2 { |
623 | 0 | return Bson::Document(doc); |
624 | 0 | } |
625 | 0 |
|
626 | 0 | let mut keys: Vec<_> = doc.keys().map(|s| s.as_str()).collect(); |
627 | 0 | keys.sort_unstable(); |
628 | 0 |
|
629 | 0 | match keys.as_slice() { |
630 | 0 | ["$oid"] => { |
631 | 0 | if let Ok(oid) = doc.get_str("$oid") { |
632 | 0 | if let Ok(oid) = crate::oid::ObjectId::parse_str(oid) { |
633 | 0 | return Bson::ObjectId(oid); |
634 | 0 | } |
635 | 0 | } |
636 | | } |
637 | | |
638 | 0 | ["$symbol"] => { |
639 | 0 | if let Ok(symbol) = doc.get_str("$symbol") { |
640 | 0 | return Bson::Symbol(symbol.into()); |
641 | 0 | } |
642 | | } |
643 | | |
644 | 0 | ["$numberInt"] => { |
645 | 0 | if let Ok(i) = doc.get_str("$numberInt") { |
646 | 0 | if let Ok(i) = i.parse() { |
647 | 0 | return Bson::Int32(i); |
648 | 0 | } |
649 | 0 | } |
650 | | } |
651 | | |
652 | 0 | ["$numberLong"] => { |
653 | 0 | if let Ok(i) = doc.get_str("$numberLong") { |
654 | 0 | if let Ok(i) = i.parse() { |
655 | 0 | return Bson::Int64(i); |
656 | 0 | } |
657 | 0 | } |
658 | | } |
659 | | |
660 | 0 | ["$numberDouble"] => match doc.get_str("$numberDouble") { |
661 | 0 | Ok("Infinity") => return Bson::Double(f64::INFINITY), |
662 | 0 | Ok("-Infinity") => return Bson::Double(f64::NEG_INFINITY), |
663 | 0 | Ok("NaN") => return Bson::Double(f64::NAN), |
664 | 0 | Ok(other) => { |
665 | 0 | if let Ok(d) = other.parse() { |
666 | 0 | return Bson::Double(d); |
667 | 0 | } |
668 | | } |
669 | 0 | _ => {} |
670 | | }, |
671 | | |
672 | 0 | ["$numberDecimal"] => { |
673 | 0 | if let Ok(d) = doc.get_str("$numberDecimal") { |
674 | 0 | if let Ok(d) = d.parse() { |
675 | 0 | return Bson::Decimal128(d); |
676 | 0 | } |
677 | 0 | } |
678 | | } |
679 | | |
680 | 0 | ["$numberDecimalBytes"] => { |
681 | 0 | if let Ok(bytes) = doc.get_binary_generic("$numberDecimalBytes") { |
682 | 0 | if let Ok(b) = bytes.clone().try_into() { |
683 | 0 | return Bson::Decimal128(Decimal128 { bytes: b }); |
684 | 0 | } |
685 | 0 | } |
686 | | } |
687 | | |
688 | 0 | ["$binary"] => { |
689 | 0 | if let Some(binary) = Binary::from_extended_doc(&doc) { |
690 | 0 | return Bson::Binary(binary); |
691 | 0 | } |
692 | | } |
693 | | |
694 | 0 | ["$code"] => { |
695 | 0 | if let Ok(code) = doc.get_str("$code") { |
696 | 0 | return Bson::JavaScriptCode(code.into()); |
697 | 0 | } |
698 | | } |
699 | | |
700 | 0 | ["$code", "$scope"] => { |
701 | 0 | if let Ok(code) = doc.get_str("$code") { |
702 | 0 | if let Ok(scope) = doc.get_document("$scope") { |
703 | 0 | return Bson::JavaScriptCodeWithScope(JavaScriptCodeWithScope { |
704 | 0 | code: code.into(), |
705 | 0 | scope: scope.clone(), |
706 | 0 | }); |
707 | 0 | } |
708 | 0 | } |
709 | | } |
710 | | |
711 | 0 | ["$timestamp"] => { |
712 | 0 | if let Ok(timestamp) = doc.get_document("$timestamp") { |
713 | 0 | if let Ok(t) = timestamp.get_i32("t") { |
714 | 0 | if let Ok(i) = timestamp.get_i32("i") { |
715 | 0 | return Bson::Timestamp(Timestamp { |
716 | 0 | time: t as u32, |
717 | 0 | increment: i as u32, |
718 | 0 | }); |
719 | 0 | } |
720 | 0 | } |
721 | | |
722 | 0 | if let Ok(t) = timestamp.get_i64("t") { |
723 | 0 | if let Ok(i) = timestamp.get_i64("i") { |
724 | 0 | if t >= 0 && i >= 0 && t <= (u32::MAX as i64) && i <= (u32::MAX as i64) |
725 | | { |
726 | 0 | return Bson::Timestamp(Timestamp { |
727 | 0 | time: t as u32, |
728 | 0 | increment: i as u32, |
729 | 0 | }); |
730 | 0 | } |
731 | 0 | } |
732 | 0 | } |
733 | 0 | } |
734 | | } |
735 | | |
736 | 0 | ["$regularExpression"] => { |
737 | 0 | if let Ok(regex) = doc.get_document("$regularExpression") { |
738 | 0 | if let Ok(pattern) = regex.get_str("pattern") { |
739 | 0 | if let Ok(options) = regex.get_str("options") { |
740 | 0 | if let Ok(regex) = Regex::from_strings(pattern, options) { |
741 | 0 | return Bson::RegularExpression(regex); |
742 | 0 | } |
743 | 0 | } |
744 | 0 | } |
745 | 0 | } |
746 | | } |
747 | | |
748 | 0 | ["$dbPointer"] => { |
749 | 0 | if let Ok(db_pointer) = doc.get_document("$dbPointer") { |
750 | 0 | if let Ok(ns) = db_pointer.get_str("$ref") { |
751 | 0 | if let Ok(id) = db_pointer.get_object_id("$id") { |
752 | 0 | return Bson::DbPointer(DbPointer { |
753 | 0 | namespace: ns.into(), |
754 | 0 | id, |
755 | 0 | }); |
756 | 0 | } |
757 | 0 | } |
758 | 0 | } |
759 | | } |
760 | | |
761 | 0 | ["$date"] => { |
762 | 0 | if let Ok(date) = doc.get_i64("$date") { |
763 | 0 | return Bson::DateTime(crate::DateTime::from_millis(date)); |
764 | 0 | } |
765 | | |
766 | 0 | if let Ok(date) = doc.get_str("$date") { |
767 | 0 | if let Ok(dt) = crate::DateTime::parse_rfc3339_str(date) { |
768 | 0 | return Bson::DateTime(dt); |
769 | 0 | } |
770 | 0 | } |
771 | | } |
772 | | |
773 | 0 | ["$minKey"] => { |
774 | 0 | let min_key = doc.get("$minKey"); |
775 | 0 |
|
776 | 0 | if min_key == Some(&Bson::Int32(1)) || min_key == Some(&Bson::Int64(1)) { |
777 | 0 | return Bson::MinKey; |
778 | 0 | } |
779 | | } |
780 | | |
781 | 0 | ["$maxKey"] => { |
782 | 0 | let max_key = doc.get("$maxKey"); |
783 | 0 |
|
784 | 0 | if max_key == Some(&Bson::Int32(1)) || max_key == Some(&Bson::Int64(1)) { |
785 | 0 | return Bson::MaxKey; |
786 | 0 | } |
787 | | } |
788 | | |
789 | 0 | ["$undefined"] => { |
790 | 0 | if doc.get("$undefined") == Some(&Bson::Boolean(true)) { |
791 | 0 | return Bson::Undefined; |
792 | 0 | } |
793 | | } |
794 | | |
795 | 0 | _ => {} |
796 | | }; |
797 | | |
798 | 0 | Bson::Document( |
799 | 0 | doc.into_iter() |
800 | 0 | .map(|(k, v)| { |
801 | 0 | let v = match v { |
802 | 0 | Bson::Document(v) => Bson::from_extended_document(v), |
803 | 0 | other => other, |
804 | | }; |
805 | | |
806 | 0 | (k, v) |
807 | 0 | }) |
808 | 0 | .collect(), |
809 | 0 | ) |
810 | 0 | } |
811 | | |
812 | | /// Method for converting a given [`Bson`] value to a [`serde::de::Unexpected`] for error |
813 | | /// reporting. |
814 | | #[cfg(feature = "serde")] |
815 | 0 | pub(crate) fn as_unexpected(&self) -> serde::de::Unexpected<'_> { |
816 | | use serde::de::Unexpected; |
817 | 0 | match self { |
818 | 0 | Bson::Array(_) => Unexpected::Seq, |
819 | 0 | Bson::Binary(b) => Unexpected::Bytes(b.bytes.as_slice()), |
820 | 0 | Bson::Boolean(b) => Unexpected::Bool(*b), |
821 | 0 | Bson::DbPointer(_) => Unexpected::Other("dbpointer"), |
822 | 0 | Bson::Document(_) => Unexpected::Map, |
823 | 0 | Bson::Double(f) => Unexpected::Float(*f), |
824 | 0 | Bson::Int32(i) => Unexpected::Signed(*i as i64), |
825 | 0 | Bson::Int64(i) => Unexpected::Signed(*i), |
826 | 0 | Bson::JavaScriptCode(_) => Unexpected::Other("javascript code"), |
827 | 0 | Bson::JavaScriptCodeWithScope(_) => Unexpected::Other("javascript code with scope"), |
828 | 0 | Bson::MaxKey => Unexpected::Other("maxkey"), |
829 | 0 | Bson::MinKey => Unexpected::Other("minkey"), |
830 | 0 | Bson::Null => Unexpected::Unit, |
831 | 0 | Bson::Undefined => Unexpected::Other("undefined"), |
832 | 0 | Bson::ObjectId(_) => Unexpected::Other("objectid"), |
833 | 0 | Bson::RegularExpression(_) => Unexpected::Other("regex"), |
834 | 0 | Bson::String(s) => Unexpected::Str(s.as_str()), |
835 | 0 | Bson::Symbol(_) => Unexpected::Other("symbol"), |
836 | 0 | Bson::Timestamp(_) => Unexpected::Other("timestamp"), |
837 | 0 | Bson::DateTime(_) => Unexpected::Other("datetime"), |
838 | 0 | Bson::Decimal128(_) => Unexpected::Other("decimal128"), |
839 | | } |
840 | 0 | } |
841 | | |
842 | 405k | pub(crate) fn append_to(&self, buf: &mut Vec<u8>) -> crate::error::Result<()> { |
843 | 405k | match self { |
844 | 6.66k | Self::Int32(val) => RawBsonRef::Int32(*val).append_to(buf), |
845 | 3.54k | Self::Int64(val) => RawBsonRef::Int64(*val).append_to(buf), |
846 | 11.1k | Self::Double(val) => RawBsonRef::Double(*val).append_to(buf), |
847 | 25.0k | Self::Binary(bin) => RawBsonRef::Binary(crate::RawBinaryRef { |
848 | 25.0k | subtype: bin.subtype, |
849 | 25.0k | bytes: &bin.bytes, |
850 | 25.0k | }) |
851 | 25.0k | .append_to(buf), |
852 | 3.21k | Self::String(s) => RawBsonRef::String(s).append_to(buf), |
853 | 10.6k | Self::Array(arr) => { |
854 | 10.6k | let mut writer = DocWriter::open(buf); |
855 | 156k | for (ix, v) in arr.iter().enumerate() { |
856 | 156k | writer.append_key( |
857 | 156k | v.element_type(), |
858 | 156k | &crate::raw::CString::from_string_unchecked(ix.to_string()), |
859 | 156k | ); |
860 | 156k | v.append_to(writer.buffer())?; |
861 | | } |
862 | | } |
863 | 14.7k | Self::Document(doc) => doc.append_to(buf)?, |
864 | 13.7k | Self::Boolean(b) => RawBsonRef::Boolean(*b).append_to(buf), |
865 | 55.9k | Self::RegularExpression(re) => RawBsonRef::RegularExpression(crate::RawRegexRef { |
866 | 55.9k | pattern: &re.pattern, |
867 | 55.9k | options: &re.options, |
868 | 55.9k | }) |
869 | 55.9k | .append_to(buf), |
870 | 3.26k | Self::JavaScriptCode(js) => RawBsonRef::JavaScriptCode(js).append_to(buf), |
871 | 2.82k | Self::JavaScriptCodeWithScope(cws) => { |
872 | 2.82k | let start = buf.len(); |
873 | 2.82k | buf.extend(0i32.to_le_bytes()); // placeholder |
874 | 2.82k | RawBsonRef::String(&cws.code).append_to(buf); |
875 | 2.82k | cws.scope.append_to(buf)?; |
876 | 2.82k | let len: i32 = (buf.len() - start) as i32; |
877 | 2.82k | buf[start..start + 4].copy_from_slice(&len.to_le_bytes()); |
878 | | } |
879 | 3.94k | Self::Timestamp(ts) => RawBsonRef::Timestamp(*ts).append_to(buf), |
880 | 5.08k | Self::ObjectId(oid) => RawBsonRef::ObjectId(*oid).append_to(buf), |
881 | 22.5k | Self::DateTime(dt) => RawBsonRef::DateTime(*dt).append_to(buf), |
882 | 5.62k | Self::Symbol(s) => RawBsonRef::Symbol(s).append_to(buf), |
883 | 3.69k | Self::Decimal128(d) => RawBsonRef::Decimal128(*d).append_to(buf), |
884 | 3.77k | Self::DbPointer(dbp) => { |
885 | 3.77k | RawBsonRef::String(&dbp.namespace).append_to(buf); |
886 | 3.77k | RawBsonRef::ObjectId(dbp.id).append_to(buf); |
887 | 3.77k | } |
888 | 210k | Self::Null | Self::Undefined | Self::MinKey | Self::MaxKey => {} |
889 | | } |
890 | 405k | Ok(()) |
891 | 405k | } |
892 | | } |
893 | | |
894 | | /// Value helpers |
895 | | impl Bson { |
896 | | /// If `self` is [`Double`](Bson::Double), return its value as an `f64`. Returns [`None`] |
897 | | /// otherwise. |
898 | 0 | pub fn as_f64(&self) -> Option<f64> { |
899 | 0 | match *self { |
900 | 0 | Bson::Double(v) => Some(v), |
901 | 0 | _ => None, |
902 | | } |
903 | 0 | } |
904 | | |
905 | | /// If `self` is [`String`](Bson::String), return its value as a `&str`. Returns [`None`] |
906 | | /// otherwise. |
907 | 0 | pub fn as_str(&self) -> Option<&str> { |
908 | 0 | match *self { |
909 | 0 | Bson::String(ref s) => Some(s), |
910 | 0 | _ => None, |
911 | | } |
912 | 0 | } |
913 | | |
914 | | /// If `self` is [`String`](Bson::String), return a mutable reference to its value as a [`str`]. |
915 | | /// Returns [`None`] otherwise. |
916 | 0 | pub fn as_str_mut(&mut self) -> Option<&mut str> { |
917 | 0 | match *self { |
918 | 0 | Bson::String(ref mut s) => Some(s), |
919 | 0 | _ => None, |
920 | | } |
921 | 0 | } |
922 | | |
923 | | /// If `self` is [`Array`](Bson::Array), return its value. Returns [`None`] otherwise. |
924 | 0 | pub fn as_array(&self) -> Option<&Array> { |
925 | 0 | match *self { |
926 | 0 | Bson::Array(ref v) => Some(v), |
927 | 0 | _ => None, |
928 | | } |
929 | 0 | } |
930 | | |
931 | | /// If `self` is [`Array`](Bson::Array), return a mutable reference to its value. Returns |
932 | | /// [`None`] otherwise. |
933 | 0 | pub fn as_array_mut(&mut self) -> Option<&mut Array> { |
934 | 0 | match *self { |
935 | 0 | Bson::Array(ref mut v) => Some(v), |
936 | 0 | _ => None, |
937 | | } |
938 | 0 | } |
939 | | |
940 | | /// If `self` is [`Document`](Bson::Document), return its value. Returns [`None`] otherwise. |
941 | 0 | pub fn as_document(&self) -> Option<&Document> { |
942 | 0 | match *self { |
943 | 0 | Bson::Document(ref v) => Some(v), |
944 | 0 | _ => None, |
945 | | } |
946 | 0 | } |
947 | | |
948 | | /// If `self` is [`Document`](Bson::Document), return a mutable reference to its value. Returns |
949 | | /// [`None`] otherwise. |
950 | 0 | pub fn as_document_mut(&mut self) -> Option<&mut Document> { |
951 | 0 | match *self { |
952 | 0 | Bson::Document(ref mut v) => Some(v), |
953 | 0 | _ => None, |
954 | | } |
955 | 0 | } |
956 | | |
957 | | /// If `self` is [`Boolean`](Bson::Boolean), return its value. Returns [`None`] otherwise. |
958 | 0 | pub fn as_bool(&self) -> Option<bool> { |
959 | 0 | match *self { |
960 | 0 | Bson::Boolean(v) => Some(v), |
961 | 0 | _ => None, |
962 | | } |
963 | 0 | } |
964 | | |
965 | | /// If `self` is [`Int32`](Bson::Int32), return its value. Returns [`None`] otherwise. |
966 | 0 | pub fn as_i32(&self) -> Option<i32> { |
967 | 0 | match *self { |
968 | 0 | Bson::Int32(v) => Some(v), |
969 | 0 | _ => None, |
970 | | } |
971 | 0 | } |
972 | | |
973 | | /// If `self` is [`Int64`](Bson::Int64), return its value. Returns [`None`] otherwise. |
974 | 0 | pub fn as_i64(&self) -> Option<i64> { |
975 | 0 | match *self { |
976 | 0 | Bson::Int64(v) => Some(v), |
977 | 0 | _ => None, |
978 | | } |
979 | 0 | } |
980 | | |
981 | | /// If `self` is [`ObjectId`](Bson::ObjectId), return its value. Returns [`None`] otherwise. |
982 | 0 | pub fn as_object_id(&self) -> Option<oid::ObjectId> { |
983 | 0 | match *self { |
984 | 0 | Bson::ObjectId(v) => Some(v), |
985 | 0 | _ => None, |
986 | | } |
987 | 0 | } |
988 | | |
989 | | /// If `self` is [`ObjectId`](Bson::ObjectId), return a mutable reference to its value. Returns |
990 | | /// [`None`] otherwise. |
991 | 0 | pub fn as_object_id_mut(&mut self) -> Option<&mut oid::ObjectId> { |
992 | 0 | match *self { |
993 | 0 | Bson::ObjectId(ref mut v) => Some(v), |
994 | 0 | _ => None, |
995 | | } |
996 | 0 | } |
997 | | |
998 | | /// If `self` is [`DateTime`](Bson::DateTime), return its value. Returns [`None`] otherwise. |
999 | 0 | pub fn as_datetime(&self) -> Option<&crate::DateTime> { |
1000 | 0 | match *self { |
1001 | 0 | Bson::DateTime(ref v) => Some(v), |
1002 | 0 | _ => None, |
1003 | | } |
1004 | 0 | } |
1005 | | |
1006 | | /// If `self` is [`DateTime`](Bson::DateTime), return a mutable reference to its value. Returns |
1007 | | /// [`None`] otherwise. |
1008 | 0 | pub fn as_datetime_mut(&mut self) -> Option<&mut crate::DateTime> { |
1009 | 0 | match *self { |
1010 | 0 | Bson::DateTime(ref mut v) => Some(v), |
1011 | 0 | _ => None, |
1012 | | } |
1013 | 0 | } |
1014 | | |
1015 | | /// If `self` is [`Symbol`](Bson::Symbol), return its value. Returns [`None`] otherwise. |
1016 | 0 | pub fn as_symbol(&self) -> Option<&str> { |
1017 | 0 | match *self { |
1018 | 0 | Bson::Symbol(ref v) => Some(v), |
1019 | 0 | _ => None, |
1020 | | } |
1021 | 0 | } |
1022 | | |
1023 | | /// If `self` is [`Symbol`](Bson::Symbol), return a mutable reference to its value. Returns |
1024 | | /// [`None`] otherwise. |
1025 | 0 | pub fn as_symbol_mut(&mut self) -> Option<&mut str> { |
1026 | 0 | match *self { |
1027 | 0 | Bson::Symbol(ref mut v) => Some(v), |
1028 | 0 | _ => None, |
1029 | | } |
1030 | 0 | } |
1031 | | |
1032 | | /// If `self` is [`Timestamp`](Bson::Timestamp), return its value. Returns [`None`] otherwise. |
1033 | 0 | pub fn as_timestamp(&self) -> Option<Timestamp> { |
1034 | 0 | match *self { |
1035 | 0 | Bson::Timestamp(timestamp) => Some(timestamp), |
1036 | 0 | _ => None, |
1037 | | } |
1038 | 0 | } |
1039 | | |
1040 | | /// If `self` is [`Null`](Bson::Null), return `()`. Returns [`None`] otherwise. |
1041 | 0 | pub fn as_null(&self) -> Option<()> { |
1042 | 0 | match *self { |
1043 | 0 | Bson::Null => Some(()), |
1044 | 0 | _ => None, |
1045 | | } |
1046 | 0 | } |
1047 | | |
1048 | | /// If `self` is [`DbPointer`](Bson::DbPointer), return its value. Returns [`None`] otherwise. |
1049 | 0 | pub fn as_db_pointer(&self) -> Option<&DbPointer> { |
1050 | 0 | match self { |
1051 | 0 | Bson::DbPointer(ref db_pointer) => Some(db_pointer), |
1052 | 0 | _ => None, |
1053 | | } |
1054 | 0 | } |
1055 | | } |
1056 | | |
1057 | | /// Represents a BSON timestamp value. |
1058 | | #[derive(Debug, Eq, Ord, PartialEq, PartialOrd, Clone, Copy, Hash)] |
1059 | | pub struct Timestamp { |
1060 | | /// The number of seconds since the Unix epoch. |
1061 | | pub time: u32, |
1062 | | |
1063 | | /// An incrementing value to order timestamps with the same number of seconds in the `time` |
1064 | | /// field. |
1065 | | pub increment: u32, |
1066 | | } |
1067 | | |
1068 | | impl Display for Timestamp { |
1069 | 344 | fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { |
1070 | 344 | write!(fmt, "Timestamp({}, {})", self.time, self.increment) |
1071 | 344 | } |
1072 | | } |
1073 | | |
1074 | | impl Timestamp { |
1075 | 5.92k | pub(crate) fn to_le_bytes(self) -> [u8; 8] { |
1076 | 5.92k | let mut out = [0; 8]; |
1077 | 5.92k | out[0..4].copy_from_slice(&self.increment.to_le_bytes()); |
1078 | 5.92k | out[4..8].copy_from_slice(&self.time.to_le_bytes()); |
1079 | 5.92k | out |
1080 | 5.92k | } |
1081 | | |
1082 | 156k | pub(crate) fn from_le_bytes(bytes: [u8; 8]) -> Self { |
1083 | 156k | let mut inc_bytes = [0; 4]; |
1084 | 156k | inc_bytes.copy_from_slice(&bytes[0..4]); |
1085 | 156k | let mut time_bytes = [0; 4]; |
1086 | 156k | time_bytes.copy_from_slice(&bytes[4..8]); |
1087 | 156k | Self { |
1088 | 156k | increment: u32::from_le_bytes(inc_bytes), |
1089 | 156k | time: u32::from_le_bytes(time_bytes), |
1090 | 156k | } |
1091 | 156k | } |
1092 | | } |
1093 | | |
1094 | | /// Represents a BSON regular expression value. |
1095 | | #[derive(Debug, Clone, Eq, PartialEq, Hash)] |
1096 | | pub struct Regex { |
1097 | | /// The regex pattern to match. |
1098 | | pub pattern: CString, |
1099 | | |
1100 | | /// The options for the regex. |
1101 | | /// |
1102 | | /// Options are identified by characters, which must be stored in |
1103 | | /// alphabetical order. Valid options are 'i' for case insensitive matching, 'm' for |
1104 | | /// multiline matching, 'x' for verbose mode, 'l' to make \w, \W, etc. locale dependent, |
1105 | | /// 's' for dotall mode ('.' matches everything), and 'u' to make \w, \W, etc. match |
1106 | | /// unicode. |
1107 | | pub options: CString, |
1108 | | } |
1109 | | |
1110 | | impl Regex { |
1111 | | #[cfg(any(test, feature = "serde"))] |
1112 | 286k | pub(crate) fn from_strings( |
1113 | 286k | pattern: impl AsRef<str>, |
1114 | 286k | options: impl AsRef<str>, |
1115 | 286k | ) -> crate::error::Result<Self> { |
1116 | 286k | let mut chars: Vec<_> = options.as_ref().chars().collect(); |
1117 | 286k | chars.sort_unstable(); |
1118 | 286k | let options: String = chars.into_iter().collect(); |
1119 | 286k | Ok(Self { |
1120 | 286k | pattern: pattern.as_ref().to_string().try_into()?, |
1121 | 286k | options: options.try_into()?, |
1122 | | }) |
1123 | 286k | } <bson::bson::Regex>::from_strings::<alloc::string::String, alloc::string::String> Line | Count | Source | 1112 | 286k | pub(crate) fn from_strings( | 1113 | 286k | pattern: impl AsRef<str>, | 1114 | 286k | options: impl AsRef<str>, | 1115 | 286k | ) -> crate::error::Result<Self> { | 1116 | 286k | let mut chars: Vec<_> = options.as_ref().chars().collect(); | 1117 | 286k | chars.sort_unstable(); | 1118 | 286k | let options: String = chars.into_iter().collect(); | 1119 | 286k | Ok(Self { | 1120 | 286k | pattern: pattern.as_ref().to_string().try_into()?, | 1121 | 286k | options: options.try_into()?, | 1122 | | }) | 1123 | 286k | } |
Unexecuted instantiation: <bson::bson::Regex>::from_strings::<&str, &str> |
1124 | | } |
1125 | | |
1126 | | impl Display for Regex { |
1127 | 2.28k | fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { |
1128 | 2.28k | write!(fmt, "/{}/{}", self.pattern, self.options) |
1129 | 2.28k | } |
1130 | | } |
1131 | | |
1132 | | /// Represents a BSON code with scope value. |
1133 | | #[derive(Debug, Clone, PartialEq, Eq, Hash)] |
1134 | | pub struct JavaScriptCodeWithScope { |
1135 | | /// The JavaScript code. |
1136 | | pub code: String, |
1137 | | |
1138 | | /// The scope document containing variable bindings. |
1139 | | pub scope: Document, |
1140 | | } |
1141 | | |
1142 | | impl Display for JavaScriptCodeWithScope { |
1143 | 0 | fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { |
1144 | 0 | fmt.write_str(&self.code) |
1145 | 0 | } |
1146 | | } |
1147 | | |
1148 | | /// Represents a DBPointer. (Deprecated) |
1149 | | #[derive(Debug, Clone, Hash, PartialEq, Eq)] |
1150 | | pub struct DbPointer { |
1151 | | pub(crate) namespace: String, |
1152 | | pub(crate) id: oid::ObjectId, |
1153 | | } |