Skip to content

RUST-736 Update documentation for 2.0 release #295

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Aug 31, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .evergreen/check-rustdoc.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#!/bin/sh

set -o errexit

. ~/.cargo/env
cargo +nightly rustdoc -p bson --all-features -- --cfg docsrs -D warnings
15 changes: 15 additions & 0 deletions .evergreen/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,16 @@ functions:
${PREPARE_SHELL}
.evergreen/check-clippy.sh

"check rustdoc":
- command: shell.exec
type: test
params:
shell: bash
working_dir: "src"
script: |
${PREPARE_SHELL}
.evergreen/check-rustdoc.sh

"init test-results":
- command: shell.exec
params:
Expand Down Expand Up @@ -148,6 +158,10 @@ tasks:
commands:
- func: "check clippy"

- name: "check-rustdoc"
commands:
- func: "check rustdoc"

axes:
- id: "extra-rust-versions"
values:
Expand Down Expand Up @@ -185,3 +199,4 @@ buildvariants:
tasks:
- name: "check-clippy"
- name: "check-rustfmt"
- name: "check-rustdoc"
5 changes: 5 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -58,3 +58,8 @@ assert_matches = "1.2"
serde_bytes = "0.11"
pretty_assertions = "0.6.1"
chrono = { version = "0.4", features = ["serde"] }
uuid = { version = "0.8.1", features = ["serde", "v4"] }

[package.metadata.docs.rs]
all-features = true
rustdoc-args = ["--cfg", "docsrs"]
105 changes: 100 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,16 +1,24 @@
# bson-rs
# bson

[![crates.io](https://img.shields.io/crates/v/bson.svg)](https://crates.io/crates/bson)
[![docs.rs](https://docs.rs/mongodb/badge.svg)](https://docs.rs/bson)
[![crates.io](https://img.shields.io/crates/l/bson.svg)](https://crates.io/crates/bson)

Encoding and decoding support for BSON in Rust

## Index
- [Installation](#installation)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the structure was updated to match the driver's readme

- [Requirements](#requirements)
- [Importing](#importing)
- [Feature flags](#feature-flags)
- [Useful links](#useful-links)
- [Overview of BSON Format](#overview-of-bson-format)
- [Usage](#usage)
- [BSON Values](#bson-values)
- [BSON Documents](#bson-documents)
- [Modeling BSON with strongly typed data structures](#modeling-bson-with-strongly-typed-data-structures)
- [Working with datetimes](#working-with-datetimes)
- [Working with UUIDs](#working-with-uuids)
- [Contributing](#contributing)
- [Running the Tests](#running-the-tests)
- [Continuous Integration](#continuous-integration)
Expand All @@ -20,17 +28,28 @@ Encoding and decoding support for BSON in Rust
- [Serde Documentation](https://serde.rs/)

## Installation
This crate works with Cargo and can be found on
[crates.io](https://crates.io/crates/bson) with a `Cargo.toml` like:
### Requirements
- Rust 1.48+

### Importing
This crate is available on [crates.io](https://crates.io/crates/bson). To use it in your application, simply add it to your project's `Cargo.toml`.

```toml
[dependencies]
bson = "2.0.0-beta.3"
```

This crate requires Rust 1.48+.
Note that if you are using `bson` through the `mongodb` crate, you do not need to specify it in your
`Cargo.toml`, since the `mongodb` crate already re-exports it.

#### Feature Flags

| Feature | Description | Extra dependencies | Default |
|:-------------|:-----------------------------------------------------------------------------------------------|:-------------------|:--------|
| `chrono-0_4` | Enable support for v0.4 of the [`chrono`](docs.rs/chrono/0.4) crate in the public API. | n/a | no |
| `uuid-0_8` | Enable support for v0.8 of the [`uuid`](docs.rs/uuid/0.8) crate in the public API. | `uuid` 0.8 | no |

## Overview of BSON Format
## Overview of the BSON Format

BSON, short for Binary JSON, is a binary-encoded serialization of JSON-like documents.
Like JSON, BSON supports the embedding of documents and arrays within other documents
Expand Down Expand Up @@ -186,6 +205,82 @@ separate the "business logic" that operates over the data from the (de)serializa
translates the data to/from its serialized form. This can lead to more clear and concise code
that is also less error prone.

### Working with datetimes

The BSON format includes a datetime type, which is modeled in this crate by the
[`bson::DateTime`](https://docs.rs/bson/2.0.0-beta.3/bson/struct.DateTime.html) struct, and the
`Serialize` and `Deserialize` implementations for this struct produce and parse BSON datetimes when
serializing to or deserializing from BSON. The popular crate [`chrono`](https://docs.rs/chrono) also
provides a `DateTime` type, but its `Serialize` and `Deserialize` implementations operate on strings
instead, so when using it with BSON, the BSON datetime type is not used. To work around this, the
`chrono-0_4` feature flag can be enabled. This flag exposes a number of convenient conversions
between `bson::DateTime` and `chrono::DateTime`, including the
[`chrono_datetime_as_bson_datetime`](https://docs.rs/bson/2.0.0-beta.3/bson/serde_helpers/chrono_datetime_as_bson_datetime/index.html)
serde helper, which can be used to (de)serialize `chrono::DateTime`s to/from BSON datetimes, and the
`From<chrono::DateTime>` implementation for `Bson`, which allows `chrono::DateTime` values to be
used in the `doc!` and `bson!` macros.

e.g.
``` rust
use serde::{Serialize, Deserialize};

#[derive(Serialize, Deserialize)]
struct Foo {
// serializes as a BSON datetime.
date_time: bson::DateTime,

// serializes as an RFC 3339 / ISO-8601 string.
chrono_datetime: chrono::DateTime<chrono::Utc>,

// serializes as a BSON datetime.
// this requires the "chrono-0_4" feature flag
#[serde(with = "bson::serde_helpers::chrono_datetime_as_bson_datetime")]
chrono_as_bson: chrono::DateTime<chrono::Utc>,
}

// this automatic conversion also requires the "chrono-0_4" feature flag
let query = doc! {
"created_at": chrono::Utc::now(),
};
```

### Working with UUIDs

The BSON format does not contain a dedicated UUID type, though it does have a "binary" type which
has UUID subtypes. Accordingly, this crate provides a
[`Binary`](https://docs.rs/bson/latest/bson/struct.Binary.html) struct which models this binary type
and serializes to and deserializes from it. The popular [`uuid`](https://docs.rs/uuid) crate does
provide a UUID type (`Uuid`), though its `Serialize` and `Deserialize` implementations operate on
strings, so when using it with BSON, the BSON binary type will not be used. To facilitate the
conversion between `Uuid` values and BSON binary values, the `uuid-0_8` feature flag can be
enabled. This flag exposes a number of convenient conversions from `Uuid`, including the
[`uuid_as_binary`](https://docs.rs/bson/2.0.0-beta.3/bson/serde_helpers/uuid_as_binary/index.html)
serde helper, which can be used to (de)serialize `Uuid`s to/from BSON binaries with the UUID
subtype, and the `From<Uuid>` implementation for `Bson`, which allows `Uuid` values to be used in
the `doc!` and `bson!` macros.

e.g.

``` rust
use serde::{Serialize, Deserialize};

#[derive(Serialize, Deserialize)]
struct Foo {
// serializes as a String.
uuid: Uuid,

// serializes as a BSON binary with subtype 4.
// this requires the "uuid-0_8" feature flag
#[serde(with = "bson::serde_helpers::uuid_as_binary")]
uuid_as_bson: uuid::Uuid,
}

// this automatic conversion also requires the "uuid-0_8" feature flag
let query = doc! {
"uuid": uuid::Uuid::new_v4(),
};
```

## Minimum supported Rust version (MSRV)

The MSRV for this crate is currently 1.48.0. This will be rarely be increased, and if it ever is,
Expand Down
1 change: 1 addition & 0 deletions rustfmt.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@ use_try_shorthand = true
wrap_comments = true
imports_layout = "HorizontalVertical"
imports_granularity = "Crate"
ignore = ["src/lib.rs"]
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rustfmt kept messing up the table that has the feature flags in it so I just had it skip lib.rs. Once rust-lang/rustfmt#4210 is released we should be able to remove this.

20 changes: 20 additions & 0 deletions src/bson.rs
Original file line number Diff line number Diff line change
Expand Up @@ -321,12 +321,21 @@ impl From<oid::ObjectId> for Bson {
}

#[cfg(feature = "chrono-0_4")]
#[cfg_attr(docsrs, doc(cfg(feature = "chrono-0_4")))]
impl<T: chrono::TimeZone> From<chrono::DateTime<T>> for Bson {
fn from(a: chrono::DateTime<T>) -> Bson {
Bson::DateTime(crate::DateTime::from(a))
}
}

#[cfg(feature = "uuid-0_8")]
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I noticed this wasn't here after I tried to ensure my documentation examples compiled. For completeness, I just went ahead and implemented it (RUST-997).

#[cfg_attr(docsrs, doc(cfg(feature = "uuid-0_8")))]
impl From<uuid::Uuid> for Bson {
fn from(uuid: uuid::Uuid) -> Self {
Bson::Binary(uuid.into())
}
}

impl From<crate::DateTime> for Bson {
fn from(dt: crate::DateTime) -> Self {
Bson::DateTime(dt)
Expand Down Expand Up @@ -1045,6 +1054,17 @@ impl Binary {
}
}

#[cfg(feature = "uuid-0_8")]
#[cfg_attr(docsrs, doc(cfg(feature = "uuid-0_8")))]
impl From<uuid::Uuid> for Binary {
fn from(uuid: uuid::Uuid) -> Self {
Binary {
subtype: BinarySubtype::Uuid,
bytes: uuid.as_bytes().to_vec(),
}
}
}

/// Represents a DBPointer. (Deprecated)
#[derive(Debug, Clone, PartialEq)]
pub struct DbPointer {
Expand Down
10 changes: 7 additions & 3 deletions src/datetime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ use chrono::{LocalResult, TimeZone, Utc};
/// will serialize to and deserialize from that format's equivalent of the
/// [extended JSON representation](https://docs.mongodb.com/manual/reference/mongodb-extended-json/) of a datetime.
/// To serialize a [`chrono::DateTime`] as a BSON datetime, you can use
/// [`serde_helpers::chrono_datetime_as_bson_datetime`].
/// [`crate::serde_helpers::chrono_datetime_as_bson_datetime`].
///
/// ```rust
/// # #[cfg(feature = "chrono-0_4")]
Expand Down Expand Up @@ -81,6 +81,7 @@ impl crate::DateTime {
/// Convert the given `chrono::DateTime` into a `bson::DateTime`, truncating it to millisecond
/// precision.
#[cfg(feature = "chrono-0_4")]
#[cfg_attr(docsrs, doc(cfg(feature = "chrono-0_4")))]
pub fn from_chrono<T: chrono::TimeZone>(dt: chrono::DateTime<T>) -> Self {
Self::from_millis(dt.timestamp_millis())
}
Expand Down Expand Up @@ -119,11 +120,12 @@ impl crate::DateTime {
/// assert_eq!(chrono_big, chrono::MAX_DATETIME)
/// ```
#[cfg(feature = "chrono-0_4")]
#[cfg_attr(docsrs, doc(cfg(feature = "chrono-0_4")))]
pub fn to_chrono(self) -> chrono::DateTime<Utc> {
self.to_chrono_private()
}

/// Convert the given [`std::SystemTime`] to a [`DateTime`].
/// Convert the given [`std::time::SystemTime`] to a [`DateTime`].
///
/// If the provided time is too far in the future or too far in the past to be represented
/// by a BSON datetime, either [`DateTime::MAX`] or [`DateTime::MIN`] will be
Expand All @@ -149,7 +151,7 @@ impl crate::DateTime {
}
}

/// Convert this [`DateTime`] to a [`std::SystemTime`].
/// Convert this [`DateTime`] to a [`std::time::SystemTime`].
pub fn to_system_time(self) -> SystemTime {
if self.0 >= 0 {
SystemTime::UNIX_EPOCH + Duration::from_millis(self.0 as u64)
Expand Down Expand Up @@ -204,13 +206,15 @@ impl From<crate::DateTime> for SystemTime {
}

#[cfg(feature = "chrono-0_4")]
#[cfg_attr(docsrs, doc(cfg(feature = "chrono-0_4")))]
impl From<crate::DateTime> for chrono::DateTime<Utc> {
fn from(bson_dt: DateTime) -> Self {
bson_dt.to_chrono()
}
}

#[cfg(feature = "chrono-0_4")]
#[cfg_attr(docsrs, doc(cfg(feature = "chrono-0_4")))]
impl<T: chrono::TimeZone> From<chrono::DateTime<T>> for crate::DateTime {
fn from(x: chrono::DateTime<T>) -> Self {
Self::from_chrono(x)
Expand Down
2 changes: 1 addition & 1 deletion src/de/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ pub enum Error {
EndOfStream,

/// A general error encountered during deserialization.
/// See: https://docs.serde.rs/serde/de/trait.Error.html
/// See: <https://docs.serde.rs/serde/de/trait.Error.html>
#[non_exhaustive]
DeserializationError {
/// A message describing the error.
Expand Down
4 changes: 2 additions & 2 deletions src/de/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -423,7 +423,7 @@ where
/// sequences with the Unicode replacement character.
///
/// This is mainly useful when reading raw BSON returned from a MongoDB server, which
/// in rare cases can contain invalidly truncated strings (https://jira.mongodb.org/browse/SERVER-24007).
/// in rare cases can contain invalidly truncated strings (<https://jira.mongodb.org/browse/SERVER-24007>).
/// For most use cases, [`crate::from_reader`] can be used instead.
pub fn from_reader_utf8_lossy<R, T>(reader: R) -> Result<T>
where
Expand All @@ -447,7 +447,7 @@ where
/// sequences with the Unicode replacement character.
///
/// This is mainly useful when reading raw BSON returned from a MongoDB server, which
/// in rare cases can contain invalidly truncated strings (https://jira.mongodb.org/browse/SERVER-24007).
/// in rare cases can contain invalidly truncated strings (<https://jira.mongodb.org/browse/SERVER-24007>).
/// For most use cases, [`crate::from_slice`] can be used instead.
pub fn from_slice_utf8_lossy<'de, T>(bytes: &'de [u8]) -> Result<T>
where
Expand Down
2 changes: 1 addition & 1 deletion src/document.rs
Original file line number Diff line number Diff line change
Expand Up @@ -607,7 +607,7 @@ impl Document {
/// stream.
///
/// This is mainly useful when reading raw BSON returned from a MongoDB server, which
/// in rare cases can contain invalidly truncated strings (https://jira.mongodb.org/browse/SERVER-24007).
/// in rare cases can contain invalidly truncated strings (<https://jira.mongodb.org/browse/SERVER-24007>).
/// For most use cases, `Document::from_reader` can be used instead.
pub fn from_reader_utf8_lossy<R: Read>(mut reader: R) -> crate::de::Result<Document> {
Self::decode(&mut reader, true)
Expand Down
2 changes: 1 addition & 1 deletion src/extjson/de.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ pub enum Error {
InvalidObjectId(oid::Error),

/// A general error encountered during deserialization.
/// See: https://docs.serde.rs/serde/de/trait.Error.html
/// See: <https://docs.serde.rs/serde/de/trait.Error.html>
DeserializationError { message: String },
}

Expand Down
Loading