1use core::fmt;
4use core::marker::PhantomData;
5
6use serde::de;
7#[cfg(feature = "parsing")]
8use serde::Deserializer;
9
10#[cfg(feature = "parsing")]
11use super::{
12 DATE_FORMAT, OFFSET_DATE_TIME_FORMAT, PRIMITIVE_DATE_TIME_FORMAT, TIME_FORMAT,
13 UTC_DATE_TIME_FORMAT, UTC_OFFSET_FORMAT,
14};
15use crate::error::ComponentRange;
16#[cfg(feature = "parsing")]
17use crate::format_description::well_known::*;
18use crate::{
19 Date, Duration, Month, OffsetDateTime, PrimitiveDateTime, Time, UtcDateTime, UtcOffset, Weekday,
20};
21
22pub(super) struct Visitor<T: ?Sized>(pub(super) PhantomData<T>);
24
25impl<'a> de::Visitor<'a> for Visitor<Date> {
26 type Value = Date;
27
28 fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
29 formatter.write_str("a `Date`")
30 }
31
32 #[cfg(feature = "parsing")]
33 fn visit_str<E: de::Error>(self, value: &str) -> Result<Date, E> {
34 Date::parse(value, &DATE_FORMAT).map_err(E::custom)
35 }
36
37 fn visit_seq<A: de::SeqAccess<'a>>(self, mut seq: A) -> Result<Date, A::Error> {
38 let year = item!(seq, "year")?;
39 let ordinal = item!(seq, "day of year")?;
40 Date::from_ordinal_date(year, ordinal).map_err(ComponentRange::into_de_error)
41 }
42}
43
44impl<'a> de::Visitor<'a> for Visitor<Duration> {
45 type Value = Duration;
46
47 fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
48 formatter.write_str("a `Duration`")
49 }
50
51 fn visit_str<E: de::Error>(self, value: &str) -> Result<Duration, E> {
52 let (seconds, nanoseconds) = value.split_once('.').ok_or_else(|| {
53 de::Error::invalid_value(de::Unexpected::Str(value), &"a decimal point")
54 })?;
55
56 let seconds = seconds
57 .parse()
58 .map_err(|_| de::Error::invalid_value(de::Unexpected::Str(seconds), &"seconds"))?;
59 let mut nanoseconds = nanoseconds.parse().map_err(|_| {
60 de::Error::invalid_value(de::Unexpected::Str(nanoseconds), &"nanoseconds")
61 })?;
62
63 if seconds < 0
64 || (seconds == 0 && value.starts_with("-"))
66 {
67 nanoseconds *= -1;
68 }
69
70 Ok(Duration::new(seconds, nanoseconds))
71 }
72
73 fn visit_seq<A: de::SeqAccess<'a>>(self, mut seq: A) -> Result<Duration, A::Error> {
74 let seconds = item!(seq, "seconds")?;
75 let nanoseconds = item!(seq, "nanoseconds")?;
76 Ok(Duration::new(seconds, nanoseconds))
77 }
78}
79
80impl<'a> de::Visitor<'a> for Visitor<OffsetDateTime> {
81 type Value = OffsetDateTime;
82
83 fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
84 formatter.write_str("an `OffsetDateTime`")
85 }
86
87 #[cfg(feature = "parsing")]
88 fn visit_str<E: de::Error>(self, value: &str) -> Result<OffsetDateTime, E> {
89 OffsetDateTime::parse(value, &OFFSET_DATE_TIME_FORMAT).map_err(E::custom)
90 }
91
92 fn visit_seq<A: de::SeqAccess<'a>>(self, mut seq: A) -> Result<OffsetDateTime, A::Error> {
93 let year = item!(seq, "year")?;
94 let ordinal = item!(seq, "day of year")?;
95 let hour = item!(seq, "hour")?;
96 let minute = item!(seq, "minute")?;
97 let second = item!(seq, "second")?;
98 let nanosecond = item!(seq, "nanosecond")?;
99 let offset_hours = item!(seq, "offset hours")?;
100 let offset_minutes = item!(seq, "offset minutes")?;
101 let offset_seconds = item!(seq, "offset seconds")?;
102
103 Date::from_ordinal_date(year, ordinal)
104 .and_then(|date| date.with_hms_nano(hour, minute, second, nanosecond))
105 .and_then(|datetime| {
106 UtcOffset::from_hms(offset_hours, offset_minutes, offset_seconds)
107 .map(|offset| datetime.assume_offset(offset))
108 })
109 .map_err(ComponentRange::into_de_error)
110 }
111}
112
113impl<'a> de::Visitor<'a> for Visitor<PrimitiveDateTime> {
114 type Value = PrimitiveDateTime;
115
116 fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
117 formatter.write_str("a `PrimitiveDateTime`")
118 }
119
120 #[cfg(feature = "parsing")]
121 fn visit_str<E: de::Error>(self, value: &str) -> Result<PrimitiveDateTime, E> {
122 PrimitiveDateTime::parse(value, &PRIMITIVE_DATE_TIME_FORMAT).map_err(E::custom)
123 }
124
125 fn visit_seq<A: de::SeqAccess<'a>>(self, mut seq: A) -> Result<PrimitiveDateTime, A::Error> {
126 let year = item!(seq, "year")?;
127 let ordinal = item!(seq, "day of year")?;
128 let hour = item!(seq, "hour")?;
129 let minute = item!(seq, "minute")?;
130 let second = item!(seq, "second")?;
131 let nanosecond = item!(seq, "nanosecond")?;
132
133 Date::from_ordinal_date(year, ordinal)
134 .and_then(|date| date.with_hms_nano(hour, minute, second, nanosecond))
135 .map_err(ComponentRange::into_de_error)
136 }
137}
138
139impl<'a> de::Visitor<'a> for Visitor<UtcDateTime> {
140 type Value = UtcDateTime;
141
142 fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
143 formatter.write_str("a `PrimitiveDateTime`")
144 }
145
146 #[cfg(feature = "parsing")]
147 fn visit_str<E: de::Error>(self, value: &str) -> Result<UtcDateTime, E> {
148 UtcDateTime::parse(value, &UTC_DATE_TIME_FORMAT).map_err(E::custom)
149 }
150
151 fn visit_seq<A: de::SeqAccess<'a>>(self, mut seq: A) -> Result<UtcDateTime, A::Error> {
152 let year = item!(seq, "year")?;
153 let ordinal = item!(seq, "day of year")?;
154 let hour = item!(seq, "hour")?;
155 let minute = item!(seq, "minute")?;
156 let second = item!(seq, "second")?;
157 let nanosecond = item!(seq, "nanosecond")?;
158
159 Date::from_ordinal_date(year, ordinal)
160 .and_then(|date| date.with_hms_nano(hour, minute, second, nanosecond))
161 .map(UtcDateTime::from_primitive)
162 .map_err(ComponentRange::into_de_error)
163 }
164}
165
166impl<'a> de::Visitor<'a> for Visitor<Time> {
167 type Value = Time;
168
169 fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
170 formatter.write_str("a `Time`")
171 }
172
173 #[cfg(feature = "parsing")]
174 fn visit_str<E: de::Error>(self, value: &str) -> Result<Time, E> {
175 Time::parse(value, &TIME_FORMAT).map_err(E::custom)
176 }
177
178 fn visit_seq<A: de::SeqAccess<'a>>(self, mut seq: A) -> Result<Time, A::Error> {
179 let hour = item!(seq, "hour")?;
180 let minute = item!(seq, "minute")?;
181 let second = item!(seq, "second")?;
182 let nanosecond = item!(seq, "nanosecond")?;
183
184 Time::from_hms_nano(hour, minute, second, nanosecond).map_err(ComponentRange::into_de_error)
185 }
186}
187
188impl<'a> de::Visitor<'a> for Visitor<UtcOffset> {
189 type Value = UtcOffset;
190
191 fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
192 formatter.write_str("a `UtcOffset`")
193 }
194
195 #[cfg(feature = "parsing")]
196 fn visit_str<E: de::Error>(self, value: &str) -> Result<UtcOffset, E> {
197 UtcOffset::parse(value, &UTC_OFFSET_FORMAT).map_err(E::custom)
198 }
199
200 fn visit_seq<A: de::SeqAccess<'a>>(self, mut seq: A) -> Result<UtcOffset, A::Error> {
201 let hours = item!(seq, "offset hours")?;
202 let mut minutes = 0;
203 let mut seconds = 0;
204
205 if let Ok(Some(min)) = seq.next_element() {
206 minutes = min;
207 if let Ok(Some(sec)) = seq.next_element() {
208 seconds = sec;
209 }
210 };
211
212 UtcOffset::from_hms(hours, minutes, seconds).map_err(ComponentRange::into_de_error)
213 }
214}
215
216impl de::Visitor<'_> for Visitor<Weekday> {
217 type Value = Weekday;
218
219 fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
220 formatter.write_str("a `Weekday`")
221 }
222
223 fn visit_str<E: de::Error>(self, value: &str) -> Result<Weekday, E> {
224 match value {
225 "Monday" => Ok(Weekday::Monday),
226 "Tuesday" => Ok(Weekday::Tuesday),
227 "Wednesday" => Ok(Weekday::Wednesday),
228 "Thursday" => Ok(Weekday::Thursday),
229 "Friday" => Ok(Weekday::Friday),
230 "Saturday" => Ok(Weekday::Saturday),
231 "Sunday" => Ok(Weekday::Sunday),
232 _ => Err(E::invalid_value(de::Unexpected::Str(value), &"a `Weekday`")),
233 }
234 }
235
236 fn visit_u64<E: de::Error>(self, value: u64) -> Result<Weekday, E> {
237 match value {
238 1 => Ok(Weekday::Monday),
239 2 => Ok(Weekday::Tuesday),
240 3 => Ok(Weekday::Wednesday),
241 4 => Ok(Weekday::Thursday),
242 5 => Ok(Weekday::Friday),
243 6 => Ok(Weekday::Saturday),
244 7 => Ok(Weekday::Sunday),
245 _ => Err(E::invalid_value(
246 de::Unexpected::Unsigned(value),
247 &"a value in the range 1..=7",
248 )),
249 }
250 }
251}
252
253impl de::Visitor<'_> for Visitor<Month> {
254 type Value = Month;
255
256 fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
257 formatter.write_str("a `Month`")
258 }
259
260 fn visit_str<E: de::Error>(self, value: &str) -> Result<Month, E> {
261 match value {
262 "January" => Ok(Month::January),
263 "February" => Ok(Month::February),
264 "March" => Ok(Month::March),
265 "April" => Ok(Month::April),
266 "May" => Ok(Month::May),
267 "June" => Ok(Month::June),
268 "July" => Ok(Month::July),
269 "August" => Ok(Month::August),
270 "September" => Ok(Month::September),
271 "October" => Ok(Month::October),
272 "November" => Ok(Month::November),
273 "December" => Ok(Month::December),
274 _ => Err(E::invalid_value(de::Unexpected::Str(value), &"a `Month`")),
275 }
276 }
277
278 fn visit_u64<E: de::Error>(self, value: u64) -> Result<Month, E> {
279 match value {
280 1 => Ok(Month::January),
281 2 => Ok(Month::February),
282 3 => Ok(Month::March),
283 4 => Ok(Month::April),
284 5 => Ok(Month::May),
285 6 => Ok(Month::June),
286 7 => Ok(Month::July),
287 8 => Ok(Month::August),
288 9 => Ok(Month::September),
289 10 => Ok(Month::October),
290 11 => Ok(Month::November),
291 12 => Ok(Month::December),
292 _ => Err(E::invalid_value(
293 de::Unexpected::Unsigned(value),
294 &"a value in the range 1..=12",
295 )),
296 }
297 }
298}
299
300macro_rules! well_known {
302 ($article:literal, $name:literal, $($ty:tt)+) => {
303 #[cfg(feature = "parsing")]
304 impl de::Visitor<'_> for Visitor<$($ty)+> {
305 type Value = OffsetDateTime;
306
307 fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
308 formatter.write_str(concat!($article, " ", $name, "-formatted `OffsetDateTime`"))
309 }
310
311 fn visit_str<E: de::Error>(self, value: &str) -> Result<OffsetDateTime, E> {
312 OffsetDateTime::parse(value, &$($ty)+).map_err(E::custom)
313 }
314 }
315
316 #[cfg(feature = "parsing")]
317 impl<'a> de::Visitor<'a> for Visitor<Option<$($ty)+>> {
318 type Value = Option<OffsetDateTime>;
319
320 fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
321 formatter.write_str(concat!(
322 $article,
323 " ",
324 $name,
325 "-formatted `Option<OffsetDateTime>`"
326 ))
327 }
328
329 fn visit_some<D: Deserializer<'a>>(
330 self,
331 deserializer: D,
332 ) -> Result<Option<OffsetDateTime>, D::Error> {
333 deserializer
334 .deserialize_any(Visitor::<$($ty)+>(PhantomData))
335 .map(Some)
336 }
337
338 fn visit_none<E: de::Error>(self) -> Result<Option<OffsetDateTime>, E> {
339 Ok(None)
340 }
341
342 fn visit_unit<E: de::Error>(self) -> Result<Self::Value, E> {
343 Ok(None)
344 }
345 }
346 };
347}
348
349well_known!("an", "RFC2822", Rfc2822);
350well_known!("an", "RFC3339", Rfc3339);
351well_known!(
352 "an",
353 "ISO 8601",
354 Iso8601::<{ super::iso8601::SERDE_CONFIG }>
355);