diff options
Diffstat (limited to 'components/script/dom/bindings/str.rs')
-rw-r--r-- | components/script/dom/bindings/str.rs | 101 |
1 files changed, 101 insertions, 0 deletions
diff --git a/components/script/dom/bindings/str.rs b/components/script/dom/bindings/str.rs index 6601d8e6856..596b2db14b2 100644 --- a/components/script/dom/bindings/str.rs +++ b/components/script/dom/bindings/str.rs @@ -279,6 +279,20 @@ impl DOMString { _ => false } } + + /// A valid date string should be "YYYY-MM-DD" + /// YYYY must be four or more digits, MM and DD both must be two digits + /// https://html.spec.whatwg.org/multipage/#valid-date-string + pub fn is_valid_date_string(&self) -> bool { + parse_date_string(&*self.0).is_ok() + } + + /// A valid month string should be "YYYY-MM" + /// YYYY must be four or more digits, MM both must be two digits + /// https://html.spec.whatwg.org/multipage/#valid-month-string + pub fn is_valid_month_string(&self) -> bool { + parse_month_string(&*self.0).is_ok() + } } impl Borrow<str> for DOMString { @@ -403,3 +417,90 @@ impl Extend<char> for DOMString { self.0.extend(iterable) } } + +/// https://html.spec.whatwg.org/multipage/#parse-a-month-string +fn parse_month_string(value: &str) -> Result<(u32, u32), ()> { + // Step 1, 2, 3 + let (year_int, month_int) = parse_month_component(value)?; + + // Step 4 + if value.split("-").nth(2).is_some() { + return Err(()); + } + // Step 5 + Ok((year_int, month_int)) +} + +/// https://html.spec.whatwg.org/multipage/#parse-a-date-string +fn parse_date_string(value: &str) -> Result<(u32, u32, u32), ()> { + // Step 1, 2, 3 + let (year_int, month_int, day_int) = parse_date_component(value)?; + + // Step 4 + if value.split('-').nth(3).is_some() { + return Err(()); + } + + // Step 5, 6 + Ok((year_int, month_int, day_int)) +} + +/// https://html.spec.whatwg.org/multipage/#parse-a-month-component +fn parse_month_component(value: &str) -> Result<(u32, u32), ()> { + // Step 3 + let mut iterator = value.split('-'); + let year = iterator.next().ok_or(())?; + let month = iterator.next().ok_or(())?; + + // Step 1, 2 + let year_int = year.parse::<u32>().map_err(|_| ())?; + if year.len() < 4 || year_int == 0 { + return Err(()); + } + + // Step 4, 5 + let month_int = month.parse::<u32>().map_err(|_| ())?; + if month.len() != 2 || month_int > 12 || month_int < 1 { + return Err(()); + } + + // Step 6 + Ok((year_int, month_int)) +} + +/// https://html.spec.whatwg.org/multipage/#parse-a-date-component +fn parse_date_component(value: &str) -> Result<(u32, u32, u32), ()> { + // Step 1 + let (year_int, month_int) = parse_month_component(value)?; + + // Step 3, 4 + let day = value.split('-').nth(2).ok_or(())?; + let day_int = day.parse::<u32>().map_err(|_| ())?; + if day.len() != 2 { + return Err(()); + } + + // Step 2, 5 + let max_day = max_day_in_month(year_int, month_int)?; + if day_int == 0 || day_int > max_day { + return Err(()); + } + + // Step 6 + Ok((year_int, month_int, day_int)) +} + +fn max_day_in_month(year_num: u32, month_num: u32) -> Result<u32, ()> { + match month_num { + 1|3|5|7|8|10|12 => Ok(31), + 4|6|9|11 => Ok(30), + 2 => { + if year_num % 400 == 0 || (year_num % 4 == 0 && year_num % 100 != 0) { + Ok(29) + } else { + Ok(28) + } + }, + _ => Err(()) + } +} |