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