use ktrs_syntax::SyntaxKind;
use crate::rule::TokenSet;
const UNBUILT: (u32, u32) = (u32::MAX, 0);
pub(crate) struct RuleDispatch {
spans: Vec<(u32, u32)>,
indices: Vec<u16>,
pub(crate) after: Vec<u16>,
}
impl RuleDispatch {
pub(crate) fn new(visits_after: impl ExactSizeIterator<Item = bool>) -> RuleDispatch {
let rule_count = visits_after.len();
RuleDispatch {
spans: vec![UNBUILT; SyntaxKind::DUMMY_HOLDER as usize + 1],
indices: Vec::with_capacity(rule_count * 32),
after: visits_after.enumerate().filter(|&(_, after)| after).map(|(i, _)| i as u16).collect(),
}
}
pub(crate) fn rules_for(
&mut self,
kind: SyntaxKind,
visited_types: impl Iterator<Item = Option<TokenSet>>,
all: bool,
) -> (usize, usize) {
let span = &mut self.spans[kind as usize];
if *span == UNBUILT {
let start = self.indices.len();
self.indices.extend(
visited_types
.enumerate()
.filter(|(_, types)| all || types.is_none_or(|t| t.contains(kind)))
.map(|(i, _)| i as u16),
);
*span = (start as u32, (self.indices.len() - start) as u32);
}
(span.0 as usize, span.1 as usize)
}
pub(crate) fn rule_at(&self, position: usize) -> usize {
usize::from(self.indices[position])
}
}