1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
/// Implemented for `u8` and `char` - operates on bytes for performance.
pub trait CharExt: Copy {
fn to_char(self) -> Option<char>;
/// Test whether a given byte/character starts an identifier.
///
/// https://tc39.github.io/ecma262/#prod-IdentifierStart
#[inline]
fn is_ident_start(self) -> bool {
let c = match self.to_char() {
Some(c) => c,
None => return false,
};
swc_ecma_ast::Ident::is_valid_start(c)
}
/// Test whether a given byte/character is part of an identifier.
#[inline]
fn is_ident_part(self) -> bool {
let c = match self.to_char() {
Some(c) => c,
None => return false,
};
swc_ecma_ast::Ident::is_valid_continue(c)
}
/// See https://tc39.github.io/ecma262/#sec-line-terminators
#[inline]
fn is_line_terminator(self) -> bool {
let c = match self.to_char() {
Some(c) => c,
None => return false,
};
matches!(c, '\r' | '\n' | '\u{2028}' | '\u{2029}')
}
}
impl CharExt for u8 {
#[inline(always)]
fn to_char(self) -> Option<char> {
// For ASCII bytes, this is a fast path
if self <= 0x7f {
Some(self as char)
} else {
// For non-ASCII bytes, we can't convert a single byte to a char
// The caller should use cur_as_char() on the Input trait instead
None
}
}
}
impl CharExt for char {
#[inline(always)]
fn to_char(self) -> Option<char> {
Some(self)
}
}