#[cfg(not(feature = "std"))]
use alloc::{vec, vec::Vec};
#[cfg(feature = "std")]
use std::vec::Vec;
pub type FlagId = u16;
#[derive(Clone, Debug, Default, PartialEq, Eq)]
pub struct ParseContext {
words: Vec<u64>,
error_node_kind: Option<crate::types::SyntaxKind>,
}
impl ParseContext {
#[must_use]
pub const fn new() -> Self {
Self {
words: Vec::new(),
error_node_kind: None,
}
}
#[must_use]
pub fn with_capacity_for(max_flag_id: FlagId) -> Self {
let n = word_index(max_flag_id) + 1;
Self {
words: vec![0u64; n],
error_node_kind: None,
}
}
#[must_use]
pub fn with_set(mut self, id: FlagId) -> Self {
self.set(id);
self
}
#[must_use]
pub fn with_clear(mut self, id: FlagId) -> Self {
self.clear(id);
self
}
#[inline]
pub fn set(&mut self, id: FlagId) {
let w = word_index(id);
if w >= self.words.len() {
self.words.resize(w + 1, 0);
}
self.words[w] |= 1u64 << bit_index(id);
}
#[inline]
pub fn clear(&mut self, id: FlagId) {
let w = word_index(id);
if w < self.words.len() {
self.words[w] &= !(1u64 << bit_index(id));
}
}
#[must_use]
#[inline]
pub fn has(&self, id: FlagId) -> bool {
let w = word_index(id);
if w < self.words.len() {
(self.words[w] >> bit_index(id)) & 1 != 0
} else {
false
}
}
#[must_use]
#[inline]
pub fn num_words(&self) -> usize {
self.words.len()
}
#[must_use]
#[inline]
pub fn words(&self) -> &[u64] {
&self.words
}
#[must_use]
pub const fn with_error_node_kind(mut self, kind: crate::types::SyntaxKind) -> Self {
self.error_node_kind = Some(kind);
self
}
#[must_use]
#[inline]
pub const fn error_node_kind(&self) -> Option<crate::types::SyntaxKind> {
self.error_node_kind
}
}
#[inline]
pub(crate) const fn word_index(id: FlagId) -> usize {
(id >> 6) as usize
}
#[inline]
pub(crate) const fn bit_index(id: FlagId) -> u32 {
(id & 63) as u32
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct FlagMaskWord {
pub word: u32,
pub set_bits: u64,
pub clear_bits: u64,
}
#[derive(Clone, Debug)]
pub struct FlagMask<'a> {
pub entries: &'a [FlagMaskWord],
}
impl FlagMask<'_> {
#[inline]
pub fn apply(&self, flags: &mut Vec<u64>) {
for e in self.entries {
let w = e.word as usize;
if w >= flags.len() {
flags.resize(w + 1, 0);
}
flags[w] = (flags[w] | e.set_bits) & !e.clear_bits;
}
}
}