rust_args_parser/
util.rs

1/// Compute visible length (strip minimal ANSI we add) so alignment stays correct.
2#[must_use]
3pub fn strip_ansi_len(s: &str) -> usize {
4    let mut n = 0usize;
5    let mut skip = false;
6    let bytes = s.as_bytes();
7    let mut i = 0;
8    while i < bytes.len() {
9        if bytes[i] == 0x1B {
10            skip = true;
11            i += 1;
12            continue;
13        }
14        if skip {
15            if bytes[i] == b'm' {
16                skip = false;
17            }
18            i += 1;
19            continue;
20        }
21        n += 1;
22        i += 1;
23    }
24    n
25}
26
27/// Heuristic: token that looks like a number (accepts leading '-', digits, optional dot/exponent).
28#[must_use]
29pub fn looks_like_number_token(s: &str) -> bool {
30    let bytes = s.as_bytes();
31    if bytes.is_empty() {
32        return false;
33    }
34    let mut i = 0;
35    if bytes[0] == b'-' || bytes[0] == b'+' {
36        i += 1;
37        if i >= bytes.len() {
38            return false;
39        }
40    }
41    let mut has_digit = false;
42    let mut dot = false;
43    let mut exp = false;
44    while i < bytes.len() {
45        match bytes[i] {
46            b'0'..=b'9' => {
47                has_digit = true;
48            }
49            b'.' if !dot && !exp => {
50                dot = true;
51            }
52            b'e' | b'E' if has_digit && !exp => {
53                exp = true;
54                has_digit = false;
55                if i + 1 < bytes.len() && (bytes[i + 1] == b'+' || bytes[i + 1] == b'-') {
56                    i += 1;
57                }
58            }
59            _ => return false,
60        }
61        i += 1;
62    }
63    has_digit
64}