| //- |
| // Copyright 2017 Jason Lingle |
| // |
| // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or |
| // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license |
| // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your |
| // option. This file may not be copied, modified, or distributed |
| // except according to those terms. |
| |
| use proptest::prelude::*; |
| |
| fn parse_date(s: &str) -> Option<(u32, u32, u32)> { |
| if 10 != s.len() { |
| return None; |
| } |
| |
| // NEW: Ignore non-ASCII strings so we don't need to deal with Unicode. |
| if !s.is_ascii() { |
| return None; |
| } |
| |
| if "-" != &s[4..5] || "-" != &s[7..8] { |
| return None; |
| } |
| |
| let year = &s[0..4]; |
| let month = &s[6..7]; // ! |
| let day = &s[8..10]; |
| |
| year.parse::<u32>().ok().and_then(|y| { |
| month |
| .parse::<u32>() |
| .ok() |
| .and_then(|m| day.parse::<u32>().ok().map(|d| (y, m, d))) |
| }) |
| } |
| |
| // NB We omit #[test] on these functions so that main() can call them. |
| proptest! { |
| fn doesnt_crash(s in "\\PC*") { |
| parse_date(&s); |
| } |
| |
| fn parses_all_valid_dates(s in "[0-9]{4}-[0-9]{2}-[0-9]{2}") { |
| parse_date(&s).unwrap(); |
| } |
| |
| fn parses_date_back_to_original(y in 0u32..10_000, |
| m in 1u32..13, d in 1u32..32) { |
| let (y2, m2, d2) = parse_date( |
| &format!("{:04}-{:02}-{:02}", y, m, d)).unwrap(); |
| prop_assert_eq!((y, m, d), (y2, m2, d2)); |
| } |
| } |
| |
| fn main() { |
| assert_eq!(None, parse_date("2017-06-1")); |
| assert_eq!(None, parse_date("2017-06-170")); |
| assert_eq!(None, parse_date("2017006-17")); |
| assert_eq!(None, parse_date("2017-06017")); |
| assert_eq!(Some((2017, 6, 17)), parse_date("2017-06-17")); |
| |
| doesnt_crash(); |
| parses_all_valid_dates(); |
| parses_date_back_to_original(); |
| } |