#[macro_use] extern crate proptest;
#[allow(unused_imports)]
use std::ascii::AsciiExt;
fn parse_date(s: &str) -> Option<(u32, u32, u32)> {
if 10 != s.len() { return None; }
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))))
}
proptest! {
fn doesnt_crash(ref s in "\\PC*") {
parse_date(s);
}
fn parses_all_valid_dates(ref 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();
}