//- // Copyright 2017 Jason Lingle // // Licensed under the Apache License, Version 2.0 or the MIT license // , 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::().ok().and_then(|y| { month .parse::() .ok() .and_then(|m| day.parse::().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(); }