1fad3a1d3Sopenharmony_cipub(crate) fn skip(mut s: &str) -> &str {
2fad3a1d3Sopenharmony_ci    'skip: while !s.is_empty() {
3fad3a1d3Sopenharmony_ci        let byte = s.as_bytes()[0];
4fad3a1d3Sopenharmony_ci        if byte == b'/' {
5fad3a1d3Sopenharmony_ci            if s.starts_with("//")
6fad3a1d3Sopenharmony_ci                && (!s.starts_with("///") || s.starts_with("////"))
7fad3a1d3Sopenharmony_ci                && !s.starts_with("//!")
8fad3a1d3Sopenharmony_ci            {
9fad3a1d3Sopenharmony_ci                if let Some(i) = s.find('\n') {
10fad3a1d3Sopenharmony_ci                    s = &s[i + 1..];
11fad3a1d3Sopenharmony_ci                    continue;
12fad3a1d3Sopenharmony_ci                } else {
13fad3a1d3Sopenharmony_ci                    return "";
14fad3a1d3Sopenharmony_ci                }
15fad3a1d3Sopenharmony_ci            } else if s.starts_with("/**/") {
16fad3a1d3Sopenharmony_ci                s = &s[4..];
17fad3a1d3Sopenharmony_ci                continue;
18fad3a1d3Sopenharmony_ci            } else if s.starts_with("/*")
19fad3a1d3Sopenharmony_ci                && (!s.starts_with("/**") || s.starts_with("/***"))
20fad3a1d3Sopenharmony_ci                && !s.starts_with("/*!")
21fad3a1d3Sopenharmony_ci            {
22fad3a1d3Sopenharmony_ci                let mut depth = 0;
23fad3a1d3Sopenharmony_ci                let bytes = s.as_bytes();
24fad3a1d3Sopenharmony_ci                let mut i = 0;
25fad3a1d3Sopenharmony_ci                let upper = bytes.len() - 1;
26fad3a1d3Sopenharmony_ci                while i < upper {
27fad3a1d3Sopenharmony_ci                    if bytes[i] == b'/' && bytes[i + 1] == b'*' {
28fad3a1d3Sopenharmony_ci                        depth += 1;
29fad3a1d3Sopenharmony_ci                        i += 1; // eat '*'
30fad3a1d3Sopenharmony_ci                    } else if bytes[i] == b'*' && bytes[i + 1] == b'/' {
31fad3a1d3Sopenharmony_ci                        depth -= 1;
32fad3a1d3Sopenharmony_ci                        if depth == 0 {
33fad3a1d3Sopenharmony_ci                            s = &s[i + 2..];
34fad3a1d3Sopenharmony_ci                            continue 'skip;
35fad3a1d3Sopenharmony_ci                        }
36fad3a1d3Sopenharmony_ci                        i += 1; // eat '/'
37fad3a1d3Sopenharmony_ci                    }
38fad3a1d3Sopenharmony_ci                    i += 1;
39fad3a1d3Sopenharmony_ci                }
40fad3a1d3Sopenharmony_ci                return s;
41fad3a1d3Sopenharmony_ci            }
42fad3a1d3Sopenharmony_ci        }
43fad3a1d3Sopenharmony_ci        match byte {
44fad3a1d3Sopenharmony_ci            b' ' | 0x09..=0x0d => {
45fad3a1d3Sopenharmony_ci                s = &s[1..];
46fad3a1d3Sopenharmony_ci                continue;
47fad3a1d3Sopenharmony_ci            }
48fad3a1d3Sopenharmony_ci            b if b <= 0x7f => {}
49fad3a1d3Sopenharmony_ci            _ => {
50fad3a1d3Sopenharmony_ci                let ch = s.chars().next().unwrap();
51fad3a1d3Sopenharmony_ci                if is_whitespace(ch) {
52fad3a1d3Sopenharmony_ci                    s = &s[ch.len_utf8()..];
53fad3a1d3Sopenharmony_ci                    continue;
54fad3a1d3Sopenharmony_ci                }
55fad3a1d3Sopenharmony_ci            }
56fad3a1d3Sopenharmony_ci        }
57fad3a1d3Sopenharmony_ci        return s;
58fad3a1d3Sopenharmony_ci    }
59fad3a1d3Sopenharmony_ci    s
60fad3a1d3Sopenharmony_ci}
61fad3a1d3Sopenharmony_ci
62fad3a1d3Sopenharmony_cifn is_whitespace(ch: char) -> bool {
63fad3a1d3Sopenharmony_ci    // Rust treats left-to-right mark and right-to-left mark as whitespace
64fad3a1d3Sopenharmony_ci    ch.is_whitespace() || ch == '\u{200e}' || ch == '\u{200f}'
65fad3a1d3Sopenharmony_ci}
66