summaryrefslogtreecommitdiffstats
path: root/third_party/rust/time/src/serde/visitor.rs
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/rust/time/src/serde/visitor.rs')
-rw-r--r--third_party/rust/time/src/serde/visitor.rs316
1 files changed, 316 insertions, 0 deletions
diff --git a/third_party/rust/time/src/serde/visitor.rs b/third_party/rust/time/src/serde/visitor.rs
new file mode 100644
index 0000000000..e61989afde
--- /dev/null
+++ b/third_party/rust/time/src/serde/visitor.rs
@@ -0,0 +1,316 @@
+//! 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_OFFSET_FORMAT,
+};
+use crate::error::ComponentRange;
+#[cfg(feature = "parsing")]
+use crate::format_description::well_known::*;
+use crate::{Date, Duration, Month, OffsetDateTime, PrimitiveDateTime, Time, UtcOffset, Weekday};
+
+/// A serde visitor for various types.
+pub(super) struct Visitor<T: ?Sized>(pub(super) PhantomData<T>);
+
+impl<'a> de::Visitor<'a> for Visitor<Date> {
+ type Value = Date;
+
+ fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
+ formatter.write_str("a `Date`")
+ }
+
+ #[cfg(feature = "parsing")]
+ fn visit_str<E: de::Error>(self, value: &str) -> Result<Date, E> {
+ Date::parse(value, &DATE_FORMAT).map_err(E::custom)
+ }
+
+ fn visit_seq<A: de::SeqAccess<'a>>(self, mut seq: A) -> Result<Date, A::Error> {
+ 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<Duration> {
+ type Value = Duration;
+
+ fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
+ formatter.write_str("a `Duration`")
+ }
+
+ fn visit_str<E: de::Error>(self, value: &str) -> Result<Duration, E> {
+ 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 {
+ nanoseconds *= -1;
+ }
+
+ Ok(Duration::new(seconds, nanoseconds))
+ }
+
+ fn visit_seq<A: de::SeqAccess<'a>>(self, mut seq: A) -> Result<Duration, A::Error> {
+ let seconds = item!(seq, "seconds")?;
+ let nanoseconds = item!(seq, "nanoseconds")?;
+ Ok(Duration::new(seconds, nanoseconds))
+ }
+}
+
+impl<'a> de::Visitor<'a> for Visitor<OffsetDateTime> {
+ type Value = OffsetDateTime;
+
+ fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
+ formatter.write_str("an `OffsetDateTime`")
+ }
+
+ #[cfg(feature = "parsing")]
+ fn visit_str<E: de::Error>(self, value: &str) -> Result<OffsetDateTime, E> {
+ OffsetDateTime::parse(value, &OFFSET_DATE_TIME_FORMAT).map_err(E::custom)
+ }
+
+ fn visit_seq<A: de::SeqAccess<'a>>(self, mut seq: A) -> Result<OffsetDateTime, A::Error> {
+ 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<PrimitiveDateTime> {
+ type Value = PrimitiveDateTime;
+
+ fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
+ formatter.write_str("a `PrimitiveDateTime`")
+ }
+
+ #[cfg(feature = "parsing")]
+ fn visit_str<E: de::Error>(self, value: &str) -> Result<PrimitiveDateTime, E> {
+ PrimitiveDateTime::parse(value, &PRIMITIVE_DATE_TIME_FORMAT).map_err(E::custom)
+ }
+
+ fn visit_seq<A: de::SeqAccess<'a>>(self, mut seq: A) -> Result<PrimitiveDateTime, A::Error> {
+ 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<Time> {
+ type Value = Time;
+
+ fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
+ formatter.write_str("a `Time`")
+ }
+
+ #[cfg(feature = "parsing")]
+ fn visit_str<E: de::Error>(self, value: &str) -> Result<Time, E> {
+ Time::parse(value, &TIME_FORMAT).map_err(E::custom)
+ }
+
+ fn visit_seq<A: de::SeqAccess<'a>>(self, mut seq: A) -> Result<Time, A::Error> {
+ let hour = item!(seq, "hour")?;
+ let minute = item!(seq, "minute")?;
+ let second = item!(seq, "second")?;
+ let nanosecond = item!(seq, "nanosecond")?;
+
+ Time::from_hms_nano(hour, minute, second, nanosecond).map_err(ComponentRange::into_de_error)
+ }
+}
+
+impl<'a> de::Visitor<'a> for Visitor<UtcOffset> {
+ type Value = UtcOffset;
+
+ fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
+ formatter.write_str("a `UtcOffset`")
+ }
+
+ #[cfg(feature = "parsing")]
+ fn visit_str<E: de::Error>(self, value: &str) -> Result<UtcOffset, E> {
+ UtcOffset::parse(value, &UTC_OFFSET_FORMAT).map_err(E::custom)
+ }
+
+ fn visit_seq<A: de::SeqAccess<'a>>(self, mut seq: A) -> Result<UtcOffset, A::Error> {
+ let hours = item!(seq, "offset hours")?;
+ let minutes = item!(seq, "offset minutes")?;
+ let seconds = item!(seq, "offset seconds")?;
+
+ UtcOffset::from_hms(hours, minutes, seconds).map_err(ComponentRange::into_de_error)
+ }
+}
+
+impl<'a> de::Visitor<'a> for Visitor<Weekday> {
+ type Value = Weekday;
+
+ fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
+ formatter.write_str("a `Weekday`")
+ }
+
+ fn visit_str<E: de::Error>(self, value: &str) -> Result<Weekday, E> {
+ match value {
+ "Monday" => Ok(Weekday::Monday),
+ "Tuesday" => Ok(Weekday::Tuesday),
+ "Wednesday" => Ok(Weekday::Wednesday),
+ "Thursday" => Ok(Weekday::Thursday),
+ "Friday" => Ok(Weekday::Friday),
+ "Saturday" => Ok(Weekday::Saturday),
+ "Sunday" => Ok(Weekday::Sunday),
+ _ => Err(E::invalid_value(de::Unexpected::Str(value), &"a `Weekday`")),
+ }
+ }
+
+ fn visit_u64<E: de::Error>(self, value: u64) -> Result<Weekday, E> {
+ match value {
+ 1 => Ok(Weekday::Monday),
+ 2 => Ok(Weekday::Tuesday),
+ 3 => Ok(Weekday::Wednesday),
+ 4 => Ok(Weekday::Thursday),
+ 5 => Ok(Weekday::Friday),
+ 6 => Ok(Weekday::Saturday),
+ 7 => Ok(Weekday::Sunday),
+ _ => Err(E::invalid_value(
+ de::Unexpected::Unsigned(value),
+ &"a value in the range 1..=7",
+ )),
+ }
+ }
+}
+
+impl<'a> de::Visitor<'a> for Visitor<Month> {
+ type Value = Month;
+
+ fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
+ formatter.write_str("a `Month`")
+ }
+
+ fn visit_str<E: de::Error>(self, value: &str) -> Result<Month, E> {
+ match value {
+ "January" => Ok(Month::January),
+ "February" => Ok(Month::February),
+ "March" => Ok(Month::March),
+ "April" => Ok(Month::April),
+ "May" => Ok(Month::May),
+ "June" => Ok(Month::June),
+ "July" => Ok(Month::July),
+ "August" => Ok(Month::August),
+ "September" => Ok(Month::September),
+ "October" => Ok(Month::October),
+ "November" => Ok(Month::November),
+ "December" => Ok(Month::December),
+ _ => Err(E::invalid_value(de::Unexpected::Str(value), &"a `Month`")),
+ }
+ }
+
+ fn visit_u64<E: de::Error>(self, value: u64) -> Result<Month, E> {
+ match value {
+ 1 => Ok(Month::January),
+ 2 => Ok(Month::February),
+ 3 => Ok(Month::March),
+ 4 => Ok(Month::April),
+ 5 => Ok(Month::May),
+ 6 => Ok(Month::June),
+ 7 => Ok(Month::July),
+ 8 => Ok(Month::August),
+ 9 => Ok(Month::September),
+ 10 => Ok(Month::October),
+ 11 => Ok(Month::November),
+ 12 => Ok(Month::December),
+ _ => Err(E::invalid_value(
+ de::Unexpected::Unsigned(value),
+ &"a value in the range 1..=12",
+ )),
+ }
+ }
+}
+
+/// Implement a visitor for a well-known format.
+macro_rules! well_known {
+ ($article:literal, $name:literal, $($ty:tt)+) => {
+ #[cfg(feature = "parsing")]
+ impl<'a> de::Visitor<'a> for Visitor<$($ty)+> {
+ type Value = OffsetDateTime;
+
+ fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
+ formatter.write_str(concat!($article, " ", $name, "-formatted `OffsetDateTime`"))
+ }
+
+ fn visit_str<E: de::Error>(self, value: &str) -> Result<OffsetDateTime, E> {
+ OffsetDateTime::parse(value, &$($ty)+).map_err(E::custom)
+ }
+ }
+
+ #[cfg(feature = "parsing")]
+ impl<'a> de::Visitor<'a> for Visitor<Option<$($ty)+>> {
+ type Value = Option<OffsetDateTime>;
+
+ fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
+ formatter.write_str(concat!(
+ $article,
+ " ",
+ $name,
+ "-formatted `Option<OffsetDateTime>`"
+ ))
+ }
+
+ fn visit_some<D: Deserializer<'a>>(
+ self,
+ deserializer: D,
+ ) -> Result<Option<OffsetDateTime>, D::Error> {
+ deserializer
+ .deserialize_any(Visitor::<$($ty)+>(PhantomData))
+ .map(Some)
+ }
+
+ fn visit_none<E: de::Error>(self) -> Result<Option<OffsetDateTime>, E> {
+ Ok(None)
+ }
+
+ fn visit_unit<E: de::Error>(self) -> Result<Self::Value, E> {
+ Ok(None)
+ }
+ }
+ };
+}
+
+well_known!("an", "RFC2822", Rfc2822);
+well_known!("an", "RFC3339", Rfc3339);
+well_known!(
+ "an",
+ "ISO 8601",
+ Iso8601::<{ super::iso8601::SERDE_CONFIG }>
+);