//! 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)); }