From 8cdfa445d6629ffef4cb84967ff7017654045bc2 Mon Sep 17 00:00:00 2001 From: mo khan Date: Wed, 2 Jul 2025 18:36:06 -0600 Subject: chore: add vendor directory --- vendor/time/src/serde/iso8601.rs | 76 +++ vendor/time/src/serde/mod.rs | 535 +++++++++++++++++++++ vendor/time/src/serde/rfc2822.rs | 71 +++ vendor/time/src/serde/rfc3339.rs | 71 +++ vendor/time/src/serde/timestamp/microseconds.rs | 63 +++ vendor/time/src/serde/timestamp/milliseconds.rs | 63 +++ .../time/src/serde/timestamp/milliseconds_i64.rs | 66 +++ vendor/time/src/serde/timestamp/mod.rs | 65 +++ vendor/time/src/serde/timestamp/nanoseconds.rs | 61 +++ vendor/time/src/serde/visitor.rs | 355 ++++++++++++++ 10 files changed, 1426 insertions(+) create mode 100644 vendor/time/src/serde/iso8601.rs create mode 100644 vendor/time/src/serde/mod.rs create mode 100644 vendor/time/src/serde/rfc2822.rs create mode 100644 vendor/time/src/serde/rfc3339.rs create mode 100644 vendor/time/src/serde/timestamp/microseconds.rs create mode 100644 vendor/time/src/serde/timestamp/milliseconds.rs create mode 100644 vendor/time/src/serde/timestamp/milliseconds_i64.rs create mode 100644 vendor/time/src/serde/timestamp/mod.rs create mode 100644 vendor/time/src/serde/timestamp/nanoseconds.rs create mode 100644 vendor/time/src/serde/visitor.rs (limited to 'vendor/time/src/serde') diff --git a/vendor/time/src/serde/iso8601.rs b/vendor/time/src/serde/iso8601.rs new file mode 100644 index 00000000..f08cf511 --- /dev/null +++ b/vendor/time/src/serde/iso8601.rs @@ -0,0 +1,76 @@ +//! Use the well-known [ISO 8601 format] when serializing and deserializing an [`OffsetDateTime`]. +//! +//! Use this module in combination with serde's [`#[with]`][with] attribute. +//! +//! [ISO 8601 format]: https://www.iso.org/iso-8601-date-and-time-format.html +//! [with]: https://serde.rs/field-attrs.html#with + +#[cfg(feature = "parsing")] +use core::marker::PhantomData; + +#[cfg(feature = "formatting")] +use serde::ser::Error as _; +#[cfg(feature = "parsing")] +use serde::Deserializer; +#[cfg(feature = "formatting")] +use serde::{Serialize, Serializer}; + +#[cfg(feature = "parsing")] +use super::Visitor; +use crate::format_description::well_known::iso8601::{Config, EncodedConfig}; +use crate::format_description::well_known::Iso8601; +use crate::OffsetDateTime; + +/// The configuration of ISO 8601 used for serde implementations. +pub(crate) const SERDE_CONFIG: EncodedConfig = + Config::DEFAULT.set_year_is_six_digits(true).encode(); + +/// Serialize an [`OffsetDateTime`] using the well-known ISO 8601 format. +#[cfg(feature = "formatting")] +pub fn serialize( + datetime: &OffsetDateTime, + serializer: S, +) -> Result { + datetime + .format(&Iso8601::) + .map_err(S::Error::custom)? + .serialize(serializer) +} + +/// Deserialize an [`OffsetDateTime`] from its ISO 8601 representation. +#[cfg(feature = "parsing")] +pub fn deserialize<'a, D: Deserializer<'a>>(deserializer: D) -> Result { + deserializer.deserialize_str(Visitor::>(PhantomData)) +} + +/// Use the well-known ISO 8601 format when serializing and deserializing an +/// [`Option`]. +/// +/// Use this module in combination with serde's [`#[with]`][with] attribute. +/// +/// [ISO 8601 format]: https://www.iso.org/iso-8601-date-and-time-format.html +/// [with]: https://serde.rs/field-attrs.html#with +pub mod option { + use super::*; + + /// Serialize an [`Option`] using the well-known ISO 8601 format. + #[cfg(feature = "formatting")] + pub fn serialize( + option: &Option, + serializer: S, + ) -> Result { + option + .map(|odt| odt.format(&Iso8601::)) + .transpose() + .map_err(S::Error::custom)? + .serialize(serializer) + } + + /// Deserialize an [`Option`] from its ISO 8601 representation. + #[cfg(feature = "parsing")] + pub fn deserialize<'a, D: Deserializer<'a>>( + deserializer: D, + ) -> Result, D::Error> { + deserializer.deserialize_option(Visitor::>>(PhantomData)) + } +} diff --git a/vendor/time/src/serde/mod.rs b/vendor/time/src/serde/mod.rs new file mode 100644 index 00000000..72b43721 --- /dev/null +++ b/vendor/time/src/serde/mod.rs @@ -0,0 +1,535 @@ +//! Differential formats for serde. +// This also includes the serde implementations for all types. This doesn't need to be externally +// documented, though. + +// Types with guaranteed stable serde representations. Strings are avoided to allow for optimal +// representations in various binary forms. + +/// Consume the next item in a sequence. +macro_rules! item { + ($seq:expr, $name:literal) => { + $seq.next_element()? + .ok_or_else(|| ::custom(concat!("expected ", $name))) + }; +} + +#[cfg(any(feature = "formatting", feature = "parsing"))] +pub mod iso8601; +#[cfg(any(feature = "formatting", feature = "parsing"))] +pub mod rfc2822; +#[cfg(any(feature = "formatting", feature = "parsing"))] +pub mod rfc3339; +pub mod timestamp; +mod visitor; + +#[cfg(feature = "serde-human-readable")] +use alloc::string::ToString; +use core::marker::PhantomData; + +#[cfg(feature = "serde-human-readable")] +use serde::ser::Error as _; +use serde::{Deserialize, Deserializer, Serialize, Serializer}; +/// Generate a custom serializer and deserializer from a format string or an existing format. +/// +/// The syntax accepted by this macro is the same as [`format_description::parse()`], which can +/// be found in [the book](https://time-rs.github.io/book/api/format-description.html). +/// +/// # Usage +/// +/// Invoked as `serde::format_description!(mod_name, Date, FORMAT)` where `FORMAT` is either a +/// `""` or something that implements +#[cfg_attr( + all(feature = "formatting", feature = "parsing"), + doc = "[`Formattable`](crate::formatting::Formattable) and \ + [`Parsable`](crate::parsing::Parsable)." +)] +#[cfg_attr( + all(feature = "formatting", not(feature = "parsing")), + doc = "[`Formattable`](crate::formatting::Formattable)." +)] +#[cfg_attr( + all(not(feature = "formatting"), feature = "parsing"), + doc = "[`Parsable`](crate::parsing::Parsable)." +)] +/// This puts a module named `mod_name` in the current scope that can be used to format `Date` +/// structs. A submodule (`mod_name::option`) is also generated for `Option`. Both +/// modules are only visible in the current scope by default. To increase visibility, you can +/// specify `pub`, `pub(crate)`, or similar before the module name: +/// `serde::format_description!(pub mod_name, Date, FORMAT)`. +/// +/// The returned `Option` will contain a deserialized value if present and `None` if the field +/// is present but the value is `null` (or the equivalent in other formats). To return `None` +/// when the field is not present, you should use `#[serde(default)]` on the field. +/// +/// # Examples +/// +/// Using a format string: +/// +/// ```rust,no_run +/// # use time::OffsetDateTime; +#[cfg_attr( + all(feature = "formatting", feature = "parsing"), + doc = "use ::serde::{Serialize, Deserialize};" +)] +#[cfg_attr( + all(feature = "formatting", not(feature = "parsing")), + doc = "use ::serde::Serialize;" +)] +#[cfg_attr( + all(not(feature = "formatting"), feature = "parsing"), + doc = "use ::serde::Deserialize;" +)] +/// use time::serde; +/// +/// // Makes a module `mod my_format { ... }`. +/// serde::format_description!(my_format, OffsetDateTime, "hour=[hour], minute=[minute]"); +/// +/// # #[allow(dead_code)] +#[cfg_attr( + all(feature = "formatting", feature = "parsing"), + doc = "#[derive(Serialize, Deserialize)]" +)] +#[cfg_attr( + all(feature = "formatting", not(feature = "parsing")), + doc = "#[derive(Serialize)]" +)] +#[cfg_attr( + all(not(feature = "formatting"), feature = "parsing"), + doc = "#[derive(Deserialize)]" +)] +/// struct SerializesWithCustom { +/// #[serde(with = "my_format")] +/// dt: OffsetDateTime, +/// #[serde(with = "my_format::option")] +/// maybe_dt: Option, +/// } +/// ``` +/// +/// Define the format separately to be used in multiple places: +/// ```rust,no_run +/// # use time::OffsetDateTime; +#[cfg_attr( + all(feature = "formatting", feature = "parsing"), + doc = "use ::serde::{Serialize, Deserialize};" +)] +#[cfg_attr( + all(feature = "formatting", not(feature = "parsing")), + doc = "use ::serde::Serialize;" +)] +#[cfg_attr( + all(not(feature = "formatting"), feature = "parsing"), + doc = "use ::serde::Deserialize;" +)] +/// use time::serde; +/// use time::format_description::BorrowedFormatItem; +/// +/// const DATE_TIME_FORMAT: &[BorrowedFormatItem<'_>] = time::macros::format_description!( +/// "hour=[hour], minute=[minute]" +/// ); +/// +/// // Makes a module `mod my_format { ... }`. +/// serde::format_description!(my_format, OffsetDateTime, DATE_TIME_FORMAT); +/// +/// # #[allow(dead_code)] +#[cfg_attr( + all(feature = "formatting", feature = "parsing"), + doc = "#[derive(Serialize, Deserialize)]" +)] +#[cfg_attr( + all(feature = "formatting", not(feature = "parsing")), + doc = "#[derive(Serialize)]" +)] +#[cfg_attr( + all(not(feature = "formatting"), feature = "parsing"), + doc = "#[derive(Deserialize)]" +)] +/// struct SerializesWithCustom { +/// #[serde(with = "my_format")] +/// dt: OffsetDateTime, +/// #[serde(with = "my_format::option")] +/// maybe_dt: Option, +/// } +/// +/// fn main() { +/// # #[allow(unused_variables)] +/// let str_ts = OffsetDateTime::now_utc().format(DATE_TIME_FORMAT).unwrap(); +/// } +/// ``` +/// +/// Customize the configuration of ISO 8601 formatting/parsing: +/// ```rust,no_run +/// # use time::OffsetDateTime; +#[cfg_attr( + all(feature = "formatting", feature = "parsing"), + doc = "use ::serde::{Serialize, Deserialize};" +)] +#[cfg_attr( + all(feature = "formatting", not(feature = "parsing")), + doc = "use ::serde::Serialize;" +)] +#[cfg_attr( + all(not(feature = "formatting"), feature = "parsing"), + doc = "use ::serde::Deserialize;" +)] +/// use time::serde; +/// use time::format_description::well_known::{iso8601, Iso8601}; +/// +/// # #[allow(dead_code)] +/// const CONFIG: iso8601::EncodedConfig = iso8601::Config::DEFAULT +/// .set_year_is_six_digits(false) +/// .encode(); +/// # #[allow(dead_code)] +/// const FORMAT: Iso8601 = Iso8601::; +/// +/// // Makes a module `mod my_format { ... }`. +/// serde::format_description!(my_format, OffsetDateTime, FORMAT); +/// +/// # #[allow(dead_code)] +#[cfg_attr( + all(feature = "formatting", feature = "parsing"), + doc = "#[derive(Serialize, Deserialize)]" +)] +#[cfg_attr( + all(feature = "formatting", not(feature = "parsing")), + doc = "#[derive(Serialize)]" +)] +#[cfg_attr( + all(not(feature = "formatting"), feature = "parsing"), + doc = "#[derive(Deserialize)]" +)] +/// struct SerializesWithCustom { +/// #[serde(with = "my_format")] +/// dt: OffsetDateTime, +/// #[serde(with = "my_format::option")] +/// maybe_dt: Option, +/// } +/// # fn main() {} +/// ``` +/// +/// [`format_description::parse()`]: crate::format_description::parse() +#[cfg(all(feature = "macros", any(feature = "formatting", feature = "parsing")))] +pub use time_macros::serde_format_description as format_description; + +use self::visitor::Visitor; +#[cfg(feature = "parsing")] +use crate::format_description::{modifier, BorrowedFormatItem, Component}; +use crate::{ + Date, Duration, Month, OffsetDateTime, PrimitiveDateTime, Time, UtcDateTime, UtcOffset, Weekday, +}; + +/// The format used when serializing and deserializing a human-readable `Date`. +#[cfg(feature = "parsing")] +const DATE_FORMAT: &[BorrowedFormatItem<'_>] = &[ + BorrowedFormatItem::Component(Component::Year(modifier::Year::default())), + BorrowedFormatItem::Literal(b"-"), + BorrowedFormatItem::Component(Component::Month(modifier::Month::default())), + BorrowedFormatItem::Literal(b"-"), + BorrowedFormatItem::Component(Component::Day(modifier::Day::default())), +]; + +impl Serialize for Date { + fn serialize(&self, serializer: S) -> Result { + #[cfg(feature = "serde-human-readable")] + if serializer.is_human_readable() { + let Ok(s) = self.format(&DATE_FORMAT) else { + return Err(S::Error::custom("failed formatting `Date`")); + }; + return serializer.serialize_str(&s); + } + + (self.year(), self.ordinal()).serialize(serializer) + } +} + +impl<'a> Deserialize<'a> for Date { + fn deserialize>(deserializer: D) -> Result { + if cfg!(feature = "serde-human-readable") && deserializer.is_human_readable() { + deserializer.deserialize_any(Visitor::(PhantomData)) + } else { + deserializer.deserialize_tuple(2, Visitor::(PhantomData)) + } + } +} + +impl Serialize for Duration { + fn serialize(&self, serializer: S) -> Result { + #[cfg(feature = "serde-human-readable")] + if serializer.is_human_readable() { + return serializer.collect_str(&format_args!( + "{}{}.{:>09}", + if self.is_negative() { "-" } else { "" }, + self.whole_seconds().unsigned_abs(), + self.subsec_nanoseconds().abs(), + )); + } + + (self.whole_seconds(), self.subsec_nanoseconds()).serialize(serializer) + } +} + +impl<'a> Deserialize<'a> for Duration { + fn deserialize>(deserializer: D) -> Result { + if cfg!(feature = "serde-human-readable") && deserializer.is_human_readable() { + deserializer.deserialize_any(Visitor::(PhantomData)) + } else { + deserializer.deserialize_tuple(2, Visitor::(PhantomData)) + } + } +} + +/// The format used when serializing and deserializing a human-readable `OffsetDateTime`. +#[cfg(feature = "parsing")] +const OFFSET_DATE_TIME_FORMAT: &[BorrowedFormatItem<'_>] = &[ + BorrowedFormatItem::Compound(DATE_FORMAT), + BorrowedFormatItem::Literal(b" "), + BorrowedFormatItem::Compound(TIME_FORMAT), + BorrowedFormatItem::Literal(b" "), + BorrowedFormatItem::Compound(UTC_OFFSET_FORMAT), +]; + +impl Serialize for OffsetDateTime { + fn serialize(&self, serializer: S) -> Result { + #[cfg(feature = "serde-human-readable")] + if serializer.is_human_readable() { + let Ok(s) = self.format(&OFFSET_DATE_TIME_FORMAT) else { + return Err(S::Error::custom("failed formatting `OffsetDateTime`")); + }; + return serializer.serialize_str(&s); + } + + ( + self.year(), + self.ordinal(), + self.hour(), + self.minute(), + self.second(), + self.nanosecond(), + self.offset().whole_hours(), + self.offset().minutes_past_hour(), + self.offset().seconds_past_minute(), + ) + .serialize(serializer) + } +} + +impl<'a> Deserialize<'a> for OffsetDateTime { + fn deserialize>(deserializer: D) -> Result { + if cfg!(feature = "serde-human-readable") && deserializer.is_human_readable() { + deserializer.deserialize_any(Visitor::(PhantomData)) + } else { + deserializer.deserialize_tuple(9, Visitor::(PhantomData)) + } + } +} + +/// The format used when serializing and deserializing a human-readable `PrimitiveDateTime`. +#[cfg(feature = "parsing")] +const PRIMITIVE_DATE_TIME_FORMAT: &[BorrowedFormatItem<'_>] = &[ + BorrowedFormatItem::Compound(DATE_FORMAT), + BorrowedFormatItem::Literal(b" "), + BorrowedFormatItem::Compound(TIME_FORMAT), +]; + +impl Serialize for PrimitiveDateTime { + fn serialize(&self, serializer: S) -> Result { + #[cfg(feature = "serde-human-readable")] + if serializer.is_human_readable() { + let Ok(s) = self.format(&PRIMITIVE_DATE_TIME_FORMAT) else { + return Err(S::Error::custom("failed formatting `PrimitiveDateTime`")); + }; + return serializer.serialize_str(&s); + } + + ( + self.year(), + self.ordinal(), + self.hour(), + self.minute(), + self.second(), + self.nanosecond(), + ) + .serialize(serializer) + } +} + +impl<'a> Deserialize<'a> for PrimitiveDateTime { + fn deserialize>(deserializer: D) -> Result { + if cfg!(feature = "serde-human-readable") && deserializer.is_human_readable() { + deserializer.deserialize_any(Visitor::(PhantomData)) + } else { + deserializer.deserialize_tuple(6, Visitor::(PhantomData)) + } + } +} + +/// The format used when serializing and deserializing a human-readable `UtcDateTime`. +#[cfg(feature = "parsing")] +const UTC_DATE_TIME_FORMAT: &[BorrowedFormatItem<'_>] = PRIMITIVE_DATE_TIME_FORMAT; + +impl Serialize for UtcDateTime { + fn serialize(&self, serializer: S) -> Result { + #[cfg(feature = "serde-human-readable")] + if serializer.is_human_readable() { + let Ok(s) = self.format(&PRIMITIVE_DATE_TIME_FORMAT) else { + return Err(S::Error::custom("failed formatting `UtcDateTime`")); + }; + return serializer.serialize_str(&s); + } + + ( + self.year(), + self.ordinal(), + self.hour(), + self.minute(), + self.second(), + self.nanosecond(), + ) + .serialize(serializer) + } +} + +impl<'a> Deserialize<'a> for UtcDateTime { + fn deserialize>(deserializer: D) -> Result { + if cfg!(feature = "serde-human-readable") && deserializer.is_human_readable() { + deserializer.deserialize_any(Visitor::(PhantomData)) + } else { + deserializer.deserialize_tuple(6, Visitor::(PhantomData)) + } + } +} + +/// The format used when serializing and deserializing a human-readable `Time`. +#[cfg(feature = "parsing")] +const TIME_FORMAT: &[BorrowedFormatItem<'_>] = &[ + BorrowedFormatItem::Component(Component::Hour(modifier::Hour::default())), + BorrowedFormatItem::Literal(b":"), + BorrowedFormatItem::Component(Component::Minute(modifier::Minute::default())), + BorrowedFormatItem::Literal(b":"), + BorrowedFormatItem::Component(Component::Second(modifier::Second::default())), + BorrowedFormatItem::Literal(b"."), + BorrowedFormatItem::Component(Component::Subsecond(modifier::Subsecond::default())), +]; + +impl Serialize for Time { + fn serialize(&self, serializer: S) -> Result { + #[cfg(feature = "serde-human-readable")] + if serializer.is_human_readable() { + let Ok(s) = self.format(&TIME_FORMAT) else { + return Err(S::Error::custom("failed formatting `Time`")); + }; + return serializer.serialize_str(&s); + } + + (self.hour(), self.minute(), self.second(), self.nanosecond()).serialize(serializer) + } +} + +impl<'a> Deserialize<'a> for Time { + fn deserialize>(deserializer: D) -> Result { + if cfg!(feature = "serde-human-readable") && deserializer.is_human_readable() { + deserializer.deserialize_any(Visitor::(PhantomData)) + } else { + deserializer.deserialize_tuple(4, Visitor::(PhantomData)) + } + } +} + +// FIXME: turn these constants into `const { ... }` blocks once we can depend on Rust 1.79. +#[cfg(feature = "parsing")] +const UTC_OFFSET_HOUR: modifier::OffsetHour = { + let mut m = modifier::OffsetHour::default(); + m.sign_is_mandatory = true; + m +}; +#[cfg(feature = "parsing")] +const UTC_OFFSET_MINUTE: modifier::OffsetMinute = modifier::OffsetMinute::default(); +#[cfg(feature = "parsing")] +const UTC_OFFSET_SECOND: modifier::OffsetSecond = modifier::OffsetSecond::default(); +/// The format used when serializing and deserializing a human-readable `UtcOffset`. +#[cfg(feature = "parsing")] +const UTC_OFFSET_FORMAT: &[BorrowedFormatItem<'_>] = &[ + BorrowedFormatItem::Component(Component::OffsetHour(UTC_OFFSET_HOUR)), + BorrowedFormatItem::Optional(&BorrowedFormatItem::Compound(&[ + BorrowedFormatItem::Literal(b":"), + BorrowedFormatItem::Component(Component::OffsetMinute(UTC_OFFSET_MINUTE)), + BorrowedFormatItem::Optional(&BorrowedFormatItem::Compound(&[ + BorrowedFormatItem::Literal(b":"), + BorrowedFormatItem::Component(Component::OffsetSecond(UTC_OFFSET_SECOND)), + ])), + ])), +]; + +impl Serialize for UtcOffset { + fn serialize(&self, serializer: S) -> Result { + #[cfg(feature = "serde-human-readable")] + if serializer.is_human_readable() { + let Ok(s) = self.format(&UTC_OFFSET_FORMAT) else { + return Err(S::Error::custom("failed formatting `UtcOffset`")); + }; + return serializer.serialize_str(&s); + } + + ( + self.whole_hours(), + self.minutes_past_hour(), + self.seconds_past_minute(), + ) + .serialize(serializer) + } +} + +impl<'a> Deserialize<'a> for UtcOffset { + fn deserialize>(deserializer: D) -> Result { + if cfg!(feature = "serde-human-readable") && deserializer.is_human_readable() { + deserializer.deserialize_any(Visitor::(PhantomData)) + } else { + deserializer.deserialize_tuple(3, Visitor::(PhantomData)) + } + } +} + +impl Serialize for Weekday { + fn serialize(&self, serializer: S) -> Result { + #[cfg(feature = "serde-human-readable")] + if serializer.is_human_readable() { + #[cfg(not(feature = "std"))] + use alloc::string::ToString; + return self.to_string().serialize(serializer); + } + + self.number_from_monday().serialize(serializer) + } +} + +impl<'a> Deserialize<'a> for Weekday { + fn deserialize>(deserializer: D) -> Result { + if cfg!(feature = "serde-human-readable") && deserializer.is_human_readable() { + deserializer.deserialize_any(Visitor::(PhantomData)) + } else { + deserializer.deserialize_u8(Visitor::(PhantomData)) + } + } +} + +impl Serialize for Month { + fn serialize(&self, serializer: S) -> Result { + #[cfg(feature = "serde-human-readable")] + if serializer.is_human_readable() { + #[cfg(not(feature = "std"))] + use alloc::string::String; + return self.to_string().serialize(serializer); + } + + u8::from(*self).serialize(serializer) + } +} + +impl<'a> Deserialize<'a> for Month { + fn deserialize>(deserializer: D) -> Result { + if cfg!(feature = "serde-human-readable") && deserializer.is_human_readable() { + deserializer.deserialize_any(Visitor::(PhantomData)) + } else { + deserializer.deserialize_u8(Visitor::(PhantomData)) + } + } +} diff --git a/vendor/time/src/serde/rfc2822.rs b/vendor/time/src/serde/rfc2822.rs new file mode 100644 index 00000000..c6716d58 --- /dev/null +++ b/vendor/time/src/serde/rfc2822.rs @@ -0,0 +1,71 @@ +//! Use the well-known [RFC2822 format] when serializing and deserializing an [`OffsetDateTime`]. +//! +//! Use this module in combination with serde's [`#[with]`][with] attribute. +//! +//! [RFC2822 format]: https://tools.ietf.org/html/rfc2822#section-3.3 +//! [with]: https://serde.rs/field-attrs.html#with + +#[cfg(feature = "parsing")] +use core::marker::PhantomData; + +#[cfg(feature = "formatting")] +use serde::ser::Error as _; +#[cfg(feature = "parsing")] +use serde::Deserializer; +#[cfg(feature = "formatting")] +use serde::{Serialize, Serializer}; + +#[cfg(feature = "parsing")] +use super::Visitor; +use crate::format_description::well_known::Rfc2822; +use crate::OffsetDateTime; + +/// Serialize an [`OffsetDateTime`] using the well-known RFC2822 format. +#[cfg(feature = "formatting")] +pub fn serialize( + datetime: &OffsetDateTime, + serializer: S, +) -> Result { + datetime + .format(&Rfc2822) + .map_err(S::Error::custom)? + .serialize(serializer) +} + +/// Deserialize an [`OffsetDateTime`] from its RFC2822 representation. +#[cfg(feature = "parsing")] +pub fn deserialize<'a, D: Deserializer<'a>>(deserializer: D) -> Result { + deserializer.deserialize_str(Visitor::(PhantomData)) +} + +/// Use the well-known [RFC2822 format] when serializing and deserializing an +/// [`Option`]. +/// +/// Use this module in combination with serde's [`#[with]`][with] attribute. +/// +/// [RFC2822 format]: https://tools.ietf.org/html/rfc2822#section-3.3 +/// [with]: https://serde.rs/field-attrs.html#with +pub mod option { + use super::*; + + /// Serialize an [`Option`] using the well-known RFC2822 format. + #[cfg(feature = "formatting")] + pub fn serialize( + option: &Option, + serializer: S, + ) -> Result { + option + .map(|odt| odt.format(&Rfc2822)) + .transpose() + .map_err(S::Error::custom)? + .serialize(serializer) + } + + /// Deserialize an [`Option`] from its RFC2822 representation. + #[cfg(feature = "parsing")] + pub fn deserialize<'a, D: Deserializer<'a>>( + deserializer: D, + ) -> Result, D::Error> { + deserializer.deserialize_option(Visitor::>(PhantomData)) + } +} diff --git a/vendor/time/src/serde/rfc3339.rs b/vendor/time/src/serde/rfc3339.rs new file mode 100644 index 00000000..4cccd635 --- /dev/null +++ b/vendor/time/src/serde/rfc3339.rs @@ -0,0 +1,71 @@ +//! Use the well-known [RFC3339 format] when serializing and deserializing an [`OffsetDateTime`]. +//! +//! Use this module in combination with serde's [`#[with]`][with] attribute. +//! +//! [RFC3339 format]: https://tools.ietf.org/html/rfc3339#section-5.6 +//! [with]: https://serde.rs/field-attrs.html#with + +#[cfg(feature = "parsing")] +use core::marker::PhantomData; + +#[cfg(feature = "formatting")] +use serde::ser::Error as _; +#[cfg(feature = "parsing")] +use serde::Deserializer; +#[cfg(feature = "formatting")] +use serde::{Serialize, Serializer}; + +#[cfg(feature = "parsing")] +use super::Visitor; +use crate::format_description::well_known::Rfc3339; +use crate::OffsetDateTime; + +/// Serialize an [`OffsetDateTime`] using the well-known RFC3339 format. +#[cfg(feature = "formatting")] +pub fn serialize( + datetime: &OffsetDateTime, + serializer: S, +) -> Result { + datetime + .format(&Rfc3339) + .map_err(S::Error::custom)? + .serialize(serializer) +} + +/// Deserialize an [`OffsetDateTime`] from its RFC3339 representation. +#[cfg(feature = "parsing")] +pub fn deserialize<'a, D: Deserializer<'a>>(deserializer: D) -> Result { + deserializer.deserialize_str(Visitor::(PhantomData)) +} + +/// Use the well-known [RFC3339 format] when serializing and deserializing an +/// [`Option`]. +/// +/// Use this module in combination with serde's [`#[with]`][with] attribute. +/// +/// [RFC3339 format]: https://tools.ietf.org/html/rfc3339#section-5.6 +/// [with]: https://serde.rs/field-attrs.html#with +pub mod option { + use super::*; + + /// Serialize an [`Option`] using the well-known RFC3339 format. + #[cfg(feature = "formatting")] + pub fn serialize( + option: &Option, + serializer: S, + ) -> Result { + option + .map(|odt| odt.format(&Rfc3339)) + .transpose() + .map_err(S::Error::custom)? + .serialize(serializer) + } + + /// Deserialize an [`Option`] from its RFC3339 representation. + #[cfg(feature = "parsing")] + pub fn deserialize<'a, D: Deserializer<'a>>( + deserializer: D, + ) -> Result, D::Error> { + deserializer.deserialize_option(Visitor::>(PhantomData)) + } +} diff --git a/vendor/time/src/serde/timestamp/microseconds.rs b/vendor/time/src/serde/timestamp/microseconds.rs new file mode 100644 index 00000000..65c603ec --- /dev/null +++ b/vendor/time/src/serde/timestamp/microseconds.rs @@ -0,0 +1,63 @@ +//! Treat an [`OffsetDateTime`] as a [Unix timestamp] with microseconds for +//! the purposes of serde. +//! +//! Use this module in combination with serde's [`#[with]`][with] attribute. +//! +//! When deserializing, the offset is assumed to be UTC. +//! +//! [Unix timestamp]: https://en.wikipedia.org/wiki/Unix_time +//! [with]: https://serde.rs/field-attrs.html#with + +use serde::{de, Deserialize, Deserializer, Serialize, Serializer}; + +use crate::OffsetDateTime; + +/// Serialize an `OffsetDateTime` as its Unix timestamp with microseconds +pub fn serialize( + datetime: &OffsetDateTime, + serializer: S, +) -> Result { + let timestamp = datetime.unix_timestamp_nanos() / 1_000; + timestamp.serialize(serializer) +} + +/// Deserialize an `OffsetDateTime` from its Unix timestamp with microseconds +pub fn deserialize<'a, D: Deserializer<'a>>(deserializer: D) -> Result { + let value: i128 = <_>::deserialize(deserializer)?; + OffsetDateTime::from_unix_timestamp_nanos(value * 1_000) + .map_err(|err| de::Error::invalid_value(de::Unexpected::Signed(err.value), &err)) +} + +/// Treat an `Option` as a [Unix timestamp] with microseconds +/// for the purposes of serde. +/// +/// Use this module in combination with serde's [`#[with]`][with] attribute. +/// +/// When deserializing, the offset is assumed to be UTC. +/// +/// [Unix timestamp]: https://en.wikipedia.org/wiki/Unix_time +/// [with]: https://serde.rs/field-attrs.html#with +pub mod option { + #[allow(clippy::wildcard_imports)] + use super::*; + + /// Serialize an `Option` as its Unix timestamp with microseconds + pub fn serialize( + option: &Option, + serializer: S, + ) -> Result { + option + .map(|timestamp| timestamp.unix_timestamp_nanos() / 1_000) + .serialize(serializer) + } + + /// Deserialize an `Option` from its Unix timestamp with microseconds + pub fn deserialize<'a, D: Deserializer<'a>>( + deserializer: D, + ) -> Result, D::Error> { + Option::deserialize(deserializer)? + .map(|value: i128| OffsetDateTime::from_unix_timestamp_nanos(value * 1_000)) + .transpose() + .map_err(|err| de::Error::invalid_value(de::Unexpected::Signed(err.value), &err)) + } +} diff --git a/vendor/time/src/serde/timestamp/milliseconds.rs b/vendor/time/src/serde/timestamp/milliseconds.rs new file mode 100644 index 00000000..e571b6c9 --- /dev/null +++ b/vendor/time/src/serde/timestamp/milliseconds.rs @@ -0,0 +1,63 @@ +//! Treat an [`OffsetDateTime`] as a [Unix timestamp] with milliseconds for +//! the purposes of serde. +//! +//! Use this module in combination with serde's [`#[with]`][with] attribute. +//! +//! When deserializing, the offset is assumed to be UTC. +//! +//! [Unix timestamp]: https://en.wikipedia.org/wiki/Unix_time +//! [with]: https://serde.rs/field-attrs.html#with + +use serde::{de, Deserialize, Deserializer, Serialize, Serializer}; + +use crate::OffsetDateTime; + +/// Serialize an `OffsetDateTime` as its Unix timestamp with milliseconds +pub fn serialize( + datetime: &OffsetDateTime, + serializer: S, +) -> Result { + let timestamp = datetime.unix_timestamp_nanos() / 1_000_000; + timestamp.serialize(serializer) +} + +/// Deserialize an `OffsetDateTime` from its Unix timestamp with milliseconds +pub fn deserialize<'a, D: Deserializer<'a>>(deserializer: D) -> Result { + let value: i128 = <_>::deserialize(deserializer)?; + OffsetDateTime::from_unix_timestamp_nanos(value * 1_000_000) + .map_err(|err| de::Error::invalid_value(de::Unexpected::Signed(err.value), &err)) +} + +/// Treat an `Option` as a [Unix timestamp] with milliseconds +/// for the purposes of serde. +/// +/// Use this module in combination with serde's [`#[with]`][with] attribute. +/// +/// When deserializing, the offset is assumed to be UTC. +/// +/// [Unix timestamp]: https://en.wikipedia.org/wiki/Unix_time +/// [with]: https://serde.rs/field-attrs.html#with +pub mod option { + #[allow(clippy::wildcard_imports)] + use super::*; + + /// Serialize an `Option` as its Unix timestamp with milliseconds + pub fn serialize( + option: &Option, + serializer: S, + ) -> Result { + option + .map(|timestamp| timestamp.unix_timestamp_nanos() / 1_000_000) + .serialize(serializer) + } + + /// Deserialize an `Option` from its Unix timestamp with milliseconds + pub fn deserialize<'a, D: Deserializer<'a>>( + deserializer: D, + ) -> Result, D::Error> { + Option::deserialize(deserializer)? + .map(|value: i128| OffsetDateTime::from_unix_timestamp_nanos(value * 1_000_000)) + .transpose() + .map_err(|err| de::Error::invalid_value(de::Unexpected::Signed(err.value), &err)) + } +} diff --git a/vendor/time/src/serde/timestamp/milliseconds_i64.rs b/vendor/time/src/serde/timestamp/milliseconds_i64.rs new file mode 100644 index 00000000..59f44644 --- /dev/null +++ b/vendor/time/src/serde/timestamp/milliseconds_i64.rs @@ -0,0 +1,66 @@ +//! Treat an [`OffsetDateTime`] as a [Unix timestamp] with milliseconds for +//! the purposes of serde. +//! +//! Use this module in combination with serde's [`#[with]`][with] attribute. +//! +//! When deserializing, the offset is assumed to be UTC. +//! +//! [Unix timestamp]: https://en.wikipedia.org/wiki/Unix_time +//! [with]: https://serde.rs/field-attrs.html#with + +use num_conv::prelude::*; +use serde::{de, Deserialize, Deserializer, Serialize, Serializer}; + +use crate::OffsetDateTime; + +/// Serialize an `OffsetDateTime` as its Unix timestamp with milliseconds +pub fn serialize( + datetime: &OffsetDateTime, + serializer: S, +) -> Result { + let timestamp = (datetime.unix_timestamp_nanos() / 1_000_000).truncate::(); + timestamp.serialize(serializer) +} + +/// Deserialize an `OffsetDateTime` from its Unix timestamp with milliseconds +pub fn deserialize<'a, D: Deserializer<'a>>(deserializer: D) -> Result { + let value: i64 = <_>::deserialize(deserializer)?; + OffsetDateTime::from_unix_timestamp_nanos(value.extend::() * 1_000_000) + .map_err(|err| de::Error::invalid_value(de::Unexpected::Signed(err.value), &err)) +} + +/// Treat an `Option` as a [Unix timestamp] with milliseconds +/// for the purposes of serde. +/// +/// Use this module in combination with serde's [`#[with]`][with] attribute. +/// +/// When deserializing, the offset is assumed to be UTC. +/// +/// [Unix timestamp]: https://en.wikipedia.org/wiki/Unix_time +/// [with]: https://serde.rs/field-attrs.html#with +pub mod option { + #[allow(clippy::wildcard_imports)] + use super::*; + + /// Serialize an `Option` as its Unix timestamp with milliseconds + pub fn serialize( + option: &Option, + serializer: S, + ) -> Result { + option + .map(|timestamp| (timestamp.unix_timestamp_nanos() / 1_000_000).truncate::()) + .serialize(serializer) + } + + /// Deserialize an `Option` from its Unix timestamp with milliseconds + pub fn deserialize<'a, D: Deserializer<'a>>( + deserializer: D, + ) -> Result, D::Error> { + Option::deserialize(deserializer)? + .map(|value: i64| { + OffsetDateTime::from_unix_timestamp_nanos(value.extend::() * 1_000_000) + }) + .transpose() + .map_err(|err| de::Error::invalid_value(de::Unexpected::Signed(err.value), &err)) + } +} diff --git a/vendor/time/src/serde/timestamp/mod.rs b/vendor/time/src/serde/timestamp/mod.rs new file mode 100644 index 00000000..d27836b6 --- /dev/null +++ b/vendor/time/src/serde/timestamp/mod.rs @@ -0,0 +1,65 @@ +//! Treat an [`OffsetDateTime`] as a [Unix timestamp] for the purposes of serde. +//! +//! Use this module in combination with serde's [`#[with]`][with] attribute. +//! +//! When deserializing, the offset is assumed to be UTC. +//! +//! [Unix timestamp]: https://en.wikipedia.org/wiki/Unix_time +//! [with]: https://serde.rs/field-attrs.html#with + +pub mod microseconds; +pub mod milliseconds; +pub mod milliseconds_i64; +pub mod nanoseconds; + +use serde::{de, Deserialize, Deserializer, Serialize, Serializer}; + +use crate::OffsetDateTime; + +/// Serialize an `OffsetDateTime` as its Unix timestamp +pub fn serialize( + datetime: &OffsetDateTime, + serializer: S, +) -> Result { + datetime.unix_timestamp().serialize(serializer) +} + +/// Deserialize an `OffsetDateTime` from its Unix timestamp +pub fn deserialize<'a, D: Deserializer<'a>>(deserializer: D) -> Result { + OffsetDateTime::from_unix_timestamp(<_>::deserialize(deserializer)?) + .map_err(|err| de::Error::invalid_value(de::Unexpected::Signed(err.value), &err)) +} + +/// Treat an `Option` as a [Unix timestamp] for the purposes of +/// serde. +/// +/// Use this module in combination with serde's [`#[with]`][with] attribute. +/// +/// When deserializing, the offset is assumed to be UTC. +/// +/// [Unix timestamp]: https://en.wikipedia.org/wiki/Unix_time +/// [with]: https://serde.rs/field-attrs.html#with +pub mod option { + #[allow(clippy::wildcard_imports)] + use super::*; + + /// Serialize an `Option` as its Unix timestamp + pub fn serialize( + option: &Option, + serializer: S, + ) -> Result { + option + .map(OffsetDateTime::unix_timestamp) + .serialize(serializer) + } + + /// Deserialize an `Option` from its Unix timestamp + pub fn deserialize<'a, D: Deserializer<'a>>( + deserializer: D, + ) -> Result, D::Error> { + Option::deserialize(deserializer)? + .map(OffsetDateTime::from_unix_timestamp) + .transpose() + .map_err(|err| de::Error::invalid_value(de::Unexpected::Signed(err.value), &err)) + } +} diff --git a/vendor/time/src/serde/timestamp/nanoseconds.rs b/vendor/time/src/serde/timestamp/nanoseconds.rs new file mode 100644 index 00000000..c71d1e7c --- /dev/null +++ b/vendor/time/src/serde/timestamp/nanoseconds.rs @@ -0,0 +1,61 @@ +//! Treat an [`OffsetDateTime`] as a [Unix timestamp] with nanoseconds for +//! the purposes of serde. +//! +//! Use this module in combination with serde's [`#[with]`][with] attribute. +//! +//! When deserializing, the offset is assumed to be UTC. +//! +//! [Unix timestamp]: https://en.wikipedia.org/wiki/Unix_time +//! [with]: https://serde.rs/field-attrs.html#with + +use serde::{de, Deserialize, Deserializer, Serialize, Serializer}; + +use crate::OffsetDateTime; + +/// Serialize an `OffsetDateTime` as its Unix timestamp with nanoseconds +pub fn serialize( + datetime: &OffsetDateTime, + serializer: S, +) -> Result { + datetime.unix_timestamp_nanos().serialize(serializer) +} + +/// Deserialize an `OffsetDateTime` from its Unix timestamp with nanoseconds +pub fn deserialize<'a, D: Deserializer<'a>>(deserializer: D) -> Result { + OffsetDateTime::from_unix_timestamp_nanos(<_>::deserialize(deserializer)?) + .map_err(|err| de::Error::invalid_value(de::Unexpected::Signed(err.value), &err)) +} + +/// Treat an `Option` as a [Unix timestamp] with nanoseconds +/// for the purposes of serde. +/// +/// Use this module in combination with serde's [`#[with]`][with] attribute. +/// +/// When deserializing, the offset is assumed to be UTC. +/// +/// [Unix timestamp]: https://en.wikipedia.org/wiki/Unix_time +/// [with]: https://serde.rs/field-attrs.html#with +pub mod option { + #[allow(clippy::wildcard_imports)] + use super::*; + + /// Serialize an `Option` as its Unix timestamp with nanoseconds + pub fn serialize( + option: &Option, + serializer: S, + ) -> Result { + option + .map(OffsetDateTime::unix_timestamp_nanos) + .serialize(serializer) + } + + /// Deserialize an `Option` from its Unix timestamp with nanoseconds + pub fn deserialize<'a, D: Deserializer<'a>>( + deserializer: D, + ) -> Result, D::Error> { + Option::deserialize(deserializer)? + .map(OffsetDateTime::from_unix_timestamp_nanos) + .transpose() + .map_err(|err| de::Error::invalid_value(de::Unexpected::Signed(err.value), &err)) + } +} diff --git a/vendor/time/src/serde/visitor.rs b/vendor/time/src/serde/visitor.rs new file mode 100644 index 00000000..b7034020 --- /dev/null +++ b/vendor/time/src/serde/visitor.rs @@ -0,0 +1,355 @@ +//! Serde visitor for various types. + +use core::fmt; +use core::marker::PhantomData; + +use serde::de; +#[cfg(feature = "parsing")] +use serde::Deserializer; + +#[cfg(feature = "parsing")] +use super::{ + DATE_FORMAT, OFFSET_DATE_TIME_FORMAT, PRIMITIVE_DATE_TIME_FORMAT, TIME_FORMAT, + UTC_DATE_TIME_FORMAT, UTC_OFFSET_FORMAT, +}; +use crate::error::ComponentRange; +#[cfg(feature = "parsing")] +use crate::format_description::well_known::*; +use crate::{ + Date, Duration, Month, OffsetDateTime, PrimitiveDateTime, Time, UtcDateTime, UtcOffset, Weekday, +}; + +/// A serde visitor for various types. +pub(super) struct Visitor(pub(super) PhantomData); + +impl<'a> de::Visitor<'a> for Visitor { + type Value = Date; + + fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + formatter.write_str("a `Date`") + } + + #[cfg(feature = "parsing")] + fn visit_str(self, value: &str) -> Result { + Date::parse(value, &DATE_FORMAT).map_err(E::custom) + } + + fn visit_seq>(self, mut seq: A) -> Result { + let year = item!(seq, "year")?; + let ordinal = item!(seq, "day of year")?; + Date::from_ordinal_date(year, ordinal).map_err(ComponentRange::into_de_error) + } +} + +impl<'a> de::Visitor<'a> for Visitor { + type Value = Duration; + + fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + formatter.write_str("a `Duration`") + } + + fn visit_str(self, value: &str) -> Result { + let (seconds, nanoseconds) = value.split_once('.').ok_or_else(|| { + de::Error::invalid_value(de::Unexpected::Str(value), &"a decimal point") + })?; + + let seconds = seconds + .parse() + .map_err(|_| de::Error::invalid_value(de::Unexpected::Str(seconds), &"seconds"))?; + let mut nanoseconds = nanoseconds.parse().map_err(|_| { + de::Error::invalid_value(de::Unexpected::Str(nanoseconds), &"nanoseconds") + })?; + + if seconds < 0 + // make sure sign does not disappear when seconds == 0 + || (seconds == 0 && value.starts_with("-")) + { + nanoseconds *= -1; + } + + Ok(Duration::new(seconds, nanoseconds)) + } + + fn visit_seq>(self, mut seq: A) -> Result { + let seconds = item!(seq, "seconds")?; + let nanoseconds = item!(seq, "nanoseconds")?; + Ok(Duration::new(seconds, nanoseconds)) + } +} + +impl<'a> de::Visitor<'a> for Visitor { + type Value = OffsetDateTime; + + fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + formatter.write_str("an `OffsetDateTime`") + } + + #[cfg(feature = "parsing")] + fn visit_str(self, value: &str) -> Result { + OffsetDateTime::parse(value, &OFFSET_DATE_TIME_FORMAT).map_err(E::custom) + } + + fn visit_seq>(self, mut seq: A) -> Result { + let year = item!(seq, "year")?; + let ordinal = item!(seq, "day of year")?; + let hour = item!(seq, "hour")?; + let minute = item!(seq, "minute")?; + let second = item!(seq, "second")?; + let nanosecond = item!(seq, "nanosecond")?; + let offset_hours = item!(seq, "offset hours")?; + let offset_minutes = item!(seq, "offset minutes")?; + let offset_seconds = item!(seq, "offset seconds")?; + + Date::from_ordinal_date(year, ordinal) + .and_then(|date| date.with_hms_nano(hour, minute, second, nanosecond)) + .and_then(|datetime| { + UtcOffset::from_hms(offset_hours, offset_minutes, offset_seconds) + .map(|offset| datetime.assume_offset(offset)) + }) + .map_err(ComponentRange::into_de_error) + } +} + +impl<'a> de::Visitor<'a> for Visitor { + type Value = PrimitiveDateTime; + + fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + formatter.write_str("a `PrimitiveDateTime`") + } + + #[cfg(feature = "parsing")] + fn visit_str(self, value: &str) -> Result { + PrimitiveDateTime::parse(value, &PRIMITIVE_DATE_TIME_FORMAT).map_err(E::custom) + } + + fn visit_seq>(self, mut seq: A) -> Result { + let year = item!(seq, "year")?; + let ordinal = item!(seq, "day of year")?; + let hour = item!(seq, "hour")?; + let minute = item!(seq, "minute")?; + let second = item!(seq, "second")?; + let nanosecond = item!(seq, "nanosecond")?; + + Date::from_ordinal_date(year, ordinal) + .and_then(|date| date.with_hms_nano(hour, minute, second, nanosecond)) + .map_err(ComponentRange::into_de_error) + } +} + +impl<'a> de::Visitor<'a> for Visitor { + type Value = UtcDateTime; + + fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + formatter.write_str("a `PrimitiveDateTime`") + } + + #[cfg(feature = "parsing")] + fn visit_str(self, value: &str) -> Result { + UtcDateTime::parse(value, &UTC_DATE_TIME_FORMAT).map_err(E::custom) + } + + fn visit_seq>(self, mut seq: A) -> Result { + let year = item!(seq, "year")?; + let ordinal = item!(seq, "day of year")?; + let hour = item!(seq, "hour")?; + let minute = item!(seq, "minute")?; + let second = item!(seq, "second")?; + let nanosecond = item!(seq, "nanosecond")?; + + Date::from_ordinal_date(year, ordinal) + .and_then(|date| date.with_hms_nano(hour, minute, second, nanosecond)) + .map(UtcDateTime::from_primitive) + .map_err(ComponentRange::into_de_error) + } +} + +impl<'a> de::Visitor<'a> for Visitor