nt_time/file_time/
str.rs

1// SPDX-FileCopyrightText: 2023 Shun Sakai
2//
3// SPDX-License-Identifier: Apache-2.0 OR MIT
4
5//! Utilities for string related operations.
6
7use core::str::FromStr;
8
9use super::FileTime;
10use crate::error::ParseFileTimeError;
11
12impl FileTime {
13    /// Parses a `FileTime` from a string slice with digits in a given base.
14    ///
15    /// The string is expected to be an optional `+` sign followed by only
16    /// digits. Leading and trailing non-digit characters (including whitespace)
17    /// represent an error. Underscores (which are accepted in Rust literals)
18    /// also represent an error.
19    ///
20    /// Digits are a subset of these characters, depending on `radix`:
21    ///
22    /// - `0-9`
23    /// - `a-z`
24    /// - `A-Z`
25    ///
26    /// # Errors
27    ///
28    /// Returns [`Err`] if [`u64::from_str_radix`] returns an error.
29    ///
30    /// # Panics
31    ///
32    /// Panics if `radix` is not in the range from 2 to 36.
33    ///
34    /// # Examples
35    ///
36    /// ```
37    /// # use nt_time::FileTime;
38    /// #
39    /// assert_eq!(
40    ///     FileTime::from_str_radix("0", 2),
41    ///     Ok(FileTime::NT_TIME_EPOCH)
42    /// );
43    /// assert_eq!(
44    ///     FileTime::from_str_radix("6355435732517500000", 8),
45    ///     Ok(FileTime::UNIX_EPOCH)
46    /// );
47    /// assert_eq!(
48    ///     FileTime::from_str_radix("+9223372036854775807", 10),
49    ///     Ok(FileTime::SIGNED_MAX)
50    /// );
51    /// assert_eq!(
52    ///     FileTime::from_str_radix("+ffffffffffffffff", 16),
53    ///     Ok(FileTime::MAX)
54    /// );
55    ///
56    /// assert!(FileTime::from_str_radix("8", 8).is_err());
57    ///
58    /// assert!(FileTime::from_str_radix("", 16).is_err());
59    ///
60    /// assert!(FileTime::from_str_radix("Z", 16).is_err());
61    /// assert!(FileTime::from_str_radix("_", 16).is_err());
62    /// assert!(FileTime::from_str_radix("-1", 16).is_err());
63    /// assert!(FileTime::from_str_radix("+", 16).is_err());
64    /// assert!(FileTime::from_str_radix("0 ", 16).is_err());
65    ///
66    /// assert!(FileTime::from_str_radix("3W5E11264SGSG", 36).is_err());
67    /// ```
68    ///
69    /// `radix` must be greater than or equal to 2:
70    ///
71    /// ```should_panic
72    /// # use nt_time::FileTime;
73    /// #
74    /// let _ = FileTime::from_str_radix("0", 1);
75    /// ```
76    ///
77    /// `radix` must be less than or equal to 36:
78    ///
79    /// ```should_panic
80    /// # use nt_time::FileTime;
81    /// #
82    /// let _ = FileTime::from_str_radix("0", 37);
83    /// ```
84    pub const fn from_str_radix(src: &str, radix: u32) -> Result<Self, ParseFileTimeError> {
85        match u64::from_str_radix(src, radix) {
86            Ok(ft) => Ok(Self::new(ft)),
87            Err(err) => Err(ParseFileTimeError::new(err)),
88        }
89    }
90}
91
92impl FromStr for FileTime {
93    type Err = ParseFileTimeError;
94
95    /// Parses a string `src` to return a value of `FileTime`.
96    ///
97    /// <div class="warning">
98    ///
99    /// The string is expected to be a decimal non-negative integer. If the
100    /// string is not a decimal integer, use [`FileTime::from_str_radix`]
101    /// instead.
102    ///
103    /// </div>
104    ///
105    /// # Errors
106    ///
107    /// Returns [`Err`] if [`u64::from_str`] returns an error.
108    ///
109    /// # Examples
110    ///
111    /// ```
112    /// # use core::str::FromStr;
113    /// #
114    /// # use nt_time::FileTime;
115    /// #
116    /// assert_eq!(FileTime::from_str("0"), Ok(FileTime::NT_TIME_EPOCH));
117    /// assert_eq!(
118    ///     FileTime::from_str("116444736000000000"),
119    ///     Ok(FileTime::UNIX_EPOCH)
120    /// );
121    /// assert_eq!(
122    ///     FileTime::from_str("+9223372036854775807"),
123    ///     Ok(FileTime::SIGNED_MAX)
124    /// );
125    /// assert_eq!(
126    ///     FileTime::from_str("+18446744073709551615"),
127    ///     Ok(FileTime::MAX)
128    /// );
129    ///
130    /// assert!(FileTime::from_str("").is_err());
131    ///
132    /// assert!(FileTime::from_str("a").is_err());
133    /// assert!(FileTime::from_str("_").is_err());
134    /// assert!(FileTime::from_str("-1").is_err());
135    /// assert!(FileTime::from_str("+").is_err());
136    /// assert!(FileTime::from_str("0 ").is_err());
137    ///
138    /// assert!(FileTime::from_str("18446744073709551616").is_err());
139    /// ```
140    fn from_str(src: &str) -> Result<Self, Self::Err> {
141        Self::from_str_radix(src, 10)
142    }
143}
144
145#[cfg(test)]
146mod tests {
147    use core::{
148        error::Error,
149        num::{IntErrorKind, ParseIntError},
150    };
151
152    #[cfg(feature = "std")]
153    use proptest::{prop_assert, prop_assert_eq};
154    #[cfg(feature = "std")]
155    use test_strategy::proptest;
156
157    use super::*;
158
159    #[test]
160    fn from_str_radix() {
161        assert_eq!(
162            FileTime::from_str_radix("0", 2).unwrap(),
163            FileTime::NT_TIME_EPOCH
164        );
165        assert_eq!(
166            FileTime::from_str_radix("+0", 2).unwrap(),
167            FileTime::NT_TIME_EPOCH
168        );
169        assert_eq!(
170            FileTime::from_str_radix(
171                "110011101101100011101111011010101001111101000000000000000",
172                2
173            )
174            .unwrap(),
175            FileTime::UNIX_EPOCH
176        );
177        assert_eq!(
178            FileTime::from_str_radix(
179                "+110011101101100011101111011010101001111101000000000000000",
180                2
181            )
182            .unwrap(),
183            FileTime::UNIX_EPOCH
184        );
185        assert_eq!(
186            FileTime::from_str_radix(
187                "111111111111111111111111111111111111111111111111111111111111111",
188                2
189            )
190            .unwrap(),
191            FileTime::SIGNED_MAX
192        );
193        assert_eq!(
194            FileTime::from_str_radix(
195                "+111111111111111111111111111111111111111111111111111111111111111",
196                2
197            )
198            .unwrap(),
199            FileTime::SIGNED_MAX
200        );
201        assert_eq!(
202            FileTime::from_str_radix(
203                "1111111111111111111111111111111111111111111111111111111111111111",
204                2
205            )
206            .unwrap(),
207            FileTime::MAX
208        );
209        assert_eq!(
210            FileTime::from_str_radix(
211                "+1111111111111111111111111111111111111111111111111111111111111111",
212                2
213            )
214            .unwrap(),
215            FileTime::MAX
216        );
217        assert_eq!(
218            FileTime::from_str_radix("0", 8).unwrap(),
219            FileTime::NT_TIME_EPOCH
220        );
221        assert_eq!(
222            FileTime::from_str_radix("+0", 8).unwrap(),
223            FileTime::NT_TIME_EPOCH
224        );
225        assert_eq!(
226            FileTime::from_str_radix("6355435732517500000", 8).unwrap(),
227            FileTime::UNIX_EPOCH
228        );
229        assert_eq!(
230            FileTime::from_str_radix("+6355435732517500000", 8).unwrap(),
231            FileTime::UNIX_EPOCH
232        );
233        assert_eq!(
234            FileTime::from_str_radix("777777777777777777777", 8).unwrap(),
235            FileTime::SIGNED_MAX
236        );
237        assert_eq!(
238            FileTime::from_str_radix("+777777777777777777777", 8).unwrap(),
239            FileTime::SIGNED_MAX
240        );
241        assert_eq!(
242            FileTime::from_str_radix("1777777777777777777777", 8).unwrap(),
243            FileTime::MAX
244        );
245        assert_eq!(
246            FileTime::from_str_radix("+1777777777777777777777", 8).unwrap(),
247            FileTime::MAX
248        );
249        assert_eq!(
250            FileTime::from_str_radix("0", 10).unwrap(),
251            FileTime::NT_TIME_EPOCH
252        );
253        assert_eq!(
254            FileTime::from_str_radix("+0", 10).unwrap(),
255            FileTime::NT_TIME_EPOCH
256        );
257        assert_eq!(
258            FileTime::from_str_radix("116444736000000000", 10).unwrap(),
259            FileTime::UNIX_EPOCH
260        );
261        assert_eq!(
262            FileTime::from_str_radix("+116444736000000000", 10).unwrap(),
263            FileTime::UNIX_EPOCH
264        );
265        assert_eq!(
266            FileTime::from_str_radix("9223372036854775807", 10).unwrap(),
267            FileTime::SIGNED_MAX
268        );
269        assert_eq!(
270            FileTime::from_str_radix("+9223372036854775807", 10).unwrap(),
271            FileTime::SIGNED_MAX
272        );
273        assert_eq!(
274            FileTime::from_str_radix("18446744073709551615", 10).unwrap(),
275            FileTime::MAX
276        );
277        assert_eq!(
278            FileTime::from_str_radix("+18446744073709551615", 10).unwrap(),
279            FileTime::MAX
280        );
281        assert_eq!(
282            FileTime::from_str_radix("0", 16).unwrap(),
283            FileTime::NT_TIME_EPOCH
284        );
285        assert_eq!(
286            FileTime::from_str_radix("+0", 16).unwrap(),
287            FileTime::NT_TIME_EPOCH
288        );
289        assert_eq!(
290            FileTime::from_str_radix("19db1ded53e8000", 16).unwrap(),
291            FileTime::UNIX_EPOCH
292        );
293        assert_eq!(
294            FileTime::from_str_radix("19DB1DED53E8000", 16).unwrap(),
295            FileTime::UNIX_EPOCH
296        );
297        assert_eq!(
298            FileTime::from_str_radix("+19db1ded53e8000", 16).unwrap(),
299            FileTime::UNIX_EPOCH
300        );
301        assert_eq!(
302            FileTime::from_str_radix("+19DB1DED53E8000", 16).unwrap(),
303            FileTime::UNIX_EPOCH
304        );
305        assert_eq!(
306            FileTime::from_str_radix("7fffffffffffffff", 16).unwrap(),
307            FileTime::SIGNED_MAX
308        );
309        assert_eq!(
310            FileTime::from_str_radix("7FFFFFFFFFFFFFFF", 16).unwrap(),
311            FileTime::SIGNED_MAX
312        );
313        assert_eq!(
314            FileTime::from_str_radix("+7fffffffffffffff", 16).unwrap(),
315            FileTime::SIGNED_MAX
316        );
317        assert_eq!(
318            FileTime::from_str_radix("+7FFFFFFFFFFFFFFF", 16).unwrap(),
319            FileTime::SIGNED_MAX
320        );
321        assert_eq!(
322            FileTime::from_str_radix("ffffffffffffffff", 16).unwrap(),
323            FileTime::MAX
324        );
325        assert_eq!(
326            FileTime::from_str_radix("FFFFFFFFFFFFFFFF", 16).unwrap(),
327            FileTime::MAX
328        );
329        assert_eq!(
330            FileTime::from_str_radix("+ffffffffffffffff", 16).unwrap(),
331            FileTime::MAX
332        );
333        assert_eq!(
334            FileTime::from_str_radix("+FFFFFFFFFFFFFFFF", 16).unwrap(),
335            FileTime::MAX
336        );
337        assert_eq!(
338            FileTime::from_str_radix("0", 36).unwrap(),
339            FileTime::NT_TIME_EPOCH
340        );
341        assert_eq!(
342            FileTime::from_str_radix("+0", 36).unwrap(),
343            FileTime::NT_TIME_EPOCH
344        );
345        assert_eq!(
346            FileTime::from_str_radix("vuk7p84etc0", 36).unwrap(),
347            FileTime::UNIX_EPOCH
348        );
349        assert_eq!(
350            FileTime::from_str_radix("VUK7P84ETC0", 36).unwrap(),
351            FileTime::UNIX_EPOCH
352        );
353        assert_eq!(
354            FileTime::from_str_radix("+vuk7p84etc0", 36).unwrap(),
355            FileTime::UNIX_EPOCH
356        );
357        assert_eq!(
358            FileTime::from_str_radix("+VUK7P84ETC0", 36).unwrap(),
359            FileTime::UNIX_EPOCH
360        );
361        assert_eq!(
362            FileTime::from_str_radix("1y2p0ij32e8e7", 36).unwrap(),
363            FileTime::SIGNED_MAX
364        );
365        assert_eq!(
366            FileTime::from_str_radix("1Y2P0IJ32E8E7", 36).unwrap(),
367            FileTime::SIGNED_MAX
368        );
369        assert_eq!(
370            FileTime::from_str_radix("+1y2p0ij32e8e7", 36).unwrap(),
371            FileTime::SIGNED_MAX
372        );
373        assert_eq!(
374            FileTime::from_str_radix("+1Y2P0IJ32E8E7", 36).unwrap(),
375            FileTime::SIGNED_MAX
376        );
377        assert_eq!(
378            FileTime::from_str_radix("3w5e11264sgsf", 36).unwrap(),
379            FileTime::MAX
380        );
381        assert_eq!(
382            FileTime::from_str_radix("3W5E11264SGSF", 36).unwrap(),
383            FileTime::MAX
384        );
385        assert_eq!(
386            FileTime::from_str_radix("+3w5e11264sgsf", 36).unwrap(),
387            FileTime::MAX
388        );
389        assert_eq!(
390            FileTime::from_str_radix("+3W5E11264SGSF", 36).unwrap(),
391            FileTime::MAX
392        );
393    }
394
395    #[test]
396    fn from_str_radix_with_invalid_digit_radix() {
397        assert_eq!(
398            FileTime::from_str_radix("2", 2)
399                .unwrap_err()
400                .source()
401                .unwrap()
402                .downcast_ref::<ParseIntError>()
403                .unwrap()
404                .kind(),
405            &IntErrorKind::InvalidDigit
406        );
407        assert_eq!(
408            FileTime::from_str_radix("8", 8)
409                .unwrap_err()
410                .source()
411                .unwrap()
412                .downcast_ref::<ParseIntError>()
413                .unwrap()
414                .kind(),
415            &IntErrorKind::InvalidDigit
416        );
417        assert_eq!(
418            FileTime::from_str_radix("a", 10)
419                .unwrap_err()
420                .source()
421                .unwrap()
422                .downcast_ref::<ParseIntError>()
423                .unwrap()
424                .kind(),
425            &IntErrorKind::InvalidDigit
426        );
427        assert_eq!(
428            FileTime::from_str_radix("A", 10)
429                .unwrap_err()
430                .source()
431                .unwrap()
432                .downcast_ref::<ParseIntError>()
433                .unwrap()
434                .kind(),
435            &IntErrorKind::InvalidDigit
436        );
437        assert_eq!(
438            FileTime::from_str_radix("g", 16)
439                .unwrap_err()
440                .source()
441                .unwrap()
442                .downcast_ref::<ParseIntError>()
443                .unwrap()
444                .kind(),
445            &IntErrorKind::InvalidDigit
446        );
447        assert_eq!(
448            FileTime::from_str_radix("G", 16)
449                .unwrap_err()
450                .source()
451                .unwrap()
452                .downcast_ref::<ParseIntError>()
453                .unwrap()
454                .kind(),
455            &IntErrorKind::InvalidDigit
456        );
457    }
458
459    #[test]
460    fn from_str_radix_when_empty() {
461        assert_eq!(
462            FileTime::from_str_radix("", 16)
463                .unwrap_err()
464                .source()
465                .unwrap()
466                .downcast_ref::<ParseIntError>()
467                .unwrap()
468                .kind(),
469            &IntErrorKind::Empty
470        );
471    }
472
473    #[test]
474    fn from_str_radix_with_invalid_digit() {
475        assert_eq!(
476            FileTime::from_str_radix("Z", 16)
477                .unwrap_err()
478                .source()
479                .unwrap()
480                .downcast_ref::<ParseIntError>()
481                .unwrap()
482                .kind(),
483            &IntErrorKind::InvalidDigit
484        );
485        assert_eq!(
486            FileTime::from_str_radix("_", 16)
487                .unwrap_err()
488                .source()
489                .unwrap()
490                .downcast_ref::<ParseIntError>()
491                .unwrap()
492                .kind(),
493            &IntErrorKind::InvalidDigit
494        );
495        assert_eq!(
496            FileTime::from_str_radix("-1", 16)
497                .unwrap_err()
498                .source()
499                .unwrap()
500                .downcast_ref::<ParseIntError>()
501                .unwrap()
502                .kind(),
503            &IntErrorKind::InvalidDigit
504        );
505        assert_eq!(
506            FileTime::from_str_radix("+", 16)
507                .unwrap_err()
508                .source()
509                .unwrap()
510                .downcast_ref::<ParseIntError>()
511                .unwrap()
512                .kind(),
513            &IntErrorKind::InvalidDigit
514        );
515        assert_eq!(
516            FileTime::from_str_radix("-", 16)
517                .unwrap_err()
518                .source()
519                .unwrap()
520                .downcast_ref::<ParseIntError>()
521                .unwrap()
522                .kind(),
523            &IntErrorKind::InvalidDigit
524        );
525        assert_eq!(
526            FileTime::from_str_radix(" 0", 16)
527                .unwrap_err()
528                .source()
529                .unwrap()
530                .downcast_ref::<ParseIntError>()
531                .unwrap()
532                .kind(),
533            &IntErrorKind::InvalidDigit
534        );
535        assert_eq!(
536            FileTime::from_str_radix("0 ", 16)
537                .unwrap_err()
538                .source()
539                .unwrap()
540                .downcast_ref::<ParseIntError>()
541                .unwrap()
542                .kind(),
543            &IntErrorKind::InvalidDigit
544        );
545    }
546
547    #[test]
548    fn from_str_radix_when_positive_overflow() {
549        assert_eq!(
550            FileTime::from_str_radix(
551                "10000000000000000000000000000000000000000000000000000000000000000",
552                2
553            )
554            .unwrap_err()
555            .source()
556            .unwrap()
557            .downcast_ref::<ParseIntError>()
558            .unwrap()
559            .kind(),
560            &IntErrorKind::PosOverflow
561        );
562        assert_eq!(
563            FileTime::from_str_radix("2000000000000000000000", 8)
564                .unwrap_err()
565                .source()
566                .unwrap()
567                .downcast_ref::<ParseIntError>()
568                .unwrap()
569                .kind(),
570            &IntErrorKind::PosOverflow
571        );
572        assert_eq!(
573            FileTime::from_str_radix("18446744073709551616", 10)
574                .unwrap_err()
575                .source()
576                .unwrap()
577                .downcast_ref::<ParseIntError>()
578                .unwrap()
579                .kind(),
580            &IntErrorKind::PosOverflow
581        );
582        assert_eq!(
583            FileTime::from_str_radix("10000000000000000", 16)
584                .unwrap_err()
585                .source()
586                .unwrap()
587                .downcast_ref::<ParseIntError>()
588                .unwrap()
589                .kind(),
590            &IntErrorKind::PosOverflow
591        );
592        assert_eq!(
593            FileTime::from_str_radix("3w5e11264sgsg", 36)
594                .unwrap_err()
595                .source()
596                .unwrap()
597                .downcast_ref::<ParseIntError>()
598                .unwrap()
599                .kind(),
600            &IntErrorKind::PosOverflow
601        );
602        assert_eq!(
603            FileTime::from_str_radix("3W5E11264SGSG", 36)
604                .unwrap_err()
605                .source()
606                .unwrap()
607                .downcast_ref::<ParseIntError>()
608                .unwrap()
609                .kind(),
610            &IntErrorKind::PosOverflow
611        );
612    }
613
614    #[test]
615    #[should_panic]
616    fn from_str_radix_when_radix_is_less_than_2() {
617        let _ = FileTime::from_str_radix("0", 1);
618    }
619
620    #[test]
621    #[should_panic]
622    fn from_str_radix_when_radix_is_greater_than_36() {
623        let _ = FileTime::from_str_radix("0", 37);
624    }
625
626    #[test]
627    const fn from_str_radix_is_const_fn() {
628        const _: Result<FileTime, ParseFileTimeError> = FileTime::from_str_radix("0", 2);
629    }
630
631    #[test]
632    fn from_str() {
633        assert_eq!(FileTime::from_str("0").unwrap(), FileTime::NT_TIME_EPOCH);
634        assert_eq!(FileTime::from_str("+0").unwrap(), FileTime::NT_TIME_EPOCH);
635        assert_eq!(
636            FileTime::from_str("116444736000000000").unwrap(),
637            FileTime::UNIX_EPOCH
638        );
639        assert_eq!(
640            FileTime::from_str("+116444736000000000").unwrap(),
641            FileTime::UNIX_EPOCH
642        );
643        assert_eq!(
644            FileTime::from_str("9223372036854775807").unwrap(),
645            FileTime::SIGNED_MAX
646        );
647        assert_eq!(
648            FileTime::from_str("+9223372036854775807").unwrap(),
649            FileTime::SIGNED_MAX
650        );
651        assert_eq!(
652            FileTime::from_str("18446744073709551615").unwrap(),
653            FileTime::MAX
654        );
655        assert_eq!(
656            FileTime::from_str("+18446744073709551615").unwrap(),
657            FileTime::MAX
658        );
659    }
660
661    #[cfg(feature = "std")]
662    #[proptest]
663    fn from_str_roundtrip(#[strategy(r"\+?[0-9]{1,19}")] s: std::string::String) {
664        let ft = s.parse().unwrap();
665        prop_assert_eq!(FileTime::from_str(&s).unwrap(), FileTime::new(ft));
666    }
667
668    #[test]
669    fn from_str_when_empty() {
670        assert_eq!(
671            FileTime::from_str("")
672                .unwrap_err()
673                .source()
674                .unwrap()
675                .downcast_ref::<ParseIntError>()
676                .unwrap()
677                .kind(),
678            &IntErrorKind::Empty
679        );
680    }
681
682    #[test]
683    fn from_str_with_invalid_digit() {
684        assert_eq!(
685            FileTime::from_str("a")
686                .unwrap_err()
687                .source()
688                .unwrap()
689                .downcast_ref::<ParseIntError>()
690                .unwrap()
691                .kind(),
692            &IntErrorKind::InvalidDigit
693        );
694        assert_eq!(
695            FileTime::from_str("_")
696                .unwrap_err()
697                .source()
698                .unwrap()
699                .downcast_ref::<ParseIntError>()
700                .unwrap()
701                .kind(),
702            &IntErrorKind::InvalidDigit
703        );
704        assert_eq!(
705            FileTime::from_str("-1")
706                .unwrap_err()
707                .source()
708                .unwrap()
709                .downcast_ref::<ParseIntError>()
710                .unwrap()
711                .kind(),
712            &IntErrorKind::InvalidDigit
713        );
714        assert_eq!(
715            FileTime::from_str("+")
716                .unwrap_err()
717                .source()
718                .unwrap()
719                .downcast_ref::<ParseIntError>()
720                .unwrap()
721                .kind(),
722            &IntErrorKind::InvalidDigit
723        );
724        assert_eq!(
725            FileTime::from_str("-")
726                .unwrap_err()
727                .source()
728                .unwrap()
729                .downcast_ref::<ParseIntError>()
730                .unwrap()
731                .kind(),
732            &IntErrorKind::InvalidDigit
733        );
734        assert_eq!(
735            FileTime::from_str(" 0")
736                .unwrap_err()
737                .source()
738                .unwrap()
739                .downcast_ref::<ParseIntError>()
740                .unwrap()
741                .kind(),
742            &IntErrorKind::InvalidDigit
743        );
744        assert_eq!(
745            FileTime::from_str("0 ")
746                .unwrap_err()
747                .source()
748                .unwrap()
749                .downcast_ref::<ParseIntError>()
750                .unwrap()
751                .kind(),
752            &IntErrorKind::InvalidDigit
753        );
754    }
755
756    #[cfg(feature = "std")]
757    #[proptest]
758    fn from_str_with_invalid_digit_roundtrip(
759        #[strategy(r"-[0-9]+|[^0-9]+")] s: std::string::String,
760    ) {
761        prop_assert!(FileTime::from_str(&s).is_err());
762    }
763
764    #[test]
765    fn from_str_when_positive_overflow() {
766        assert_eq!(
767            FileTime::from_str("18446744073709551616")
768                .unwrap_err()
769                .source()
770                .unwrap()
771                .downcast_ref::<ParseIntError>()
772                .unwrap()
773                .kind(),
774            &IntErrorKind::PosOverflow
775        );
776    }
777}