pub mod crit_graph; pub mod crit_leaf; pub mod crit_matchers; pub mod crit_per_target_data; use { crate::{ crit_graph::{CritMgr, CritMiddle, CritRoot, CritRootCriterion, CritRootFixed}, crit_leaf::CritLeafMatcher, crit_matchers::{critm_any_or_all::CritMatchAnyOrAll, critm_exactly::CritMatchExactly}, }, jay_utils::{copyhashmap::CopyHashMap, numcell::NumCell}, linearize::StaticMap, regex::Regex, std::rc::{Rc, Weak}, }; pub use { crit_graph::{CritTarget, CritUpstreamNode}, crit_per_target_data::CritDestroyListener, }; #[derive(Debug)] pub struct CritMatcherIds { next: NumCell, } impl Default for CritMatcherIds { fn default() -> Self { Self { next: NumCell::new(1), } } } impl CritMatcherIds { pub fn next(&self) -> CritMatcherId { CritMatcherId(self.next.fetch_add(1)) } } #[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, Ord, PartialOrd)] pub struct CritMatcherId(u64); impl CritMatcherId { #[allow(clippy::allow_attributes, dead_code)] pub fn raw(&self) -> u64 { self.0 } #[allow(clippy::allow_attributes, dead_code)] pub fn from_raw(id: u64) -> Self { Self(id) } } impl std::fmt::Display for CritMatcherId { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { std::fmt::Display::fmt(&self.0, f) } } pub type RootMatcherMap = CopyHashMap>>; pub type FixedRootMatcher = StaticMap>>>; #[derive(Clone)] pub enum CritLiteralOrRegex { Literal(String), Regex(Regex), } impl CritLiteralOrRegex { fn matches(&self, string: &str) -> bool { match self { CritLiteralOrRegex::Literal(p) => string == p, CritLiteralOrRegex::Regex(r) => r.is_match(string), } } } pub trait CritMgrExt: CritMgr { fn list( &self, upstream: &[Rc>], all: bool, ) -> Rc> { if upstream.is_empty() { return self.match_constant()[all].clone(); } CritMiddle::new(self, upstream, CritMatchAnyOrAll::new(upstream, all)) } fn exactly( &self, upstream: &[Rc>], num: usize, ) -> Rc> { if num > upstream.len() { return self.match_constant()[false].clone(); } if num == 0 { let upstream: Vec<_> = upstream.iter().map(|u| u.not(self)).collect(); return self.list(&upstream, true); } CritMiddle::new(self, upstream, CritMatchExactly::new(upstream, num)) } fn leaf( &self, upstream: &Rc>, on_match: impl Fn(::LeafData) -> Box + 'static, ) -> Rc> { CritLeafMatcher::new(self, upstream, on_match) } fn not( &self, upstream: &Rc>, ) -> Rc> { upstream.not(self) } fn root(&self, criterion: T) -> Rc> where T: CritRootCriterion, { CritRoot::new(self.roots(), self.id(), criterion) } } impl CritMgrExt for T where T: CritMgr {}