| pub fn skip(mut s: &str) -> &str { |
| 'skip: while !s.is_empty() { |
| let byte = s.as_bytes()[0]; |
| if byte == b'/' { |
| if s.starts_with("//") |
| && (!s.starts_with("///") || s.starts_with("////")) |
| && !s.starts_with("//!") |
| { |
| if let Some(i) = s.find('\n') { |
| s = &s[i + 1..]; |
| continue; |
| } else { |
| return ""; |
| } |
| } else if s.starts_with("/**/") { |
| s = &s[4..]; |
| continue; |
| } else if s.starts_with("/*") |
| && (!s.starts_with("/**") || s.starts_with("/***")) |
| && !s.starts_with("/*!") |
| { |
| let mut depth = 0; |
| let bytes = s.as_bytes(); |
| let mut i = 0; |
| let upper = bytes.len() - 1; |
| while i < upper { |
| if bytes[i] == b'/' && bytes[i + 1] == b'*' { |
| depth += 1; |
| i += 1; // eat '*' |
| } else if bytes[i] == b'*' && bytes[i + 1] == b'/' { |
| depth -= 1; |
| if depth == 0 { |
| s = &s[i + 2..]; |
| continue 'skip; |
| } |
| i += 1; // eat '/' |
| } |
| i += 1; |
| } |
| return s; |
| } |
| } |
| match byte { |
| b' ' | 0x09..=0x0d => { |
| s = &s[1..]; |
| continue; |
| } |
| b if b <= 0x7f => {} |
| _ => { |
| let ch = s.chars().next().unwrap(); |
| if is_whitespace(ch) { |
| s = &s[ch.len_utf8()..]; |
| continue; |
| } |
| } |
| } |
| return s; |
| } |
| s |
| } |
| |
| fn is_whitespace(ch: char) -> bool { |
| // Rust treats left-to-right mark and right-to-left mark as whitespace |
| ch.is_whitespace() || ch == '\u{200e}' || ch == '\u{200f}' |
| } |