1use core::{
8 error::Error,
9 fmt,
10 num::{IntErrorKind, ParseIntError},
11};
12
13#[derive(Clone, Copy, Debug, Eq, PartialEq)]
16pub struct FileTimeRangeError(FileTimeRangeErrorKind);
17
18impl FileTimeRangeError {
19 pub(crate) const fn new(kind: FileTimeRangeErrorKind) -> Self {
20 Self(kind)
21 }
22
23 #[must_use]
37 pub const fn kind(&self) -> FileTimeRangeErrorKind {
38 self.0
39 }
40}
41
42impl fmt::Display for FileTimeRangeError {
43 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
44 self.kind().fmt(f)
45 }
46}
47
48impl Error for FileTimeRangeError {}
49
50impl From<FileTimeRangeErrorKind> for FileTimeRangeError {
51 fn from(kind: FileTimeRangeErrorKind) -> Self {
52 Self::new(kind)
53 }
54}
55
56#[derive(Clone, Copy, Debug, Eq, PartialEq)]
58pub enum FileTimeRangeErrorKind {
59 Negative,
63
64 Overflow,
69}
70
71impl fmt::Display for FileTimeRangeErrorKind {
72 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
73 match self {
74 Self::Negative => write!(f, "file time is before `1601-01-01 00:00:00 UTC`"),
75 Self::Overflow => write!(
76 f,
77 "file time is after `+60056-05-28 05:36:10.955161500 UTC`"
78 ),
79 }
80 }
81}
82
83#[derive(Clone, Debug, Eq, PartialEq)]
85pub struct ParseFileTimeError(ParseIntError);
86
87impl ParseFileTimeError {
88 pub(crate) const fn new(inner: ParseIntError) -> Self {
89 Self(inner)
90 }
91}
92
93impl fmt::Display for ParseFileTimeError {
94 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
95 let inner = &self.0;
96 if inner.kind() == &IntErrorKind::PosOverflow {
97 write!(
98 f,
99 "file time is after `+60056-05-28 05:36:10.955161500 UTC`"
100 )
101 } else {
102 inner.fmt(f)
103 }
104 }
105}
106
107impl Error for ParseFileTimeError {
108 fn source(&self) -> Option<&(dyn Error + 'static)> {
109 Some(&self.0)
110 }
111}
112
113#[cfg(test)]
114mod tests {
115 use core::str::FromStr;
116
117 use super::*;
118
119 #[test]
120 fn clone_file_time_range_error() {
121 assert_eq!(
122 FileTimeRangeError::new(FileTimeRangeErrorKind::Negative).clone(),
123 FileTimeRangeError::new(FileTimeRangeErrorKind::Negative)
124 );
125 assert_eq!(
126 FileTimeRangeError::new(FileTimeRangeErrorKind::Overflow).clone(),
127 FileTimeRangeError::new(FileTimeRangeErrorKind::Overflow)
128 );
129 }
130
131 #[test]
132 fn copy_file_time_range_error() {
133 {
134 let a = FileTimeRangeError::new(FileTimeRangeErrorKind::Negative);
135 let b = a;
136 assert_eq!(a, b);
137 }
138
139 {
140 let a = FileTimeRangeError::new(FileTimeRangeErrorKind::Overflow);
141 let b = a;
142 assert_eq!(a, b);
143 }
144 }
145
146 #[test]
147 fn debug_file_time_range_error() {
148 assert_eq!(
149 format!(
150 "{:?}",
151 FileTimeRangeError::new(FileTimeRangeErrorKind::Negative)
152 ),
153 "FileTimeRangeError(Negative)"
154 );
155 assert_eq!(
156 format!(
157 "{:?}",
158 FileTimeRangeError::new(FileTimeRangeErrorKind::Overflow)
159 ),
160 "FileTimeRangeError(Overflow)"
161 );
162 }
163
164 #[test]
165 fn file_time_range_error_equality() {
166 assert_eq!(
167 FileTimeRangeError::new(FileTimeRangeErrorKind::Negative),
168 FileTimeRangeError::new(FileTimeRangeErrorKind::Negative)
169 );
170 assert_ne!(
171 FileTimeRangeError::new(FileTimeRangeErrorKind::Negative),
172 FileTimeRangeError::new(FileTimeRangeErrorKind::Overflow)
173 );
174 assert_ne!(
175 FileTimeRangeError::new(FileTimeRangeErrorKind::Overflow),
176 FileTimeRangeError::new(FileTimeRangeErrorKind::Negative)
177 );
178 assert_eq!(
179 FileTimeRangeError::new(FileTimeRangeErrorKind::Overflow),
180 FileTimeRangeError::new(FileTimeRangeErrorKind::Overflow)
181 );
182 }
183
184 #[test]
185 fn kind_file_time_range_error() {
186 assert_eq!(
187 FileTimeRangeError::new(FileTimeRangeErrorKind::Negative).kind(),
188 FileTimeRangeErrorKind::Negative
189 );
190 assert_eq!(
191 FileTimeRangeError::new(FileTimeRangeErrorKind::Overflow).kind(),
192 FileTimeRangeErrorKind::Overflow
193 );
194 }
195
196 #[test]
197 const fn kind_file_time_range_error_is_const_fn() {
198 const _: FileTimeRangeErrorKind =
199 FileTimeRangeError::new(FileTimeRangeErrorKind::Negative).kind();
200 }
201
202 #[test]
203 fn display_file_time_range_error() {
204 assert_eq!(
205 format!(
206 "{}",
207 FileTimeRangeError::new(FileTimeRangeErrorKind::Negative)
208 ),
209 "file time is before `1601-01-01 00:00:00 UTC`"
210 );
211 assert_eq!(
212 format!(
213 "{}",
214 FileTimeRangeError::new(FileTimeRangeErrorKind::Overflow)
215 ),
216 "file time is after `+60056-05-28 05:36:10.955161500 UTC`"
217 );
218 }
219
220 #[test]
221 fn source_file_time_range_error() {
222 assert!(
223 FileTimeRangeError::new(FileTimeRangeErrorKind::Negative)
224 .source()
225 .is_none()
226 );
227 assert!(
228 FileTimeRangeError::new(FileTimeRangeErrorKind::Overflow)
229 .source()
230 .is_none()
231 );
232 }
233
234 #[test]
235 fn from_file_time_range_error_kind_to_file_time_range_error() {
236 assert_eq!(
237 FileTimeRangeError::from(FileTimeRangeErrorKind::Negative),
238 FileTimeRangeError::new(FileTimeRangeErrorKind::Negative)
239 );
240 assert_eq!(
241 FileTimeRangeError::from(FileTimeRangeErrorKind::Overflow),
242 FileTimeRangeError::new(FileTimeRangeErrorKind::Overflow)
243 );
244 }
245
246 #[test]
247 fn clone_file_time_range_error_kind() {
248 assert_eq!(
249 FileTimeRangeErrorKind::Negative.clone(),
250 FileTimeRangeErrorKind::Negative
251 );
252 assert_eq!(
253 FileTimeRangeErrorKind::Overflow.clone(),
254 FileTimeRangeErrorKind::Overflow
255 );
256 }
257
258 #[test]
259 fn copy_file_time_range_error_kind() {
260 {
261 let a = FileTimeRangeErrorKind::Negative;
262 let b = a;
263 assert_eq!(a, b);
264 }
265
266 {
267 let a = FileTimeRangeErrorKind::Overflow;
268 let b = a;
269 assert_eq!(a, b);
270 }
271 }
272
273 #[test]
274 fn debug_file_time_range_error_kind() {
275 assert_eq!(
276 format!("{:?}", FileTimeRangeErrorKind::Negative),
277 "Negative"
278 );
279 assert_eq!(
280 format!("{:?}", FileTimeRangeErrorKind::Overflow),
281 "Overflow"
282 );
283 }
284
285 #[test]
286 fn file_time_range_error_kind_equality() {
287 assert_eq!(
288 FileTimeRangeErrorKind::Negative,
289 FileTimeRangeErrorKind::Negative
290 );
291 assert_ne!(
292 FileTimeRangeErrorKind::Negative,
293 FileTimeRangeErrorKind::Overflow
294 );
295 assert_ne!(
296 FileTimeRangeErrorKind::Overflow,
297 FileTimeRangeErrorKind::Negative
298 );
299 assert_eq!(
300 FileTimeRangeErrorKind::Overflow,
301 FileTimeRangeErrorKind::Overflow
302 );
303 }
304
305 #[test]
306 fn display_file_time_range_error_kind() {
307 assert_eq!(
308 format!("{}", FileTimeRangeErrorKind::Negative),
309 "file time is before `1601-01-01 00:00:00 UTC`"
310 );
311 assert_eq!(
312 format!("{}", FileTimeRangeErrorKind::Overflow),
313 "file time is after `+60056-05-28 05:36:10.955161500 UTC`"
314 );
315 }
316
317 #[test]
318 fn debug_parse_file_time_error() {
319 assert_eq!(
320 format!(
321 "{:?}",
322 ParseFileTimeError::new(u64::from_str("").unwrap_err())
323 ),
324 "ParseFileTimeError(ParseIntError { kind: Empty })"
325 );
326 assert_eq!(
327 format!(
328 "{:?}",
329 ParseFileTimeError::new(u64::from_str("a").unwrap_err())
330 ),
331 "ParseFileTimeError(ParseIntError { kind: InvalidDigit })"
332 );
333 assert_eq!(
334 format!(
335 "{:?}",
336 ParseFileTimeError::new(u64::from_str("18446744073709551616").unwrap_err())
337 ),
338 "ParseFileTimeError(ParseIntError { kind: PosOverflow })"
339 );
340 }
341
342 #[test]
343 fn parse_file_time_error_equality() {
344 assert_eq!(
345 ParseFileTimeError::new(u64::from_str("").unwrap_err()),
346 ParseFileTimeError::new(u64::from_str("").unwrap_err())
347 );
348 assert_ne!(
349 ParseFileTimeError::new(u64::from_str("").unwrap_err()),
350 ParseFileTimeError::new(u64::from_str("a").unwrap_err())
351 );
352 assert_ne!(
353 ParseFileTimeError::new(u64::from_str("").unwrap_err()),
354 ParseFileTimeError::new(u64::from_str("18446744073709551616").unwrap_err())
355 );
356 assert_ne!(
357 ParseFileTimeError::new(u64::from_str("a").unwrap_err()),
358 ParseFileTimeError::new(u64::from_str("").unwrap_err())
359 );
360 assert_eq!(
361 ParseFileTimeError::new(u64::from_str("a").unwrap_err()),
362 ParseFileTimeError::new(u64::from_str("a").unwrap_err())
363 );
364 assert_ne!(
365 ParseFileTimeError::new(u64::from_str("a").unwrap_err()),
366 ParseFileTimeError::new(u64::from_str("18446744073709551616").unwrap_err())
367 );
368 assert_ne!(
369 ParseFileTimeError::new(u64::from_str("18446744073709551616").unwrap_err()),
370 ParseFileTimeError::new(u64::from_str("").unwrap_err())
371 );
372 assert_ne!(
373 ParseFileTimeError::new(u64::from_str("18446744073709551616").unwrap_err()),
374 ParseFileTimeError::new(u64::from_str("a").unwrap_err())
375 );
376 assert_eq!(
377 ParseFileTimeError::new(u64::from_str("18446744073709551616").unwrap_err()),
378 ParseFileTimeError::new(u64::from_str("18446744073709551616").unwrap_err())
379 );
380 }
381
382 #[test]
383 fn display_parse_file_time_error() {
384 assert_eq!(
385 format!(
386 "{}",
387 ParseFileTimeError::new(u64::from_str("").unwrap_err())
388 ),
389 "cannot parse integer from empty string"
390 );
391 assert_eq!(
392 format!(
393 "{}",
394 ParseFileTimeError::new(u64::from_str("a").unwrap_err())
395 ),
396 "invalid digit found in string"
397 );
398 assert_eq!(
399 format!(
400 "{}",
401 ParseFileTimeError::new(u64::from_str("18446744073709551616").unwrap_err())
402 ),
403 "file time is after `+60056-05-28 05:36:10.955161500 UTC`"
404 );
405 }
406
407 #[test]
408 fn source_parse_file_time_error() {
409 assert_eq!(
410 ParseFileTimeError::new(u64::from_str("").unwrap_err())
411 .source()
412 .unwrap()
413 .downcast_ref::<ParseIntError>()
414 .unwrap()
415 .kind(),
416 &IntErrorKind::Empty
417 );
418 assert_eq!(
419 ParseFileTimeError::new(u64::from_str("a").unwrap_err())
420 .source()
421 .unwrap()
422 .downcast_ref::<ParseIntError>()
423 .unwrap()
424 .kind(),
425 &IntErrorKind::InvalidDigit
426 );
427 assert_eq!(
428 ParseFileTimeError::new(u64::from_str("18446744073709551616").unwrap_err())
429 .source()
430 .unwrap()
431 .downcast_ref::<ParseIntError>()
432 .unwrap()
433 .kind(),
434 &IntErrorKind::PosOverflow
435 );
436 }
437}