diff options
Diffstat (limited to 'third_party/rust/time/src/serde/visitor.rs')
-rw-r--r-- | third_party/rust/time/src/serde/visitor.rs | 316 |
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 }> +); |