Skip to content

Commit

Permalink
Refactor fn maybe_colon_or_space
Browse files Browse the repository at this point in the history
Rename colon_or_space to maybe_colon_or_space.

Refactor fn maybe_colon_or_space to be simpler.

PR chronotope#807 feedback from @esheppa.

Issue chronotope#660
  • Loading branch information
jtmoon79 committed Mar 13, 2023
1 parent 2f7c3f9 commit 76cc9cb
Show file tree
Hide file tree
Showing 2 changed files with 83 additions and 71 deletions.
11 changes: 7 additions & 4 deletions src/format/parse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -452,23 +452,26 @@ where
| &TimezoneOffsetTripleColon
| &TimezoneOffset => {
s = scan::trim1(s);
let offset = try_consume!(scan::timezone_offset(s, scan::colon_or_space));
let offset =
try_consume!(scan::timezone_offset(s, scan::maybe_colon_or_space));
parsed.set_offset(i64::from(offset)).map_err(|e| (s, e))?;
}

&TimezoneOffsetColonZ | &TimezoneOffsetZ => {
s = scan::trim1(s);
let offset =
try_consume!(scan::timezone_offset_zulu(s, scan::colon_or_space));
try_consume!(scan::timezone_offset_zulu(s, scan::maybe_colon_or_space));
parsed.set_offset(i64::from(offset)).map_err(|e| (s, e))?;
}

&Internal(InternalFixed {
val: InternalInternal::TimezoneOffsetPermissive,
}) => {
s = scan::trim1(s);
let offset =
try_consume!(scan::timezone_offset_permissive(s, scan::colon_or_space));
let offset = try_consume!(scan::timezone_offset_permissive(
s,
scan::maybe_colon_or_space
));
parsed.set_offset(i64::from(offset)).map_err(|e| (s, e))?;
}

Expand Down
143 changes: 76 additions & 67 deletions src/format/scan.rs
Original file line number Diff line number Diff line change
Expand Up @@ -219,48 +219,46 @@ pub(super) fn trim1(s: &str) -> &str {
}
}

/// Is `s.next()` whitespace?
/// Helper function to `maybe_colon_or_space`.
fn next_is_whitespace(s: &str) -> bool {
s.chars().next().map(|c| c.is_whitespace()).unwrap_or_default()
}

/// Allow a colon with possible one-character whitespace padding.
/// Consumes zero or one of these leading patterns:
/// `":"`, `" "`, `" :"`, `": "`, or `" : "`.
pub(super) fn colon_or_space(s: &str) -> ParseResult<&str> {
let c0s = match s.chars().next() {
Some(c) => c,
None => {
return Ok(s);
}
};
if c0s != ':' && !c0s.is_whitespace() {
/// Always returns `Ok(s)`.
pub(super) fn maybe_colon_or_space(mut s: &str) -> ParseResult<&str> {
if s.is_empty() {
// nothing consumed
return Ok(s);
}
let c1s = s.chars().nth(1);
match (c0s, c1s) {
(c0, None) if c0 == ':' || c0.is_whitespace() => {
return Ok(s_next(s));
}
(c0, Some(c1)) if c0 == ':' && c1.is_whitespace() => {
return Ok(s_next(s_next(s)));
}
(c0, Some(c1)) if c0 == ':' && !c1.is_whitespace() => {
return Ok(s_next(s));
}
(c0, Some(c1)) if c0.is_whitespace() && (!c1.is_whitespace() && c1 != ':') => {
return Ok(s_next(s));

if s.starts_with(':') {
s = s_next(s);
if next_is_whitespace(s) {
s = s_next(s);
}
_ => {}
// consumed `":"` or `": "`
return Ok(s);
} else if !next_is_whitespace(s) {
return Ok(s);
}
let c2s = s.chars().nth(2);
match (c0s, c1s, c2s) {
(c0, Some(c1), None) if c0.is_whitespace() && c1 == ':' => Ok(s_next(s_next(s))),
(c0, Some(_), None) if c0.is_whitespace() => Ok(s_next(s)),
(c0, Some(c1), Some(c2)) if c0.is_whitespace() && c1 == ':' && !c2.is_whitespace() => {
Ok(s_next(s_next(s)))
}
(c0, Some(c1), Some(c2)) if c0.is_whitespace() && c1 == ':' && c2.is_whitespace() => {
Ok(s_next(s_next(s_next(s))))
}
(c0, Some(_), Some(_)) if c0.is_whitespace() => Ok(s_next(s)),
_ => Ok(s),

s = s_next(s);
if s.starts_with(':') {
s = s_next(s);
} else {
// consumed `" "`
return Ok(s);
}
if next_is_whitespace(s) {
s = s_next(s);
}

// consumed `" :"` or `" : "`
Ok(s)
}

/// Tries to parse `[-+]\d\d` continued by `\d\d`. Return an offset in seconds if possible.
Expand Down Expand Up @@ -505,37 +503,48 @@ fn test_trim1() {
}

#[test]
fn test_colon_or_space() {
assert_eq!(colon_or_space(""), Ok(""));
assert_eq!(colon_or_space(" "), Ok(""));
assert_eq!(colon_or_space("\n"), Ok(""));
assert_eq!(colon_or_space(" "), Ok(" "));
assert_eq!(colon_or_space(" "), Ok(" "));
assert_eq!(colon_or_space(" "), Ok(" "));
assert_eq!(colon_or_space("\t\t\t\t"), Ok("\t\t\t"));
assert_eq!(colon_or_space(":"), Ok(""));
assert_eq!(colon_or_space(" :"), Ok(""));
assert_eq!(colon_or_space(": "), Ok(""));
assert_eq!(colon_or_space(" : "), Ok(""));
assert_eq!(colon_or_space(" : "), Ok(" "));
assert_eq!(colon_or_space(" :"), Ok(" :"));
assert_eq!(colon_or_space(" : "), Ok(" : "));
assert_eq!(colon_or_space(" :: "), Ok(": "));
assert_eq!(colon_or_space(" : : "), Ok(": "));
assert_eq!(colon_or_space("๐Ÿ˜ธ"), Ok("๐Ÿ˜ธ"));
assert_eq!(colon_or_space("๐Ÿ˜ธ๐Ÿ˜ธ"), Ok("๐Ÿ˜ธ๐Ÿ˜ธ"));
assert_eq!(colon_or_space("๐Ÿ˜ธ:"), Ok("๐Ÿ˜ธ:"));
assert_eq!(colon_or_space("๐Ÿ˜ธ "), Ok("๐Ÿ˜ธ "));
assert_eq!(colon_or_space(" ๐Ÿ˜ธ"), Ok("๐Ÿ˜ธ"));
assert_eq!(colon_or_space(":๐Ÿ˜ธ"), Ok("๐Ÿ˜ธ"));
assert_eq!(colon_or_space(":๐Ÿ˜ธ "), Ok("๐Ÿ˜ธ "));
assert_eq!(colon_or_space(" :๐Ÿ˜ธ"), Ok("๐Ÿ˜ธ"));
assert_eq!(colon_or_space(" :๐Ÿ˜ธ "), Ok("๐Ÿ˜ธ "));
assert_eq!(colon_or_space(" :๐Ÿ˜ธ:"), Ok("๐Ÿ˜ธ:"));
assert_eq!(colon_or_space(": ๐Ÿ˜ธ"), Ok("๐Ÿ˜ธ"));
assert_eq!(colon_or_space(": ๐Ÿ˜ธ"), Ok(" ๐Ÿ˜ธ"));
assert_eq!(colon_or_space(": :๐Ÿ˜ธ"), Ok(":๐Ÿ˜ธ"));
assert_eq!(colon_or_space(" : ๐Ÿ˜ธ"), Ok("๐Ÿ˜ธ"));
assert_eq!(colon_or_space(" ::๐Ÿ˜ธ"), Ok(":๐Ÿ˜ธ"));
assert_eq!(colon_or_space(" :: ๐Ÿ˜ธ"), Ok(": ๐Ÿ˜ธ"));
fn test_next_is_whitespace() {
assert!(!next_is_whitespace(""));
assert!(!next_is_whitespace("a"));
assert!(!next_is_whitespace("๐Ÿ˜ผ๐Ÿ˜ผ"));
assert!(next_is_whitespace(" "));
assert!(next_is_whitespace("\t\t"));
assert!(next_is_whitespace("\ta\t"));
assert!(next_is_whitespace("\t๐Ÿ˜ผ\t"));
}

#[test]
fn test_maybe_colon_or_space() {
assert_eq!(maybe_colon_or_space(""), Ok(""));
assert_eq!(maybe_colon_or_space(" "), Ok(""));
assert_eq!(maybe_colon_or_space("\n"), Ok(""));
assert_eq!(maybe_colon_or_space(" "), Ok(" "));
assert_eq!(maybe_colon_or_space(" "), Ok(" "));
assert_eq!(maybe_colon_or_space(" "), Ok(" "));
assert_eq!(maybe_colon_or_space("\t\t\t\t"), Ok("\t\t\t"));
assert_eq!(maybe_colon_or_space(":"), Ok(""));
assert_eq!(maybe_colon_or_space(" :"), Ok(""));
assert_eq!(maybe_colon_or_space(": "), Ok(""));
assert_eq!(maybe_colon_or_space(" : "), Ok(""));
assert_eq!(maybe_colon_or_space(" : "), Ok(" "));
assert_eq!(maybe_colon_or_space(" :"), Ok(" :"));
assert_eq!(maybe_colon_or_space(" : "), Ok(" : "));
assert_eq!(maybe_colon_or_space(" :: "), Ok(": "));
assert_eq!(maybe_colon_or_space(" : : "), Ok(": "));
assert_eq!(maybe_colon_or_space("๐Ÿ˜ธ"), Ok("๐Ÿ˜ธ"));
assert_eq!(maybe_colon_or_space("๐Ÿ˜ธ๐Ÿ˜ธ"), Ok("๐Ÿ˜ธ๐Ÿ˜ธ"));
assert_eq!(maybe_colon_or_space("๐Ÿ˜ธ:"), Ok("๐Ÿ˜ธ:"));
assert_eq!(maybe_colon_or_space("๐Ÿ˜ธ "), Ok("๐Ÿ˜ธ "));
assert_eq!(maybe_colon_or_space(" ๐Ÿ˜ธ"), Ok("๐Ÿ˜ธ"));
assert_eq!(maybe_colon_or_space(":๐Ÿ˜ธ"), Ok("๐Ÿ˜ธ"));
assert_eq!(maybe_colon_or_space(":๐Ÿ˜ธ "), Ok("๐Ÿ˜ธ "));
assert_eq!(maybe_colon_or_space(" :๐Ÿ˜ธ"), Ok("๐Ÿ˜ธ"));
assert_eq!(maybe_colon_or_space(" :๐Ÿ˜ธ "), Ok("๐Ÿ˜ธ "));
assert_eq!(maybe_colon_or_space(" :๐Ÿ˜ธ:"), Ok("๐Ÿ˜ธ:"));
assert_eq!(maybe_colon_or_space(": ๐Ÿ˜ธ"), Ok("๐Ÿ˜ธ"));
assert_eq!(maybe_colon_or_space(": ๐Ÿ˜ธ"), Ok(" ๐Ÿ˜ธ"));
assert_eq!(maybe_colon_or_space(": :๐Ÿ˜ธ"), Ok(":๐Ÿ˜ธ"));
assert_eq!(maybe_colon_or_space(" : ๐Ÿ˜ธ"), Ok("๐Ÿ˜ธ"));
assert_eq!(maybe_colon_or_space(" ::๐Ÿ˜ธ"), Ok(":๐Ÿ˜ธ"));
assert_eq!(maybe_colon_or_space(" :: ๐Ÿ˜ธ"), Ok(": ๐Ÿ˜ธ"));
}

0 comments on commit 76cc9cb

Please sign in to comment.