diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-18 02:49:50 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-18 02:49:50 +0000 |
commit | 9835e2ae736235810b4ea1c162ca5e65c547e770 (patch) | |
tree | 3fcebf40ed70e581d776a8a4c65923e8ec20e026 /vendor/chrono/src/format/scan.rs | |
parent | Releasing progress-linux version 1.70.0+dfsg2-1~progress7.99u1. (diff) | |
download | rustc-9835e2ae736235810b4ea1c162ca5e65c547e770.tar.xz rustc-9835e2ae736235810b4ea1c162ca5e65c547e770.zip |
Merging upstream version 1.71.1+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/chrono/src/format/scan.rs')
-rw-r--r-- | vendor/chrono/src/format/scan.rs | 121 |
1 files changed, 93 insertions, 28 deletions
diff --git a/vendor/chrono/src/format/scan.rs b/vendor/chrono/src/format/scan.rs index 0efb1ee3d..263fec556 100644 --- a/vendor/chrono/src/format/scan.rs +++ b/vendor/chrono/src/format/scan.rs @@ -8,13 +8,13 @@ #![allow(deprecated)] use super::{ParseResult, INVALID, OUT_OF_RANGE, TOO_SHORT}; -use Weekday; +use crate::Weekday; /// Returns true when two slices are equal case-insensitively (in ASCII). /// Assumes that the `pattern` is already converted to lower case. fn equals(s: &str, pattern: &str) -> bool { let mut xs = s.as_bytes().iter().map(|&c| match c { - b'A'...b'Z' => c + 32, + b'A'..=b'Z' => c + 32, _ => c, }); let mut ys = pattern.as_bytes().iter().cloned(); @@ -34,7 +34,7 @@ fn equals(s: &str, pattern: &str) -> bool { /// More than `max` digits are consumed up to the first `max` digits. /// Any number that does not fit in `i64` is an error. #[inline] -pub fn number(s: &str, min: usize, max: usize) -> ParseResult<(&str, i64)> { +pub(super) fn number(s: &str, min: usize, max: usize) -> ParseResult<(&str, i64)> { assert!(min <= max); // We are only interested in ascii numbers, so we can work with the `str` as bytes. We stop on @@ -48,7 +48,7 @@ pub fn number(s: &str, min: usize, max: usize) -> ParseResult<(&str, i64)> { let mut n = 0i64; for (i, c) in bytes.iter().take(max).cloned().enumerate() { // cloned() = copied() - if c < b'0' || b'9' < c { + if !(b'0'..=b'9').contains(&c) { if i < min { return Err(INVALID); } else { @@ -62,12 +62,12 @@ pub fn number(s: &str, min: usize, max: usize) -> ParseResult<(&str, i64)> { }; } - Ok((&s[::core::cmp::min(max, bytes.len())..], n)) + Ok((&s[core::cmp::min(max, bytes.len())..], n)) } /// Tries to consume at least one digits as a fractional second. /// Returns the number of whole nanoseconds (0--999,999,999). -pub fn nanosecond(s: &str) -> ParseResult<(&str, i64)> { +pub(super) fn nanosecond(s: &str) -> ParseResult<(&str, i64)> { // record the number of digits consumed for later scaling. let origlen = s.len(); let (s, v) = number(s, 1, 9)?; @@ -79,14 +79,14 @@ pub fn nanosecond(s: &str) -> ParseResult<(&str, i64)> { let v = v.checked_mul(SCALE[consumed]).ok_or(OUT_OF_RANGE)?; // if there are more than 9 digits, skip next digits. - let s = s.trim_left_matches(|c: char| '0' <= c && c <= '9'); + let s = s.trim_left_matches(|c: char| ('0'..='9').contains(&c)); Ok((s, v)) } /// Tries to consume a fixed number of digits as a fractional second. /// Returns the number of whole nanoseconds (0--999,999,999). -pub fn nanosecond_fixed(s: &str, digits: usize) -> ParseResult<(&str, i64)> { +pub(super) fn nanosecond_fixed(s: &str, digits: usize) -> ParseResult<(&str, i64)> { // record the number of digits consumed for later scaling. let (s, v) = number(s, digits, digits)?; @@ -99,7 +99,7 @@ pub fn nanosecond_fixed(s: &str, digits: usize) -> ParseResult<(&str, i64)> { } /// Tries to parse the month index (0 through 11) with the first three ASCII letters. -pub fn short_month0(s: &str) -> ParseResult<(&str, u8)> { +pub(super) fn short_month0(s: &str) -> ParseResult<(&str, u8)> { if s.len() < 3 { return Err(TOO_SHORT); } @@ -123,7 +123,7 @@ pub fn short_month0(s: &str) -> ParseResult<(&str, u8)> { } /// Tries to parse the weekday with the first three ASCII letters. -pub fn short_weekday(s: &str) -> ParseResult<(&str, Weekday)> { +pub(super) fn short_weekday(s: &str) -> ParseResult<(&str, Weekday)> { if s.len() < 3 { return Err(TOO_SHORT); } @@ -143,9 +143,9 @@ pub fn short_weekday(s: &str) -> ParseResult<(&str, Weekday)> { /// Tries to parse the month index (0 through 11) with short or long month names. /// It prefers long month names to short month names when both are possible. -pub fn short_or_long_month0(s: &str) -> ParseResult<(&str, u8)> { +pub(super) fn short_or_long_month0(s: &str) -> ParseResult<(&str, u8)> { // lowercased month names, minus first three chars - static LONG_MONTH_SUFFIXES: [&'static str; 12] = + static LONG_MONTH_SUFFIXES: [&str; 12] = ["uary", "ruary", "ch", "il", "", "e", "y", "ust", "tember", "ober", "ember", "ember"]; let (mut s, month0) = short_month0(s)?; @@ -161,9 +161,9 @@ pub fn short_or_long_month0(s: &str) -> ParseResult<(&str, u8)> { /// Tries to parse the weekday with short or long weekday names. /// It prefers long weekday names to short weekday names when both are possible. -pub fn short_or_long_weekday(s: &str) -> ParseResult<(&str, Weekday)> { +pub(super) fn short_or_long_weekday(s: &str) -> ParseResult<(&str, Weekday)> { // lowercased weekday names, minus first three chars - static LONG_WEEKDAY_SUFFIXES: [&'static str; 7] = + static LONG_WEEKDAY_SUFFIXES: [&str; 7] = ["day", "sday", "nesday", "rsday", "day", "urday", "day"]; let (mut s, weekday) = short_weekday(s)?; @@ -178,7 +178,7 @@ pub fn short_or_long_weekday(s: &str) -> ParseResult<(&str, Weekday)> { } /// Tries to consume exactly one given character. -pub fn char(s: &str, c1: u8) -> ParseResult<&str> { +pub(super) fn char(s: &str, c1: u8) -> ParseResult<&str> { match s.as_bytes().first() { Some(&c) if c == c1 => Ok(&s[1..]), Some(_) => Err(INVALID), @@ -187,7 +187,7 @@ pub fn char(s: &str, c1: u8) -> ParseResult<&str> { } /// Tries to consume one or more whitespace. -pub fn space(s: &str) -> ParseResult<&str> { +pub(super) fn space(s: &str) -> ParseResult<&str> { let s_ = s.trim_left(); if s_.len() < s.len() { Ok(s_) @@ -199,7 +199,7 @@ pub fn space(s: &str) -> ParseResult<&str> { } /// Consumes any number (including zero) of colon or spaces. -pub fn colon_or_space(s: &str) -> ParseResult<&str> { +pub(super) fn colon_or_space(s: &str) -> ParseResult<&str> { Ok(s.trim_left_matches(|c: char| c == ':' || c.is_whitespace())) } @@ -207,7 +207,7 @@ pub fn colon_or_space(s: &str) -> ParseResult<&str> { /// /// The additional `colon` may be used to parse a mandatory or optional `:` /// between hours and minutes, and should return either a new suffix or `Err` when parsing fails. -pub fn timezone_offset<F>(s: &str, consume_colon: F) -> ParseResult<(&str, i32)> +pub(super) fn timezone_offset<F>(s: &str, consume_colon: F) -> ParseResult<(&str, i32)> where F: FnMut(&str) -> ParseResult<&str>, { @@ -240,7 +240,7 @@ where // hours (00--99) let hours = match digits(s)? { - (h1 @ b'0'...b'9', h2 @ b'0'...b'9') => i32::from((h1 - b'0') * 10 + (h2 - b'0')), + (h1 @ b'0'..=b'9', h2 @ b'0'..=b'9') => i32::from((h1 - b'0') * 10 + (h2 - b'0')), _ => return Err(INVALID), }; s = &s[2..]; @@ -252,8 +252,8 @@ where // if the next two items are digits then we have to add minutes let minutes = if let Ok(ds) = digits(s) { match ds { - (m1 @ b'0'...b'5', m2 @ b'0'...b'9') => i32::from((m1 - b'0') * 10 + (m2 - b'0')), - (b'6'...b'9', b'0'...b'9') => return Err(OUT_OF_RANGE), + (m1 @ b'0'..=b'5', m2 @ b'0'..=b'9') => i32::from((m1 - b'0') * 10 + (m2 - b'0')), + (b'6'..=b'9', b'0'..=b'9') => return Err(OUT_OF_RANGE), _ => return Err(INVALID), } } else if allow_missing_minutes { @@ -272,7 +272,7 @@ where } /// Same as `timezone_offset` but also allows for `z`/`Z` which is the same as `+00:00`. -pub fn timezone_offset_zulu<F>(s: &str, colon: F) -> ParseResult<(&str, i32)> +pub(super) fn timezone_offset_zulu<F>(s: &str, colon: F) -> ParseResult<(&str, i32)> where F: FnMut(&str) -> ParseResult<&str>, { @@ -296,7 +296,7 @@ where /// Same as `timezone_offset` but also allows for `z`/`Z` which is the same as /// `+00:00`, and allows missing minutes entirely. -pub fn timezone_offset_permissive<F>(s: &str, colon: F) -> ParseResult<(&str, i32)> +pub(super) fn timezone_offset_permissive<F>(s: &str, colon: F) -> ParseResult<(&str, i32)> where F: FnMut(&str) -> ParseResult<&str>, { @@ -308,16 +308,16 @@ where /// Same as `timezone_offset` but also allows for RFC 2822 legacy timezones. /// May return `None` which indicates an insufficient offset data (i.e. `-0000`). -pub fn timezone_offset_2822(s: &str) -> ParseResult<(&str, Option<i32>)> { +pub(super) fn timezone_offset_2822(s: &str) -> ParseResult<(&str, Option<i32>)> { // tries to parse legacy time zone names let upto = s .as_bytes() .iter() .position(|&c| match c { - b'a'...b'z' | b'A'...b'Z' => false, + b'a'..=b'z' | b'A'..=b'Z' => false, _ => true, }) - .unwrap_or_else(|| s.len()); + .unwrap_or(s.len()); if upto > 0 { let name = &s[..upto]; let s = &s[upto..]; @@ -343,8 +343,73 @@ pub fn timezone_offset_2822(s: &str) -> ParseResult<(&str, Option<i32>)> { } } -/// Tries to consume everyting until next whitespace-like symbol. +/// Tries to consume everything until next whitespace-like symbol. /// Does not provide any offset information from the consumed data. -pub fn timezone_name_skip(s: &str) -> ParseResult<(&str, ())> { +pub(super) fn timezone_name_skip(s: &str) -> ParseResult<(&str, ())> { Ok((s.trim_left_matches(|c: char| !c.is_whitespace()), ())) } + +/// Tries to consume an RFC2822 comment including preceding ` `. +/// +/// Returns the remaining string after the closing parenthesis. +pub(super) fn comment_2822(s: &str) -> ParseResult<(&str, ())> { + use CommentState::*; + + let s = s.trim_start(); + + let mut state = Start; + for (i, c) in s.bytes().enumerate() { + state = match (state, c) { + (Start, b'(') => Next(1), + (Next(1), b')') => return Ok((&s[i + 1..], ())), + (Next(depth), b'\\') => Escape(depth), + (Next(depth), b'(') => Next(depth + 1), + (Next(depth), b')') => Next(depth - 1), + (Next(depth), _) | (Escape(depth), _) => Next(depth), + _ => return Err(INVALID), + }; + } + + Err(TOO_SHORT) +} + +enum CommentState { + Start, + Next(usize), + Escape(usize), +} + +#[cfg(test)] +#[test] +fn test_rfc2822_comments() { + let testdata = [ + ("", Err(TOO_SHORT)), + (" ", Err(TOO_SHORT)), + ("x", Err(INVALID)), + ("(", Err(TOO_SHORT)), + ("()", Ok("")), + (" \r\n\t()", Ok("")), + ("() ", Ok(" ")), + ("()z", Ok("z")), + ("(x)", Ok("")), + ("(())", Ok("")), + ("((()))", Ok("")), + ("(x(x(x)x)x)", Ok("")), + ("( x ( x ( x ) x ) x )", Ok("")), + (r"(\)", Err(TOO_SHORT)), + (r"(\()", Ok("")), + (r"(\))", Ok("")), + (r"(\\)", Ok("")), + ("(()())", Ok("")), + ("( x ( x ) x ( x ) x )", Ok("")), + ]; + + for (test_in, expected) in testdata.iter() { + let actual = comment_2822(test_in).map(|(s, _)| s); + assert_eq!( + *expected, actual, + "{:?} expected to produce {:?}, but produced {:?}.", + test_in, expected, actual + ); + } +} |