diff --git a/crates/doc/src/range.rs b/crates/doc/src/range.rs index 80b4d6d33..eab847204 100644 --- a/crates/doc/src/range.rs +++ b/crates/doc/src/range.rs @@ -9,7 +9,12 @@ pub fn parse_range(s: &str, count: usize) -> Result, String> { if t.is_empty() { return Ok(open); } - t.parse().ok().filter(|n| (1..=count).contains(n)).ok_or_else(|| format!("range `{s}`: `{t}` is not a number from 1 to {count}")) + t.bytes() + .all(|b| b.is_ascii_digit()) + .then(|| t.parse().ok()) + .flatten() + .filter(|n| (1..=count).contains(n)) + .ok_or_else(|| format!("range `{s}`: `{t}` is not a number from 1 to {count}")) }; let mut out = vec![]; for part in s.split(',').map(str::trim).filter(|p| !p.is_empty()) { @@ -35,3 +40,16 @@ pub fn parse_range(s: &str, count: usize) -> Result, String> { } Ok(out) } + +#[cfg(test)] +mod tests { + use super::parse_range; + + #[test] + fn sign_is_not_part_of_a_page_number() { + assert!(parse_range("+2", 5).is_err()); + assert!(parse_range("1-+3", 5).is_err()); + assert!(parse_range("-+2", 5).is_err()); + assert_eq!(parse_range("1-3, 5", 5), Ok(vec![0, 1, 2, 4])); + } +}