| //! A bit-set of `SyntaxKind`s. | |
| use crate::SyntaxKind; | |
| /// A bit-set of `SyntaxKind`s | |
| #[derive(Clone, Copy)] | |
| pub(crate) struct TokenSet([u64; 3]); | |
| /// `TokenSet`s should only include token `SyntaxKind`s, so the discriminant of any passed/included | |
| /// `SyntaxKind` must *not* be greater than that of the last token `SyntaxKind`. | |
| /// See #17037. | |
| const LAST_TOKEN_KIND_DISCRIMINANT: usize = SyntaxKind::SHEBANG as usize; | |
| impl TokenSet { | |
| pub(crate) const EMPTY: TokenSet = TokenSet([0; 3]); | |
| pub(crate) const fn new(kinds: &[SyntaxKind]) -> TokenSet { | |
| let mut res = [0; 3]; | |
| let mut i = 0; | |
| while i < kinds.len() { | |
| let discriminant = kinds[i] as usize; | |
| debug_assert!( | |
| discriminant <= LAST_TOKEN_KIND_DISCRIMINANT, | |
| "Expected a token `SyntaxKind`" | |
| ); | |
| let idx = discriminant / 64; | |
| res[idx] |= 1 << (discriminant % 64); | |
| i += 1; | |
| } | |
| TokenSet(res) | |
| } | |
| pub(crate) const fn union(self, other: TokenSet) -> TokenSet { | |
| TokenSet([self.0[0] | other.0[0], self.0[1] | other.0[1], self.0[2] | other.0[2]]) | |
| } | |
| pub(crate) const fn contains(&self, kind: SyntaxKind) -> bool { | |
| let discriminant = kind as usize; | |
| debug_assert!( | |
| discriminant <= LAST_TOKEN_KIND_DISCRIMINANT, | |
| "Expected a token `SyntaxKind`" | |
| ); | |
| let idx = discriminant / 64; | |
| let mask = 1 << (discriminant % 64); | |
| self.0[idx] & mask != 0 | |
| } | |
| } | |
| #[test] | |
| fn token_set_works_for_tokens() { | |
| use crate::SyntaxKind::*; | |
| let ts = TokenSet::new(&[EOF, SHEBANG]); | |
| assert!(ts.contains(EOF)); | |
| assert!(ts.contains(SHEBANG)); | |
| assert!(!ts.contains(PLUS)); | |
| } |