1use core::fmt;
4use core::marker::PhantomData;
5
6#[cfg(feature = "parsing")]
7use serde_core::Deserializer;
8use serde_core::de;
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, Timestamp, UtcDateTime,
20 UtcOffset, Weekday,
21};
22
23pub(super) struct Visitor<T>(pub(super) PhantomData<T>)
25where
26 T: ?Sized;
27
28impl<'a> de::Visitor<'a> for Visitor<Date> {
29 type Value = Date;
30
31 #[inline]
32 fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
33 formatter.write_str("a `Date`")
34 }
35
36 #[cfg(feature = "parsing")]
37 #[inline]
38 fn visit_str<E>(self, value: &str) -> Result<Date, E>
39 where
40 E: de::Error,
41 {
42 Date::parse(value, &DATE_FORMAT).map_err(E::custom)
43 }
44
45 #[inline]
46 fn visit_seq<A>(self, mut seq: A) -> Result<Date, A::Error>
47 where
48 A: de::SeqAccess<'a>,
49 {
50 let year = item!(seq, "year")?;
51 let ordinal = item!(seq, "day of year")?;
52 Date::from_ordinal_date(year, ordinal).map_err(ComponentRange::into_de_error)
53 }
54}
55
56impl<'a> de::Visitor<'a> for Visitor<Duration> {
57 type Value = Duration;
58
59 #[inline]
60 fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
61 formatter.write_str("a `Duration`")
62 }
63
64 #[inline]
65 fn visit_str<E>(self, value: &str) -> Result<Duration, E>
66 where
67 E: de::Error,
68 {
69 let (seconds, nanoseconds) = value.split_once('.').ok_or_else(|| {
70 de::Error::invalid_value(de::Unexpected::Str(value), &"a decimal point")
71 })?;
72
73 let seconds = seconds
74 .parse()
75 .map_err(|_| de::Error::invalid_value(de::Unexpected::Str(seconds), &"seconds"))?;
76 let mut nanoseconds = nanoseconds.parse().map_err(|_| {
77 de::Error::invalid_value(de::Unexpected::Str(nanoseconds), &"nanoseconds")
78 })?;
79
80 if seconds < 0
81 || (seconds == 0 && value.starts_with("-"))
83 {
84 nanoseconds *= -1;
85 }
86
87 Ok(Duration::new(seconds, nanoseconds))
88 }
89
90 #[inline]
91 fn visit_seq<A>(self, mut seq: A) -> Result<Duration, A::Error>
92 where
93 A: de::SeqAccess<'a>,
94 {
95 let seconds = item!(seq, "seconds")?;
96 let nanoseconds = item!(seq, "nanoseconds")?;
97 Ok(Duration::new(seconds, nanoseconds))
98 }
99}
100
101impl<'a> de::Visitor<'a> for Visitor<OffsetDateTime> {
102 type Value = OffsetDateTime;
103
104 #[inline]
105 fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
106 formatter.write_str("an `OffsetDateTime`")
107 }
108
109 #[cfg(feature = "parsing")]
110 #[inline]
111 fn visit_str<E>(self, value: &str) -> Result<OffsetDateTime, E>
112 where
113 E: de::Error,
114 {
115 OffsetDateTime::parse(value, &OFFSET_DATE_TIME_FORMAT).map_err(E::custom)
116 }
117
118 #[inline]
119 fn visit_seq<A>(self, mut seq: A) -> Result<OffsetDateTime, A::Error>
120 where
121 A: de::SeqAccess<'a>,
122 {
123 let year = item!(seq, "year")?;
124 let ordinal = item!(seq, "day of year")?;
125 let hour = item!(seq, "hour")?;
126 let minute = item!(seq, "minute")?;
127 let second = item!(seq, "second")?;
128 let nanosecond = item!(seq, "nanosecond")?;
129 let offset_hours = item!(seq, "offset hours")?;
130 let offset_minutes = item!(seq, "offset minutes")?;
131 let offset_seconds = item!(seq, "offset seconds")?;
132
133 Date::from_ordinal_date(year, ordinal)
134 .and_then(|date| date.with_hms_nano(hour, minute, second, nanosecond))
135 .and_then(|datetime| {
136 UtcOffset::from_hms(offset_hours, offset_minutes, offset_seconds)
137 .map(|offset| datetime.assume_offset(offset))
138 })
139 .map_err(ComponentRange::into_de_error)
140 }
141}
142
143impl<'a> de::Visitor<'a> for Visitor<PrimitiveDateTime> {
144 type Value = PrimitiveDateTime;
145
146 #[inline]
147 fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
148 formatter.write_str("a `PrimitiveDateTime`")
149 }
150
151 #[cfg(feature = "parsing")]
152 #[inline]
153 fn visit_str<E>(self, value: &str) -> Result<PrimitiveDateTime, E>
154 where
155 E: de::Error,
156 {
157 PrimitiveDateTime::parse(value, &PRIMITIVE_DATE_TIME_FORMAT).map_err(E::custom)
158 }
159
160 #[inline]
161 fn visit_seq<A>(self, mut seq: A) -> Result<PrimitiveDateTime, A::Error>
162 where
163 A: de::SeqAccess<'a>,
164 {
165 let year = item!(seq, "year")?;
166 let ordinal = item!(seq, "day of year")?;
167 let hour = item!(seq, "hour")?;
168 let minute = item!(seq, "minute")?;
169 let second = item!(seq, "second")?;
170 let nanosecond = item!(seq, "nanosecond")?;
171
172 Date::from_ordinal_date(year, ordinal)
173 .and_then(|date| date.with_hms_nano(hour, minute, second, nanosecond))
174 .map_err(ComponentRange::into_de_error)
175 }
176}
177
178impl<'a> de::Visitor<'a> for Visitor<UtcDateTime> {
179 type Value = UtcDateTime;
180
181 #[inline]
182 fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
183 formatter.write_str("a `PrimitiveDateTime`")
184 }
185
186 #[cfg(feature = "parsing")]
187 #[inline]
188 fn visit_str<E>(self, value: &str) -> Result<UtcDateTime, E>
189 where
190 E: de::Error,
191 {
192 UtcDateTime::parse(value, &UTC_DATE_TIME_FORMAT).map_err(E::custom)
193 }
194
195 #[inline]
196 fn visit_seq<A>(self, mut seq: A) -> Result<UtcDateTime, A::Error>
197 where
198 A: de::SeqAccess<'a>,
199 {
200 let year = item!(seq, "year")?;
201 let ordinal = item!(seq, "day of year")?;
202 let hour = item!(seq, "hour")?;
203 let minute = item!(seq, "minute")?;
204 let second = item!(seq, "second")?;
205 let nanosecond = item!(seq, "nanosecond")?;
206
207 Date::from_ordinal_date(year, ordinal)
208 .and_then(|date| date.with_hms_nano(hour, minute, second, nanosecond))
209 .map(UtcDateTime::from_primitive)
210 .map_err(ComponentRange::into_de_error)
211 }
212}
213
214impl<'a> de::Visitor<'a> for Visitor<Time> {
215 type Value = Time;
216
217 #[inline]
218 fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
219 formatter.write_str("a `Time`")
220 }
221
222 #[cfg(feature = "parsing")]
223 #[inline]
224 fn visit_str<E>(self, value: &str) -> Result<Time, E>
225 where
226 E: de::Error,
227 {
228 Time::parse(value, &TIME_FORMAT).map_err(E::custom)
229 }
230
231 #[inline]
232 fn visit_seq<A>(self, mut seq: A) -> Result<Time, A::Error>
233 where
234 A: de::SeqAccess<'a>,
235 {
236 let hour = item!(seq, "hour")?;
237 let minute = item!(seq, "minute")?;
238 let second = item!(seq, "second")?;
239 let nanosecond = item!(seq, "nanosecond")?;
240
241 Time::from_hms_nano(hour, minute, second, nanosecond).map_err(ComponentRange::into_de_error)
242 }
243}
244
245impl<'a> de::Visitor<'a> for Visitor<UtcOffset> {
246 type Value = UtcOffset;
247
248 #[inline]
249 fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
250 formatter.write_str("a `UtcOffset`")
251 }
252
253 #[cfg(feature = "parsing")]
254 #[inline]
255 fn visit_str<E>(self, value: &str) -> Result<UtcOffset, E>
256 where
257 E: de::Error,
258 {
259 UtcOffset::parse(value, &UTC_OFFSET_FORMAT).map_err(E::custom)
260 }
261
262 #[inline]
263 fn visit_seq<A>(self, mut seq: A) -> Result<UtcOffset, A::Error>
264 where
265 A: de::SeqAccess<'a>,
266 {
267 let hours = item!(seq, "offset hours")?;
268 let mut minutes = 0;
269 let mut seconds = 0;
270
271 if let Ok(Some(min)) = seq.next_element() {
272 minutes = min;
273 if let Ok(Some(sec)) = seq.next_element() {
274 seconds = sec;
275 }
276 };
277
278 UtcOffset::from_hms(hours, minutes, seconds).map_err(ComponentRange::into_de_error)
279 }
280}
281
282impl de::Visitor<'_> for Visitor<Timestamp> {
283 type Value = Timestamp;
284
285 #[inline]
286 fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
287 formatter.write_str("a `Timestamp`")
288 }
289
290 #[inline]
291 fn visit_i128<E>(self, value: i128) -> Result<Timestamp, E>
292 where
293 E: de::Error,
294 {
295 Timestamp::from_nanoseconds(value).map_err(ComponentRange::into_de_error)
296 }
297}
298
299impl de::Visitor<'_> for Visitor<Weekday> {
300 type Value = Weekday;
301
302 #[inline]
303 fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
304 formatter.write_str("a `Weekday`")
305 }
306
307 #[inline]
308 fn visit_str<E>(self, value: &str) -> Result<Weekday, E>
309 where
310 E: de::Error,
311 {
312 match value {
313 "Monday" => Ok(Weekday::Monday),
314 "Tuesday" => Ok(Weekday::Tuesday),
315 "Wednesday" => Ok(Weekday::Wednesday),
316 "Thursday" => Ok(Weekday::Thursday),
317 "Friday" => Ok(Weekday::Friday),
318 "Saturday" => Ok(Weekday::Saturday),
319 "Sunday" => Ok(Weekday::Sunday),
320 _ => Err(E::invalid_value(de::Unexpected::Str(value), &"a `Weekday`")),
321 }
322 }
323
324 #[inline]
325 fn visit_u64<E>(self, value: u64) -> Result<Weekday, E>
326 where
327 E: de::Error,
328 {
329 match value {
330 1 => Ok(Weekday::Monday),
331 2 => Ok(Weekday::Tuesday),
332 3 => Ok(Weekday::Wednesday),
333 4 => Ok(Weekday::Thursday),
334 5 => Ok(Weekday::Friday),
335 6 => Ok(Weekday::Saturday),
336 7 => Ok(Weekday::Sunday),
337 _ => Err(E::invalid_value(
338 de::Unexpected::Unsigned(value),
339 &"a value in the range 1..=7",
340 )),
341 }
342 }
343}
344
345impl de::Visitor<'_> for Visitor<Month> {
346 type Value = Month;
347
348 #[inline]
349 fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
350 formatter.write_str("a `Month`")
351 }
352
353 #[inline]
354 fn visit_str<E>(self, value: &str) -> Result<Month, E>
355 where
356 E: de::Error,
357 {
358 match value {
359 "January" => Ok(Month::January),
360 "February" => Ok(Month::February),
361 "March" => Ok(Month::March),
362 "April" => Ok(Month::April),
363 "May" => Ok(Month::May),
364 "June" => Ok(Month::June),
365 "July" => Ok(Month::July),
366 "August" => Ok(Month::August),
367 "September" => Ok(Month::September),
368 "October" => Ok(Month::October),
369 "November" => Ok(Month::November),
370 "December" => Ok(Month::December),
371 _ => Err(E::invalid_value(de::Unexpected::Str(value), &"a `Month`")),
372 }
373 }
374
375 #[inline]
376 fn visit_u64<E>(self, value: u64) -> Result<Month, E>
377 where
378 E: de::Error,
379 {
380 match value {
381 1 => Ok(Month::January),
382 2 => Ok(Month::February),
383 3 => Ok(Month::March),
384 4 => Ok(Month::April),
385 5 => Ok(Month::May),
386 6 => Ok(Month::June),
387 7 => Ok(Month::July),
388 8 => Ok(Month::August),
389 9 => Ok(Month::September),
390 10 => Ok(Month::October),
391 11 => Ok(Month::November),
392 12 => Ok(Month::December),
393 _ => Err(E::invalid_value(
394 de::Unexpected::Unsigned(value),
395 &"a value in the range 1..=12",
396 )),
397 }
398 }
399}
400
401macro_rules! well_known {
403 ($article:literal, $name:literal, $($ty:tt)+) => {
404 #[cfg(feature = "parsing")]
405 impl de::Visitor<'_> for Visitor<$($ty)+> {
406 type Value = OffsetDateTime;
407
408 #[inline]
409 fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
410 formatter.write_str(concat!($article, " ", $name, "-formatted `OffsetDateTime`"))
411 }
412
413 #[inline]
414 fn visit_str<E>(self, value: &str) -> Result<OffsetDateTime, E>
415 where
416 E: de::Error,
417 {
418 OffsetDateTime::parse(value, &$($ty)+).map_err(E::custom)
419 }
420 }
421
422 #[cfg(feature = "parsing")]
423 impl<'a> de::Visitor<'a> for Visitor<Option<$($ty)+>> {
424 type Value = Option<OffsetDateTime>;
425
426 #[inline]
427 fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
428 formatter.write_str(concat!(
429 $article,
430 " ",
431 $name,
432 "-formatted `Option<OffsetDateTime>`"
433 ))
434 }
435
436 #[inline]
437 fn visit_some<D>(self, deserializer: D) -> Result<Option<OffsetDateTime>, D::Error>
438 where
439 D: Deserializer<'a>,
440 {
441 deserializer
442 .deserialize_any(Visitor::<$($ty)+>(PhantomData))
443 .map(Some)
444 }
445
446 #[inline]
447 fn visit_none<E>(self) -> Result<Option<OffsetDateTime>, E>
448 where
449 E: de::Error,
450 {
451 Ok(None)
452 }
453
454 #[inline]
455 fn visit_unit<E>(self) -> Result<Self::Value, E>
456 where
457 E: de::Error,
458 {
459 Ok(None)
460 }
461 }
462 };
463}
464
465well_known!("an", "RFC2822", Rfc2822);
466well_known!("an", "RFC3339", Rfc3339);
467well_known!(
468 "an",
469 "ISO 8601",
470 Iso8601::<{ super::iso8601::SERDE_CONFIG }>
471);