Skip to content

Commit

Permalink
RUST-1699: Add serde_with 3.x integration (crossterm-rs#422)
Browse files Browse the repository at this point in the history
* RUST-1699: Add serde_with 3.x integration
Co-authored-by: Abraham Egnor <abraham.egnor@mongodb.com>
Co-authored-by: Isabel Atkinson <isabel.atkinson@mongodb.com>
  • Loading branch information
drshika authored Jul 27, 2023
1 parent b243db1 commit 09a8cbb
Show file tree
Hide file tree
Showing 7 changed files with 184 additions and 31 deletions.
92 changes: 82 additions & 10 deletions .evergreen/Cargo.lock.msrv

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions .evergreen/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -195,9 +195,9 @@ axes:
- id: "extra-rust-versions"
values:
- id: "min"
display_name: "1.56 (minimum supported version)"
display_name: "1.60 (minimum supported version)"
variables:
RUST_VERSION: "1.56.0"
RUST_VERSION: "1.60.0"
MSRV: "true"
- id: "nightly"
display_name: "nightly"
Expand Down
4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -65,13 +65,13 @@ once_cell = "1.5.1"
uuid-0_8 = { package = "uuid", version = "0.8.1", features = ["serde", "v4"], optional = true }
uuid = { version = "1.1.2", features = ["serde", "v4"] }
serde_bytes = "0.11.5"
serde_with = { version = "1", optional = true }
serde_with = { version = "1.3.1", optional = true }
serde_with-3 = { package = "serde_with", version = "3.1.0", optional = true }
time = { version = "0.3.9", features = ["formatting", "parsing", "macros", "large-dates"] }
bitvec = "1.0.1"

[target.'cfg(target_arch = "wasm32")'.dependencies]
js-sys = "0.3"

[dev-dependencies]
assert_matches = "1.2"
criterion = "0.3.0"
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,8 @@ Note that if you are using `bson` through the `mongodb` crate, you do not need t
| `chrono-0_4` | Enable support for v0.4 of the [`chrono`](https://docs.rs/chrono/0.4) crate in the public API. | n/a | no |
| `uuid-0_8` | Enable support for v0.8 of the [`uuid`](https://docs.rs/uuid/0.8) crate in the public API. | n/a | no |
| `uuid-1` | Enable support for v1.x of the [`uuid`](https://docs.rs/uuid/1.0) crate in the public API. | n/a | no |
| `serde_with` | Enable [`serde_with`](https://docs.rs/serde_with/latest) integrations for `bson::DateTime` and `bson::Uuid` | serde_with | no |

| `serde_with` | Enable [`serde_with`](https://docs.rs/serde_with/1.x) 1.x integrations for `bson::DateTime` and `bson::Uuid`.| serde_with | no |
| `serde_with-3` | Enable [`serde_with`](https://docs.rs/serde_with/3.x) 3.x integrations for `bson::DateTime` and `bson::Uuid`. Requires Rust 1.61. | serde_with | no |
## Overview of the BSON Format

BSON, short for Binary JSON, is a binary-encoded serialization of JSON-like documents.
Expand Down
71 changes: 64 additions & 7 deletions src/datetime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -145,20 +145,20 @@ use serde_with::{DeserializeAs, SerializeAs};
/// }
/// # }
/// ```
/// ### The `serde_with` feature flag
/// ### The `serde_with-3` feature flag
///
/// The `serde_with` feature can be enabled to support more ergonomic serde attributes for
/// The `serde_with-3` feature can be enabled to support more ergonomic serde attributes for
/// (de)serializing [`chrono::DateTime`] from/to BSON via the [`serde_with`](https://docs.rs/serde_with/1.11.0/serde_with/)
/// crate. The main benefit of this compared to the regular `serde_helpers` is that `serde_with` can
/// handle nested [`chrono::DateTime`] values (e.g. in [`Option`]), whereas the former only works on
/// fields that are exactly [`chrono::DateTime`].
/// crate. The main benefit of this compared to the regular `serde_helpers` is that `serde_with-3`
/// can handle nested [`chrono::DateTime`] values (e.g. in [`Option`]), whereas the former only
/// works on fields that are exactly [`chrono::DateTime`].
/// ```
/// # #[cfg(all(feature = "chrono-0_4", feature = "serde_with"))]
/// # #[cfg(all(feature = "chrono-0_4", feature = "serde_with-3"))]
/// # {
/// use serde::{Deserialize, Serialize};
/// use bson::doc;
///
/// #[serde_with::serde_as]
/// #[serde_with_3::serde_as]
/// #[derive(Deserialize, Serialize, PartialEq, Debug)]
/// struct Foo {
/// /// Serializes as a BSON datetime rather than using [`chrono::DateTime`]'s serialization
Expand Down Expand Up @@ -482,6 +482,36 @@ impl SerializeAs<chrono::DateTime<Utc>> for crate::DateTime {
}
}

#[cfg(all(feature = "chrono-0_4", feature = "serde_with-3"))]
#[cfg_attr(
docsrs,
doc(cfg(all(feature = "chrono-0_4", feature = "serde_with-3")))
)]
impl<'de> serde_with_3::DeserializeAs<'de, chrono::DateTime<Utc>> for crate::DateTime {
fn deserialize_as<D>(deserializer: D) -> std::result::Result<chrono::DateTime<Utc>, D::Error>
where
D: Deserializer<'de>,
{
let dt = DateTime::deserialize(deserializer)?;
Ok(dt.to_chrono())
}
}

#[cfg(all(feature = "chrono-0_4", feature = "serde_with-3"))]
#[cfg_attr(docsrs, doc(cfg(all(feature = "chrono-0_4", feature = "chrono-0_4"))))]
impl serde_with_3::SerializeAs<chrono::DateTime<Utc>> for crate::DateTime {
fn serialize_as<S>(
source: &chrono::DateTime<Utc>,
serializer: S,
) -> std::result::Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
let dt = DateTime::from_chrono(*source);
dt.serialize(serializer)
}
}

#[cfg(feature = "time-0_3")]
#[cfg_attr(docsrs, doc(cfg(feature = "time-0_3")))]
impl From<crate::DateTime> for time::OffsetDateTime {
Expand Down Expand Up @@ -525,6 +555,33 @@ impl SerializeAs<time::OffsetDateTime> for crate::DateTime {
}
}

#[cfg(all(feature = "time-0_3", feature = "serde_with-3"))]
#[cfg_attr(docsrs, doc(cfg(all(feature = "time-0_3", feature = "serde_with-3"))))]
impl<'de> serde_with_3::DeserializeAs<'de, time::OffsetDateTime> for crate::DateTime {
fn deserialize_as<D>(deserializer: D) -> std::result::Result<time::OffsetDateTime, D::Error>
where
D: Deserializer<'de>,
{
let dt = DateTime::deserialize(deserializer)?;
Ok(dt.to_time_0_3())
}
}

#[cfg(all(feature = "time-0_3", feature = "serde_with-3"))]
#[cfg_attr(docsrs, doc(cfg(all(feature = "time-0_3", feature = "chrono-0_4"))))]
impl serde_with_3::SerializeAs<time::OffsetDateTime> for crate::DateTime {
fn serialize_as<S>(
source: &time::OffsetDateTime,
serializer: S,
) -> std::result::Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
let dt = DateTime::from_time_0_3(*source);
dt.serialize(serializer)
}
}

/// Errors that can occur during [`DateTime`] construction and generation.
#[derive(Clone, Debug)]
#[non_exhaustive]
Expand Down
4 changes: 2 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
//!
//! ## Installation
//! ### Requirements
//! - Rust 1.56+
//! - Rust 1.60+
//!
//! ### Importing
//! This crate is available on [crates.io](https://crates.io/crates/bson). To use it in your application,
Expand Down Expand Up @@ -267,7 +267,7 @@
//!
//! ## Minimum supported Rust version (MSRV)
//!
//! The MSRV for this crate is currently 1.56.0. This will be rarely be increased, and if it ever is,
//! The MSRV for this crate is currently 1.60.0. This will be rarely be increased, and if it ever is,
//! it will only happen in a minor or major version release.

#![allow(clippy::cognitive_complexity, clippy::derive_partial_eq_without_eq)]
Expand Down
36 changes: 30 additions & 6 deletions src/uuid/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,21 +74,21 @@
//! For backwards compatibility, a `uuid-0_8` feature flag can be enabled, which provides the same
//! API for interoperation with version 0.8 of the `uuid` crate.
//!
//! ## The `serde_with` feature flag
//! ## The `serde_with-3` feature flag
//!
//! The `serde_with` feature can be enabled to support more ergonomic serde attributes for
//! The `serde_with-3` feature can be enabled to support more ergonomic serde attributes for
//! (de)serializing [`uuid::Uuid`] from/to BSON via the [`serde_with`](https://docs.rs/serde_with/1.11.0/serde_with/)
//! crate. The main benefit of this compared to the regular `serde_helpers` is that `serde_with` can
//! handle nested [`uuid::Uuid`] values (e.g. in [`Option`]), whereas the former only works on
//! crate. The main benefit of this compared to the regular `serde_helpers` is that `serde_with-3`
//! can handle nested [`uuid::Uuid`] values (e.g. in [`Option`]), whereas the former only works on
//! fields that are exactly [`uuid::Uuid`].
//! ```
//! # #[cfg(all(feature = "uuid-1", feature = "serde_with"))]
//! # #[cfg(all(feature = "uuid-1", feature = "serde_with-3"))]
//! # {
//! # use uuid as uuid;
//! use serde::{Deserialize, Serialize};
//! use bson::doc;
//!
//! #[serde_with::serde_as]
//! #[serde_with_3::serde_as]
//! #[derive(Deserialize, Serialize, PartialEq, Debug)]
//! struct Foo {
//! /// Serializes as a BSON binary rather than using [`uuid::Uuid`]'s serialization
Expand Down Expand Up @@ -509,6 +509,30 @@ macro_rules! trait_impls {
uuid.serialize(serializer)
}
}

#[cfg(all($feat, feature = "serde_with-3"))]
#[cfg_attr(docsrs, doc(cfg(all($feat, feature = "serde_with-3"))))]
impl<'de> serde_with_3::DeserializeAs<'de, $u> for crate::Uuid {
fn deserialize_as<D>(deserializer: D) -> std::result::Result<$u, D::Error>
where
D: serde::Deserializer<'de>,
{
let uuid = Uuid::deserialize(deserializer)?;
Ok(uuid.into())
}
}

#[cfg(all($feat, feature = "serde_with_3"))]
#[cfg_attr(docsrs, doc(cfg(all($feat, feature = "serde_with_3"))))]
impl serde_with_3::SerializeAs<$u> for crate::Uuid {
fn serialize_as<S>(source: &$u, serializer: S) -> std::result::Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
let uuid = Uuid::from(*source);
uuid.serialize(serializer)
}
}
};
}
trait_impls!(feature = "uuid-0_8", uuid_0_8::Uuid);
Expand Down

0 comments on commit 09a8cbb

Please sign in to comment.