//! Serde visitor for various types. use core::fmt; use core::marker::PhantomData; #[cfg(feature = "parsing")] use serde_core::Deserializer; use serde_core::de; #[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) where T: ?Sized; impl<'a> de::Visitor<'a> for Visitor { type Value = Date; #[inline] fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { formatter.write_str("a `Date`") } #[cfg(feature = "parsing")] #[inline] fn visit_str(self, value: &str) -> Result where E: de::Error, { Date::parse(value, &DATE_FORMAT).map_err(E::custom) } #[inline] fn visit_seq(self, mut seq: A) -> Result where A: de::SeqAccess<'a>, { 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; #[inline] fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { formatter.write_str("a `Duration`") } #[inline] fn visit_str(self, value: &str) -> Result where E: de::Error, { 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)) } #[inline] fn visit_seq(self, mut seq: A) -> Result where A: de::SeqAccess<'a>, { 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; #[inline] fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { formatter.write_str("an `OffsetDateTime`") } #[cfg(feature = "parsing")] #[inline] fn visit_str(self, value: &str) -> Result where E: de::Error, { OffsetDateTime::parse(value, &OFFSET_DATE_TIME_FORMAT).map_err(E::custom) } #[inline] fn visit_seq(self, mut seq: A) -> Result where A: de::SeqAccess<'a>, { 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; #[inline] fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { formatter.write_str("a `PrimitiveDateTime`") } #[cfg(feature = "parsing")] #[inline] fn visit_str(self, value: &str) -> Result where E: de::Error, { PrimitiveDateTime::parse(value, &PRIMITIVE_DATE_TIME_FORMAT).map_err(E::custom) } #[inline] fn visit_seq(self, mut seq: A) -> Result where A: de::SeqAccess<'a>, { 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; #[inline] fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { formatter.write_str("a `PrimitiveDateTime`") } #[cfg(feature = "parsing")] #[inline] fn visit_str(self, value: &str) -> Result where E: de::Error, { UtcDateTime::parse(value, &UTC_DATE_TIME_FORMAT).map_err(E::custom) } #[inline] fn visit_seq(self, mut seq: A) -> Result where A: de::SeqAccess<'a>, { 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(self, mut seq: A) -> Result where A: de::SeqAccess<'a>, { 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 { type Value = UtcOffset; #[inline] fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { formatter.write_str("a `UtcOffset`") } #[cfg(feature = "parsing")] #[inline] fn visit_str(self, value: &str) -> Result where E: de::Error, { UtcOffset::parse(value, &UTC_OFFSET_FORMAT).map_err(E::custom) } #[inline] fn visit_seq(self, mut seq: A) -> Result where A: de::SeqAccess<'a>, { let hours = item!(seq, "offset hours")?; let mut minutes = 0; let mut seconds = 0; if let Ok(Some(min)) = seq.next_element() { minutes = min; if let Ok(Some(sec)) = seq.next_element() { seconds = sec; } }; UtcOffset::from_hms(hours, minutes, seconds).map_err(ComponentRange::into_de_error) } } impl de::Visitor<'_> for Visitor { type Value = Weekday; #[inline] fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { formatter.write_str("a `Weekday`") } #[inline] fn visit_str(self, value: &str) -> Result where E: de::Error, { 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`")), } } #[inline] fn visit_u64(self, value: u64) -> Result where E: de::Error, { 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 de::Visitor<'_> for Visitor { type Value = Month; #[inline] fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { formatter.write_str("a `Month`") } #[inline] fn visit_str(self, value: &str) -> Result where E: de::Error, { 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`")), } } #[inline] fn visit_u64(self, value: u64) -> Result where E: de::Error, { 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 de::Visitor<'_> for Visitor<$($ty)+> { type Value = OffsetDateTime; #[inline] fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { formatter.write_str(concat!($article, " ", $name, "-formatted `OffsetDateTime`")) } #[inline] fn visit_str(self, value: &str) -> Result where E: de::Error, { OffsetDateTime::parse(value, &$($ty)+).map_err(E::custom) } } #[cfg(feature = "parsing")] impl<'a> de::Visitor<'a> for Visitor> { type Value = Option; #[inline] fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { formatter.write_str(concat!( $article, " ", $name, "-formatted `Option`" )) } #[inline] fn visit_some(self, deserializer: D) -> Result, D::Error> where D: Deserializer<'a>, { deserializer .deserialize_any(Visitor::<$($ty)+>(PhantomData)) .map(Some) } #[inline] fn visit_none(self) -> Result, E> where E: de::Error, { Ok(None) } #[inline] fn visit_unit(self) -> Result where E: de::Error, { Ok(None) } } }; } well_known!("an", "RFC2822", Rfc2822); well_known!("an", "RFC3339", Rfc3339); well_known!( "an", "ISO 8601", Iso8601::<{ super::iso8601::SERDE_CONFIG }> );