bson/
lib.rs

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, short for Binary JSON, is a binary-encoded serialization of JSON-like documents.
23//! Like JSON, BSON supports the embedding of documents and arrays within other documents
24//! and arrays. BSON also contains extensions that allow representation of data types that
25//! are not part of the JSON spec. For example, BSON has a datetime type and a binary data type.
26//!
27//! ```text
28//! // JSON equivalent
29//! {"hello": "world"}
30//!
31//! // BSON encoding
32//! \x16\x00\x00\x00                   // total document size
33//! \x02                               // 0x02 = type String
34//! hello\x00                          // field name
35//! \x06\x00\x00\x00world\x00          // field value
36//! \x00                               // 0x00 = type EOO ('end of object')
37//! ```
38//!
39//! BSON is the primary data representation for [MongoDB](https://www.mongodb.com/), and this crate is used in the
40//! [`mongodb`](https://docs.rs/mongodb/latest/mongodb/) driver crate in its API and implementation.
41//!
42//! For more information about BSON itself, see [bsonspec.org](http://bsonspec.org).
43//!
44//! ## Installation
45//! ### Requirements
46//! - Rust 1.64+
47//!
48//! ### Importing
49//! This crate is available on [crates.io](https://crates.io/crates/bson). To use it in your application,
50//! simply add it to your project's `Cargo.toml`.
51//!
52//! ```toml
53//! [dependencies]
54//! bson = "3.0.0"
55//! ```
56//!
57//! Note that if you are using `bson` through the `mongodb` crate, you do not need to specify it in
58//! your `Cargo.toml`, since the `mongodb` crate already re-exports it.
59//!
60//! #### Feature Flags
61//!
62//! | Feature      | Description                                                                                          | Default |
63//! |:-------------|:-----------------------------------------------------------------------------------------------------|:--------|
64//! | `chrono-0_4` | Enable support for v0.4 of the [`chrono`](https://docs.rs/chrono/0.4) crate in the public API.       | no      |
65//! | `jiff-0_2` | Enable support for v0.2 of the [`jiff`](https://docs.rs/jiff/0.2) crate in the public API.             | no      |
66//! | `uuid-1`     | Enable support for v1.x of the [`uuid`](https://docs.rs/uuid/1.x) crate in the public API.           | no      |
67//! | `time-0_3`   | Enable support for v0.3 of the [`time`](https://docs.rs/time/0.3) crate in the public API.           | no      |
68//! | `serde`      | Enable integration with the [`serde`](https://docs.rs/serde/) serialization/deserialization framework.  | no      |
69//! | `serde_with-3` | Enable [`serde_with`](https://docs.rs/serde_with/3.x) type conversion utilities in the public API. | no      |
70//! | `serde_path_to_error` | Enable support for error paths via integration with [`serde_path_to_error`](https://docs.rs/serde_path_to_err/latest).  This is an unstable feature and any breaking changes to `serde_path_to_error` may affect usage of it via this feature. | no |
71//! | `compat-3-0-0` | Required for future compatibility if default features are disabled. | yes |
72//! | `large_dates` | Increase the supported year range for some `bson::DateTime` utilities from +/-9,999 (inclusive) to +/-999,999 (inclusive). Note that enabling this feature can impact performance and introduce parsing ambiguities. | no |
73//! | `serde_json-1` | Enable support for v1.x of the [`serde_json`](https://docs.rs/serde_json/1.x) crate in the public API. | no |
74//!
75//! ## BSON values
76//!
77//! Many different types can be represented as a BSON value, including 32-bit and 64-bit signed
78//! integers, 64 bit floating point numbers, strings, datetimes, embedded documents, and more. To
79//! see a full list of possible BSON values, see the [BSON specification](http://bsonspec.org/spec.html). The various
80//! possible BSON values are modeled in this crate by the [`Bson`](enum.Bson.html) enum.
81//!
82//! ### Creating [`Bson`](enum.Bson.html) instances
83//!
84//! [`Bson`](enum.Bson.html) values can be instantiated directly or via the
85//! [`bson!`](macro.bson.html) macro:
86//!
87//! ```rust
88//! use bson::{bson, Bson};
89//!
90//! let string = Bson::String("hello world".to_string());
91//! let int = Bson::Int32(5);
92//! let array = Bson::Array(vec![Bson::Int32(5), Bson::Boolean(false)]);
93//!
94//! let string: Bson = "hello world".into();
95//! let int: Bson = 5i32.into();
96//!
97//! let string = bson!("hello world");
98//! let int = bson!(5);
99//! let array = bson!([5, false]);
100//! ```
101//! [`bson!`](macro.bson.html) has supports both array and object literals, and it automatically
102//! converts any values specified to [`Bson`](enum.Bson.html), provided they are `Into<Bson>`.
103//!
104//! ### [`Bson`](enum.Bson.html) value unwrapping
105//!
106//! [`Bson`](enum.Bson.html) has a number of helper methods for accessing the underlying native Rust
107//! types. These helpers can be useful in circumstances in which the specific type of a BSON value
108//! is known ahead of time.
109//!
110//! e.g.:
111//! ```rust
112//! use bson::{bson, Bson};
113//!
114//! let value = Bson::Int32(5);
115//! let int = value.as_i32(); // Some(5)
116//! let bool = value.as_bool(); // None
117//!
118//! let value = bson!([true]);
119//! let array = value.as_array(); // Some(&Vec<Bson>)
120//! ```
121//!
122//! ## BSON documents
123//!
124//! BSON documents are ordered maps of UTF-8 encoded strings to BSON values. They are logically
125//! similar to JSON objects in that they can contain subdocuments, arrays, and values of several
126//! different types. This crate models BSON documents via the
127//! [`Document`](document/struct.Document.html) struct.
128//!
129//! ### Creating [`Document`](document/struct.Document.html)s
130//!
131//! [`Document`](document/struct.Document.html)s can be created directly either from a byte
132//! reader containing BSON data or via the `doc!` macro:
133//! ```rust
134//! use bson::{doc, Document};
135//! use std::io::Read;
136//!
137//! let mut bytes = hex::decode("0C0000001069000100000000").unwrap();
138//! let doc = Document::from_reader(&mut bytes.as_slice()).unwrap(); // { "i": 1 }
139//!
140//! let doc = doc! {
141//!    "hello": "world",
142//!    "int": 5,
143//!    "subdoc": { "cat": true },
144//! };
145//! ```
146//! [`doc!`](macro.doc.html) works similarly to [`bson!`](macro.bson.html), except that it always
147//! returns a [`Document`](document/struct.Document.html) rather than a [`Bson`](enum.Bson.html).
148//!
149//! ### [`Document`](document/struct.Document.html) member access
150//!
151//! [`Document`](document/struct.Document.html) has a number of methods on it to facilitate member
152//! access:
153//!
154//! ```rust
155//! use bson::doc;
156//!
157//! let doc = doc! {
158//!    "string": "string",
159//!    "bool": true,
160//!    "i32": 5,
161//!    "doc": { "x": true },
162//! };
163//!
164//! // attempt get values as untyped Bson
165//! let none = doc.get("asdfadsf"); // None
166//! let value = doc.get("string"); // Some(&Bson::String("string"))
167//!
168//! // attempt to get values with explicit typing
169//! let string = doc.get_str("string"); // Ok("string")
170//! let subdoc = doc.get_document("doc"); // Some(Document({ "x": true }))
171//! let error = doc.get_i64("i32"); // Err(...)
172//! ```
173//!
174//! ## Integration with `serde`
175//!
176//! While it is possible to work with documents and BSON values directly, it will often introduce a
177//! lot of boilerplate for verifying the necessary keys are present and their values are the correct
178//! types. Enabling the `serde` feature provides integration with the [`serde`](https://serde.rs/)
179//! crate that maps BSON data into Rust data structs largely automatically, removing the need for
180//! all that boilerplate.
181//!
182//! e.g.:
183//! ```rust
184//! use serde::{Deserialize, Serialize};
185//! use bson::{bson, Bson};
186//!
187//! #[derive(Serialize, Deserialize)]
188//! struct Person {
189//!     name: String,
190//!     age: i32,
191//!     phones: Vec<String>,
192//! }
193//!
194//! // Some BSON input data as a [`Bson`].
195//! let bson_data: Bson = bson!({
196//!     "name": "John Doe",
197//!     "age": 43,
198//!     "phones": [
199//!         "+44 1234567",
200//!         "+44 2345678"
201//!     ]
202//! });
203//!
204//! // Deserialize the Person struct from the BSON data, automatically
205//! // verifying that the necessary keys are present and that they are of
206//! // the correct types.
207//! let mut person: Person = bson::deserialize_from_bson(bson_data).unwrap();
208//!
209//! // Do things just like with any other Rust data structure.
210//! println!("Redacting {}'s record.", person.name);
211//! person.name = "REDACTED".to_string();
212//!
213//! // Get a serialized version of the input data as a [`Bson`].
214//! let redacted_bson = bson::serialize_to_bson(&person).unwrap();
215//! ```
216//!
217//! Any types that implement [`Serialize`](serde::Serialize) and [`Deserialize`](serde::Deserialize)
218//! can be used in this way. Doing so helps separate the "business logic" that operates over the
219//! data from the (de)serialization logic that translates the data to/from its serialized form. This
220//! can lead to more clear and concise code that is also less error prone.
221//!
222//! When serializing values that cannot be represented in BSON, or deserialzing from BSON that does
223//! not match the format expected by the type, the default error will only report the specific field
224//! that failed. To aid debugging, enabling the `serde_path_to_error` feature will
225//! [augment errors](crate::error::Error::path) with the full field path from root object to
226//! failing field.  This feature does incur a small CPU and memory overhead during (de)serialization
227//! and should be enabled with care in performance-sensitive environments.
228//!
229//! ### Embedding BSON Value Types
230//!
231//! The `serde` feature also enables implementations of [`Serialize`](serde::Serialize) and
232//! [`Deserialize`](serde::Deserialize) for the Rust types provided by this crate that represent
233//! BSON values, allowing them to be embedded in domain-specific structs as appropriate:
234//! ```rust
235//! use serde::{Deserialize, Serialize};
236//! use bson::{bson, Bson, oid::ObjectId};
237//!
238//! #[derive(Serialize, Deserialize)]
239//! struct Person {
240//!     id: ObjectId,
241//!     name: String,
242//!     age: i32,
243//!     phones: Vec<String>,
244//! }
245//!
246//! let bson_data: Bson = bson!({
247//!     "id": ObjectId::new(),
248//!     "name": "John Doe",
249//!     "age": 43,
250//!     "phones": [
251//!         "+44 1234567",
252//!         "+44 2345678"
253//!     ]
254//! });
255//!
256//! let person: Person = bson::deserialize_from_bson(bson_data).unwrap();
257//! ```
258//!
259//! ### Encoding vs. Serialization
260//!
261//! With the `serde` feature enabled, a BSON document can be converted to its wire-format byte
262//! representation in multiple ways:
263//! ```rust
264//! # fn wrapper() -> bson::error::Result<()> {
265//! use bson::{doc, serialize_to_vec};
266//! let my_document = doc! { "hello": "bson" };
267//! let encoded = my_document.to_vec()?;
268//! let serialized = serialize_to_vec(&my_document)?;
269//! # Ok(())
270//! # }
271//! # wrapper().unwrap();
272//! ```
273//!
274//! We recommend that, where possible, documents be converted to byte form using the encoding
275//! methods ([`Document::to_vec`]/[`Document::to_writer`]); this is more efficient as it avoids
276//! the intermediate `serde` data model representation.  This also applies to decoding; prefer
277//! [`Document::from_reader`] over [`deserialize_from_reader`] / [`deserialize_from_slice`].
278//!
279//! ### Serializer Compatibility
280//!
281//! The implementations of [`Serialize`](serde::Serialize) and [`Deserialize`](serde::Deserialize)
282//! for BSON value types are tested with the `serde` \[de\]serializers provided by this crate and by
283//! the `serde_json` crate.  Compatibility with formats provided by other crates is not guaranteed
284//! and the data produced by serializing BSON values to other formats may change when this crate is
285//! updated.
286//!
287//! ## Working with Extended JSON
288//!
289//! MongoDB Extended JSON (extJSON) is a format of JSON that allows for the encoding
290//! of BSON type information. Normal JSON cannot unambiguously represent all BSON types losslessly,
291//! so an extension was designed to include conventions for representing those types.
292//!
293//! For example, a BSON binary is represented by the following format:
294//! ```text
295//! {
296//!    "$binary": {
297//!        "base64": <base64 encoded payload as a string>,
298//!        "subType": <subtype as a one or two character hex string>,
299//!    }
300//! }
301//! ```
302//! For more information on extJSON and the complete list of translations, see the [official MongoDB documentation](https://www.mongodb.com/docs/manual/reference/mongodb-extended-json/).
303//!
304//! All MongoDB drivers and BSON libraries interpret and produce extJSON, so it can serve as a
305//! useful tool for communicating between applications where raw BSON bytes cannot be used (e.g. via
306//! JSON REST APIs). It's also useful for representing BSON data as a string.
307//!
308//! ### Canonical and Relaxed Modes
309//!
310//! There are two modes of extJSON: "Canonical" and "Relaxed". They are the same except for the
311//! following differences:
312//!   - In relaxed mode, all BSON numbers are represented by the JSON number type, rather than the
313//!     object notation.
314//!   - In relaxed mode, the string in the datetime object notation is RFC 3339 (ISO-8601) formatted
315//!     (if the date is after 1970).
316//!
317//! e.g.
318//! ```rust
319//! # use bson::bson;
320//! let doc = bson!({ "x": 5, "d": bson::DateTime::now() });
321//!
322//! println!("relaxed: {}", doc.clone().into_relaxed_extjson());
323//! // relaxed: "{"x":5,"d":{"$date":"2020-06-01T22:19:13.075Z"}}"
324//!
325//! println!("canonical: {}", doc.into_canonical_extjson());
326//! // canonical: {"x":{"$numberInt":"5"},"d":{"$date":{"$numberLong":"1591050020711"}}}
327//! ```
328//!
329//! Canonical mode is useful when BSON values need to be round tripped without losing any type
330//! information. Relaxed mode is more useful when debugging or logging BSON data.
331//!
332//! ### Deserializing from Extended JSON
333//!
334//! Extended JSON can be deserialized into a [`Bson`] value using the
335//! [`TryFrom`](https://docs.rs/bson/latest/bson/enum.Bson.html#impl-TryFrom%3CValue%3E-for-Bson)
336//! implementation for [`serde_json::Value`]. This implementation accepts both canonical and relaxed
337//! extJSON, and the two modes can be mixed within a single representation.
338//!
339//! e.g.
340//! ```rust
341//! # use bson::Bson;
342//! # use serde_json::json;
343//! # use std::convert::{TryFrom, TryInto};
344//! let json_doc = json!({ "x": 5i32, "y": { "$numberInt": "5" }, "z": { "subdoc": "hello" } });
345//! let bson: Bson = json_doc.try_into().unwrap(); // Bson::Document(...)
346//!
347//! let json_date = json!({ "$date": { "$numberLong": "1590972160292" } });
348//! let bson_date: Bson = json_date.try_into().unwrap(); // Bson::DateTime(...)
349//!
350//! let invalid_ext_json = json!({ "$numberLong": 5 });
351//! Bson::try_from(invalid_ext_json).expect_err("5 should be a string");
352//! ```
353//!
354//! ### Serializing to Extended JSON
355//!
356//! A [`Bson`] value can be serialized into extJSON using the [`Bson::into_relaxed_extjson`] and
357//! [`Bson::into_canonical_extjson`] methods. The `Into<serde_json::Value>` implementation for
358//! [`Bson`] produces relaxed extJSON.
359//!
360//! e.g.
361//! ```rust
362//! # use bson::{bson, oid};
363//! let doc = bson!({ "x": 5i32, "_id": oid::ObjectId::new() });
364//!
365//! let relaxed_extjson: serde_json::Value = doc.clone().into();
366//! println!("{}", relaxed_extjson); // { "x": 5, "_id": { "$oid": <hexstring> } }
367//!
368//! let relaxed_extjson = doc.clone().into_relaxed_extjson();
369//! println!("{}", relaxed_extjson); // { "x": 5, "_id": { "$oid": <hexstring> } }
370//!
371//! let canonical_extjson = doc.into_canonical_extjson();
372//! println!("{}", canonical_extjson); // { "x": { "$numberInt": "5" }, "_id": { "$oid": <hexstring> } }
373//! ```
374//!
375//! ## Working with datetimes
376//!
377//! The BSON format includes a datetime type, which is modeled in this crate by the
378//! [`DateTime`] struct, and the
379//! [`Serialize`](serde::Serialize) and [`Deserialize`](serde::Deserialize) implementations for this
380//! struct produce and parse BSON datetimes when serializing to or deserializing from BSON. The
381//! popular crate [`chrono`](docs.rs/chrono) also provides a [`DateTime`] type, but its
382//! [`Serialize`](serde::Serialize) and [`Deserialize`](serde::Deserialize) implementations operate
383//! on strings instead, so when using it with BSON, the BSON datetime type is not used. To work
384//! around this, the `chrono-0_4` feature flag can be enabled. This flag exposes a number of
385//! convenient conversions between [`bson::DateTime`](crate::DateTime) and [`chrono::DateTime`],
386//! including the [`serde_helpers::datetime::FromChrono04DateTime`]
387//! serde helper, which can be used to (de)serialize [`chrono::DateTime`]s to/from BSON datetimes,
388//! and the `From<chrono::DateTime>` implementation for [`Bson`], which allows [`chrono::DateTime`]
389//! values to be used in the `doc!` and `bson!` macros.
390//!
391//! e.g.
392//! ``` rust
393//! # #[cfg(feature = "chrono-0_4")]
394//! # {
395//! use serde::{Serialize, Deserialize};
396//! use serde_with::serde_as;
397//! use bson::doc;
398//! use bson::serde_helpers::datetime;
399//!
400//! #[serde_as]
401//! #[derive(Serialize, Deserialize)]
402//! struct Foo {
403//!     // serializes as a BSON datetime.
404//!     date_time: bson::DateTime,
405//!
406//!     // serializes as an RFC 3339 / ISO-8601 string.
407//!     chrono_datetime: chrono::DateTime<chrono::Utc>,
408//!
409//!     // serializes as a BSON datetime.
410//!     // this requires the "chrono-0_4" feature flag
411//!     #[serde_as(as = "datetime::FromChrono04DateTime")]
412//!     chrono_as_bson: chrono::DateTime<chrono::Utc>,
413//! }
414//!
415//! // this automatic conversion also requires the "chrono-0_4" feature flag
416//! let query = doc! {
417//!     "created_at": chrono::Utc::now(),
418//! };
419//! # }
420//! ```
421//!
422//! ## Working with UUIDs
423//!
424//! See the module level documentation for the [`uuid`] module.
425//!
426//! ## WASM support
427//!
428//! This crate compiles to the `wasm32-unknown-unknown` target; when doing so, the `js-sys` crate is
429//! used for the current timestamp component of `ObjectId` generation.
430//!
431//! ## Minimum supported Rust version (MSRV)
432//!
433//! The MSRV for this crate is currently 1.81. This will be rarely be increased, and if it ever
434//! is, it will only happen in a minor or major version release.
435
436#![allow(clippy::cognitive_complexity, clippy::derive_partial_eq_without_eq)]
437#![doc(html_root_url = "https://docs.rs/bson/3.0.0")]
438#![cfg_attr(docsrs, feature(doc_auto_cfg))]
439#![warn(missing_docs)]
440
441#[doc(inline)]
442pub use self::{
443    binary::Binary,
444    bson::{Array, Bson, DbPointer, Document, JavaScriptCodeWithScope, Regex, Timestamp},
445    datetime::DateTime,
446    decimal128::Decimal128,
447    raw::{
448        RawArray,
449        RawArrayBuf,
450        RawBinaryRef,
451        RawBson,
452        RawBsonRef,
453        RawDbPointerRef,
454        RawDocument,
455        RawDocumentBuf,
456        RawJavaScriptCodeWithScope,
457        RawJavaScriptCodeWithScopeRef,
458        RawRegexRef,
459    },
460    utf8_lossy::Utf8Lossy,
461    uuid::{Uuid, UuidRepresentation},
462};
463
464#[cfg(feature = "serde")]
465#[doc(inline)]
466pub use self::{
467    de::{
468        deserialize_from_bson,
469        deserialize_from_document,
470        deserialize_from_reader,
471        deserialize_from_slice,
472        raw::RawDeserializer,
473        Deserializer,
474    },
475    ser::{
476        serialize_to_bson,
477        serialize_to_buffer,
478        serialize_to_document,
479        serialize_to_raw_document_buf,
480        serialize_to_vec,
481        Serializer,
482    },
483};
484
485#[macro_use]
486mod macros;
487mod base64;
488pub mod binary;
489mod bson;
490pub mod datetime;
491#[cfg(feature = "serde")]
492pub mod de;
493pub mod decimal128;
494pub mod document;
495pub mod error;
496#[cfg(feature = "serde")]
497mod extjson;
498pub mod oid;
499pub mod raw;
500#[cfg(feature = "serde")]
501pub mod ser;
502#[cfg(feature = "serde")]
503pub mod serde_helpers;
504pub mod spec;
505mod utf8_lossy;
506pub mod uuid;
507
508#[cfg(test)]
509mod tests;
510
511#[cfg(not(feature = "compat-3-0-0"))]
512compile_error!(
513    "The feature 'compat-3-0-0' must be enabled to ensure forward compatibility with future \
514     versions of this crate."
515);