1use oxilean_kernel::{Expr, Literal, Name};
6
7#[allow(dead_code)]
9#[derive(Debug, Clone)]
10pub enum MatchBasicConfigValue {
11 Bool(bool),
12 Int(i64),
13 Float(f64),
14 Str(String),
15 List(Vec<String>),
16}
17#[allow(dead_code)]
18impl MatchBasicConfigValue {
19 pub fn as_bool(&self) -> Option<bool> {
20 match self {
21 MatchBasicConfigValue::Bool(b) => Some(*b),
22 _ => None,
23 }
24 }
25 pub fn as_int(&self) -> Option<i64> {
26 match self {
27 MatchBasicConfigValue::Int(i) => Some(*i),
28 _ => None,
29 }
30 }
31 pub fn as_float(&self) -> Option<f64> {
32 match self {
33 MatchBasicConfigValue::Float(f) => Some(*f),
34 _ => None,
35 }
36 }
37 pub fn as_str(&self) -> Option<&str> {
38 match self {
39 MatchBasicConfigValue::Str(s) => Some(s),
40 _ => None,
41 }
42 }
43 pub fn as_list(&self) -> Option<&[String]> {
44 match self {
45 MatchBasicConfigValue::List(v) => Some(v),
46 _ => None,
47 }
48 }
49 pub fn type_name(&self) -> &'static str {
50 match self {
51 MatchBasicConfigValue::Bool(_) => "bool",
52 MatchBasicConfigValue::Int(_) => "int",
53 MatchBasicConfigValue::Float(_) => "float",
54 MatchBasicConfigValue::Str(_) => "str",
55 MatchBasicConfigValue::List(_) => "list",
56 }
57 }
58}
59#[allow(dead_code)]
61#[derive(Debug, Clone, Default)]
62pub struct MatchBasicUtil12 {
63 pub id: usize,
64 pub name: String,
65 pub value: i64,
66 pub enabled: bool,
67 pub tags: Vec<String>,
68}
69#[allow(dead_code)]
70impl MatchBasicUtil12 {
71 pub fn new(id: usize, name: &str, value: i64) -> Self {
72 MatchBasicUtil12 {
73 id,
74 name: name.to_string(),
75 value,
76 enabled: true,
77 tags: Vec::new(),
78 }
79 }
80 pub fn with_tag(mut self, tag: &str) -> Self {
81 self.tags.push(tag.to_string());
82 self
83 }
84 pub fn disable(mut self) -> Self {
85 self.enabled = false;
86 self
87 }
88 pub fn is_active(&self) -> bool {
89 self.enabled
90 }
91 pub fn score(&self) -> i64 {
92 if self.enabled {
93 self.value
94 } else {
95 0
96 }
97 }
98 pub fn tag_count(&self) -> usize {
99 self.tags.len()
100 }
101 pub fn has_tag(&self, tag: &str) -> bool {
102 self.tags.iter().any(|t| t == tag)
103 }
104}
105#[allow(dead_code)]
106pub struct MatchBasicExtPass4100 {
107 pub name: String,
108 pub total_runs: usize,
109 pub successes: usize,
110 pub errors: usize,
111 pub enabled: bool,
112 pub results: Vec<MatchBasicExtResult4100>,
113}
114impl MatchBasicExtPass4100 {
115 #[allow(dead_code)]
116 pub fn new(name: &str) -> Self {
117 Self {
118 name: name.to_string(),
119 total_runs: 0,
120 successes: 0,
121 errors: 0,
122 enabled: true,
123 results: Vec::new(),
124 }
125 }
126 #[allow(dead_code)]
127 pub fn run(&mut self, input: &str) -> MatchBasicExtResult4100 {
128 if !self.enabled {
129 return MatchBasicExtResult4100::Skipped;
130 }
131 self.total_runs += 1;
132 let result = if input.is_empty() {
133 self.errors += 1;
134 MatchBasicExtResult4100::Err(format!("empty input in pass '{}'", self.name))
135 } else {
136 self.successes += 1;
137 MatchBasicExtResult4100::Ok(format!(
138 "processed {} chars in pass '{}'",
139 input.len(),
140 self.name
141 ))
142 };
143 self.results.push(result.clone());
144 result
145 }
146 #[allow(dead_code)]
147 pub fn success_count(&self) -> usize {
148 self.successes
149 }
150 #[allow(dead_code)]
151 pub fn error_count(&self) -> usize {
152 self.errors
153 }
154 #[allow(dead_code)]
155 pub fn success_rate(&self) -> f64 {
156 if self.total_runs == 0 {
157 0.0
158 } else {
159 self.successes as f64 / self.total_runs as f64
160 }
161 }
162 #[allow(dead_code)]
163 pub fn disable(&mut self) {
164 self.enabled = false;
165 }
166 #[allow(dead_code)]
167 pub fn enable(&mut self) {
168 self.enabled = true;
169 }
170 #[allow(dead_code)]
171 pub fn clear_results(&mut self) {
172 self.results.clear();
173 }
174}
175#[allow(dead_code)]
176#[derive(Debug, Clone)]
177pub enum MatchBasicExtConfigVal4100 {
178 Bool(bool),
179 Int(i64),
180 Float(f64),
181 Str(String),
182 List(Vec<String>),
183}
184impl MatchBasicExtConfigVal4100 {
185 #[allow(dead_code)]
186 pub fn as_bool(&self) -> Option<bool> {
187 if let MatchBasicExtConfigVal4100::Bool(b) = self {
188 Some(*b)
189 } else {
190 None
191 }
192 }
193 #[allow(dead_code)]
194 pub fn as_int(&self) -> Option<i64> {
195 if let MatchBasicExtConfigVal4100::Int(i) = self {
196 Some(*i)
197 } else {
198 None
199 }
200 }
201 #[allow(dead_code)]
202 pub fn as_float(&self) -> Option<f64> {
203 if let MatchBasicExtConfigVal4100::Float(f) = self {
204 Some(*f)
205 } else {
206 None
207 }
208 }
209 #[allow(dead_code)]
210 pub fn as_str(&self) -> Option<&str> {
211 if let MatchBasicExtConfigVal4100::Str(s) = self {
212 Some(s)
213 } else {
214 None
215 }
216 }
217 #[allow(dead_code)]
218 pub fn as_list(&self) -> Option<&[String]> {
219 if let MatchBasicExtConfigVal4100::List(l) = self {
220 Some(l)
221 } else {
222 None
223 }
224 }
225 #[allow(dead_code)]
226 pub fn type_name(&self) -> &'static str {
227 match self {
228 MatchBasicExtConfigVal4100::Bool(_) => "bool",
229 MatchBasicExtConfigVal4100::Int(_) => "int",
230 MatchBasicExtConfigVal4100::Float(_) => "float",
231 MatchBasicExtConfigVal4100::Str(_) => "str",
232 MatchBasicExtConfigVal4100::List(_) => "list",
233 }
234 }
235}
236#[allow(dead_code)]
238pub struct MatchBasicDiagnostics {
239 pub errors: Vec<String>,
240 pub warnings: Vec<String>,
241 pub notes: Vec<String>,
242 pub max_errors: usize,
243}
244#[allow(dead_code)]
245impl MatchBasicDiagnostics {
246 pub fn new(max_errors: usize) -> Self {
247 MatchBasicDiagnostics {
248 errors: Vec::new(),
249 warnings: Vec::new(),
250 notes: Vec::new(),
251 max_errors,
252 }
253 }
254 pub fn error(&mut self, msg: &str) {
255 if self.errors.len() < self.max_errors {
256 self.errors.push(msg.to_string());
257 }
258 }
259 pub fn warning(&mut self, msg: &str) {
260 self.warnings.push(msg.to_string());
261 }
262 pub fn note(&mut self, msg: &str) {
263 self.notes.push(msg.to_string());
264 }
265 pub fn has_errors(&self) -> bool {
266 !self.errors.is_empty()
267 }
268 pub fn num_errors(&self) -> usize {
269 self.errors.len()
270 }
271 pub fn num_warnings(&self) -> usize {
272 self.warnings.len()
273 }
274 pub fn is_clean(&self) -> bool {
275 self.errors.is_empty() && self.warnings.is_empty()
276 }
277 pub fn at_error_limit(&self) -> bool {
278 self.errors.len() >= self.max_errors
279 }
280 pub fn clear(&mut self) {
281 self.errors.clear();
282 self.warnings.clear();
283 self.notes.clear();
284 }
285 pub fn summary(&self) -> String {
286 format!(
287 "{} error(s), {} warning(s)",
288 self.errors.len(),
289 self.warnings.len()
290 )
291 }
292}
293#[allow(dead_code)]
295pub struct MatchBasicConfig {
296 pub values: std::collections::HashMap<String, MatchBasicConfigValue>,
297 pub read_only: bool,
298}
299#[allow(dead_code)]
300impl MatchBasicConfig {
301 pub fn new() -> Self {
302 MatchBasicConfig {
303 values: std::collections::HashMap::new(),
304 read_only: false,
305 }
306 }
307 pub fn set(&mut self, key: &str, value: MatchBasicConfigValue) -> bool {
308 if self.read_only {
309 return false;
310 }
311 self.values.insert(key.to_string(), value);
312 true
313 }
314 pub fn get(&self, key: &str) -> Option<&MatchBasicConfigValue> {
315 self.values.get(key)
316 }
317 pub fn get_bool(&self, key: &str) -> Option<bool> {
318 self.get(key)?.as_bool()
319 }
320 pub fn get_int(&self, key: &str) -> Option<i64> {
321 self.get(key)?.as_int()
322 }
323 pub fn get_str(&self, key: &str) -> Option<&str> {
324 self.get(key)?.as_str()
325 }
326 pub fn set_bool(&mut self, key: &str, v: bool) -> bool {
327 self.set(key, MatchBasicConfigValue::Bool(v))
328 }
329 pub fn set_int(&mut self, key: &str, v: i64) -> bool {
330 self.set(key, MatchBasicConfigValue::Int(v))
331 }
332 pub fn set_str(&mut self, key: &str, v: &str) -> bool {
333 self.set(key, MatchBasicConfigValue::Str(v.to_string()))
334 }
335 pub fn lock(&mut self) {
336 self.read_only = true;
337 }
338 pub fn unlock(&mut self) {
339 self.read_only = false;
340 }
341 pub fn size(&self) -> usize {
342 self.values.len()
343 }
344 pub fn has(&self, key: &str) -> bool {
345 self.values.contains_key(key)
346 }
347 pub fn remove(&mut self, key: &str) -> bool {
348 self.values.remove(key).is_some()
349 }
350}
351#[allow(dead_code)]
353#[derive(Debug, Clone, Default)]
354pub struct MatchBasicUtil3 {
355 pub id: usize,
356 pub name: String,
357 pub value: i64,
358 pub enabled: bool,
359 pub tags: Vec<String>,
360}
361#[allow(dead_code)]
362impl MatchBasicUtil3 {
363 pub fn new(id: usize, name: &str, value: i64) -> Self {
364 MatchBasicUtil3 {
365 id,
366 name: name.to_string(),
367 value,
368 enabled: true,
369 tags: Vec::new(),
370 }
371 }
372 pub fn with_tag(mut self, tag: &str) -> Self {
373 self.tags.push(tag.to_string());
374 self
375 }
376 pub fn disable(mut self) -> Self {
377 self.enabled = false;
378 self
379 }
380 pub fn is_active(&self) -> bool {
381 self.enabled
382 }
383 pub fn score(&self) -> i64 {
384 if self.enabled {
385 self.value
386 } else {
387 0
388 }
389 }
390 pub fn tag_count(&self) -> usize {
391 self.tags.len()
392 }
393 pub fn has_tag(&self, tag: &str) -> bool {
394 self.tags.iter().any(|t| t == tag)
395 }
396}
397#[derive(Clone, Debug, PartialEq)]
399pub enum MetaPattern {
400 Wildcard,
402 Var(Name),
404 Constructor(Name, Vec<MetaPattern>),
406 Literal(Literal),
408 As(Box<MetaPattern>, Name),
410 Or(Box<MetaPattern>, Box<MetaPattern>),
412 Inaccessible(Expr),
414}
415impl MetaPattern {
416 pub fn is_irrefutable(&self) -> bool {
418 matches!(self, MetaPattern::Wildcard | MetaPattern::Var(_))
419 }
420 pub fn is_constructor(&self) -> bool {
422 matches!(self, MetaPattern::Constructor(_, _))
423 }
424 pub fn is_literal(&self) -> bool {
426 matches!(self, MetaPattern::Literal(_))
427 }
428 pub fn ctor_name(&self) -> Option<&Name> {
430 match self {
431 MetaPattern::Constructor(name, _) => Some(name),
432 _ => None,
433 }
434 }
435 pub fn subpatterns(&self) -> &[MetaPattern] {
437 match self {
438 MetaPattern::Constructor(_, pats) => pats,
439 _ => &[],
440 }
441 }
442 pub fn num_bindings(&self) -> usize {
444 match self {
445 MetaPattern::Wildcard | MetaPattern::Inaccessible(_) => 0,
446 MetaPattern::Var(_) => 1,
447 MetaPattern::Literal(_) => 0,
448 MetaPattern::Constructor(_, pats) => pats.iter().map(|p| p.num_bindings()).sum(),
449 MetaPattern::As(inner, _) => 1 + inner.num_bindings(),
450 MetaPattern::Or(left, _right) => left.num_bindings(),
451 }
452 }
453 pub fn bound_vars(&self) -> Vec<Name> {
455 let mut vars = Vec::new();
456 self.collect_vars(&mut vars);
457 vars
458 }
459 fn collect_vars(&self, vars: &mut Vec<Name>) {
460 match self {
461 MetaPattern::Var(name) => vars.push(name.clone()),
462 MetaPattern::Constructor(_, pats) => {
463 for p in pats {
464 p.collect_vars(vars);
465 }
466 }
467 MetaPattern::As(inner, name) => {
468 vars.push(name.clone());
469 inner.collect_vars(vars);
470 }
471 MetaPattern::Or(left, _) => {
472 left.collect_vars(vars);
473 }
474 _ => {}
475 }
476 }
477 pub fn depth(&self) -> usize {
479 match self {
480 MetaPattern::Constructor(_, pats) => {
481 1 + pats.iter().map(|p| p.depth()).max().unwrap_or(0)
482 }
483 MetaPattern::As(inner, _) => 1 + inner.depth(),
484 MetaPattern::Or(left, right) => 1 + left.depth().max(right.depth()),
485 _ => 0,
486 }
487 }
488}
489#[derive(Clone, Debug, Default)]
491pub struct PatternMatrix {
492 pub rows: Vec<PatternRow>,
494 pub num_discriminants: usize,
496}
497impl PatternMatrix {
498 pub fn new(num_discriminants: usize) -> Self {
500 Self {
501 rows: Vec::new(),
502 num_discriminants,
503 }
504 }
505 pub fn add_row(&mut self, row: PatternRow) {
507 self.rows.push(row);
508 }
509 pub fn num_rows(&self) -> usize {
511 self.rows.len()
512 }
513 pub fn is_empty(&self) -> bool {
515 self.rows.is_empty()
516 }
517 pub fn first_row_is_catchall(&self) -> bool {
519 self.rows
520 .first()
521 .map(|r| r.is_all_irrefutable())
522 .unwrap_or(false)
523 }
524 pub fn specialize(&self, col: usize, ctor_name: &Name, arity: usize) -> PatternMatrix {
529 let mut result = PatternMatrix::new(self.num_discriminants - 1 + arity);
530 for row in &self.rows {
531 match &row.patterns[col] {
532 MetaPattern::Constructor(name, sub) if name == ctor_name => {
533 let mut new_pats = row.patterns.clone();
534 new_pats.remove(col);
535 for (i, s) in sub.iter().enumerate().rev() {
536 new_pats.insert(col + arity - 1 - i, s.clone());
537 }
538 result.add_row(PatternRow {
539 patterns: new_pats,
540 ..row.clone()
541 });
542 }
543 MetaPattern::Wildcard | MetaPattern::Var(_) => {
544 let mut new_pats = row.patterns.clone();
545 new_pats.remove(col);
546 for _ in 0..arity {
547 new_pats.insert(col, MetaPattern::Wildcard);
548 }
549 result.add_row(PatternRow {
550 patterns: new_pats,
551 ..row.clone()
552 });
553 }
554 _ => {}
555 }
556 }
557 result
558 }
559 pub fn default_matrix(&self, col: usize) -> PatternMatrix {
561 let mut result = PatternMatrix::new(self.num_discriminants - 1);
562 for row in &self.rows {
563 if row.patterns[col].is_irrefutable() {
564 let mut new_pats = row.patterns.clone();
565 new_pats.remove(col);
566 result.add_row(PatternRow {
567 patterns: new_pats,
568 ..row.clone()
569 });
570 }
571 }
572 result
573 }
574}
575#[allow(dead_code)]
577pub struct MatchBasicPipeline {
578 pub passes: Vec<MatchBasicAnalysisPass>,
579 pub name: String,
580 pub total_inputs_processed: usize,
581}
582#[allow(dead_code)]
583impl MatchBasicPipeline {
584 pub fn new(name: &str) -> Self {
585 MatchBasicPipeline {
586 passes: Vec::new(),
587 name: name.to_string(),
588 total_inputs_processed: 0,
589 }
590 }
591 pub fn add_pass(&mut self, pass: MatchBasicAnalysisPass) {
592 self.passes.push(pass);
593 }
594 pub fn run_all(&mut self, input: &str) -> Vec<MatchBasicResult> {
595 self.total_inputs_processed += 1;
596 self.passes
597 .iter_mut()
598 .filter(|p| p.enabled)
599 .map(|p| p.run(input))
600 .collect()
601 }
602 pub fn num_passes(&self) -> usize {
603 self.passes.len()
604 }
605 pub fn num_enabled_passes(&self) -> usize {
606 self.passes.iter().filter(|p| p.enabled).count()
607 }
608 pub fn total_success_rate(&self) -> f64 {
609 if self.passes.is_empty() {
610 0.0
611 } else {
612 let total_rate: f64 = self.passes.iter().map(|p| p.success_rate()).sum();
613 total_rate / self.passes.len() as f64
614 }
615 }
616}
617#[derive(Debug, Clone, PartialEq)]
619pub enum MatchResult {
620 Success(Vec<(oxilean_kernel::Name, Expr)>),
622 Failure,
624 Undetermined,
626}
627impl MatchResult {
628 pub fn is_success(&self) -> bool {
630 matches!(self, MatchResult::Success(_))
631 }
632 pub fn is_failure(&self) -> bool {
634 matches!(self, MatchResult::Failure)
635 }
636 pub fn bindings(&self) -> &[(oxilean_kernel::Name, Expr)] {
638 match self {
639 MatchResult::Success(b) => b,
640 _ => &[],
641 }
642 }
643}
644#[allow(dead_code)]
645pub struct MatchBasicExtDiff4100 {
646 pub added: Vec<String>,
647 pub removed: Vec<String>,
648 pub unchanged: Vec<String>,
649}
650impl MatchBasicExtDiff4100 {
651 #[allow(dead_code)]
652 pub fn new() -> Self {
653 Self {
654 added: Vec::new(),
655 removed: Vec::new(),
656 unchanged: Vec::new(),
657 }
658 }
659 #[allow(dead_code)]
660 pub fn add(&mut self, s: &str) {
661 self.added.push(s.to_string());
662 }
663 #[allow(dead_code)]
664 pub fn remove(&mut self, s: &str) {
665 self.removed.push(s.to_string());
666 }
667 #[allow(dead_code)]
668 pub fn keep(&mut self, s: &str) {
669 self.unchanged.push(s.to_string());
670 }
671 #[allow(dead_code)]
672 pub fn is_empty(&self) -> bool {
673 self.added.is_empty() && self.removed.is_empty()
674 }
675 #[allow(dead_code)]
676 pub fn total_changes(&self) -> usize {
677 self.added.len() + self.removed.len()
678 }
679 #[allow(dead_code)]
680 pub fn net_additions(&self) -> i64 {
681 self.added.len() as i64 - self.removed.len() as i64
682 }
683 #[allow(dead_code)]
684 pub fn summary(&self) -> String {
685 format!(
686 "+{} -{} =={}",
687 self.added.len(),
688 self.removed.len(),
689 self.unchanged.len()
690 )
691 }
692}
693#[allow(dead_code)]
695#[derive(Debug, Clone, Default)]
696pub struct MatchBasicUtil9 {
697 pub id: usize,
698 pub name: String,
699 pub value: i64,
700 pub enabled: bool,
701 pub tags: Vec<String>,
702}
703#[allow(dead_code)]
704impl MatchBasicUtil9 {
705 pub fn new(id: usize, name: &str, value: i64) -> Self {
706 MatchBasicUtil9 {
707 id,
708 name: name.to_string(),
709 value,
710 enabled: true,
711 tags: Vec::new(),
712 }
713 }
714 pub fn with_tag(mut self, tag: &str) -> Self {
715 self.tags.push(tag.to_string());
716 self
717 }
718 pub fn disable(mut self) -> Self {
719 self.enabled = false;
720 self
721 }
722 pub fn is_active(&self) -> bool {
723 self.enabled
724 }
725 pub fn score(&self) -> i64 {
726 if self.enabled {
727 self.value
728 } else {
729 0
730 }
731 }
732 pub fn tag_count(&self) -> usize {
733 self.tags.len()
734 }
735 pub fn has_tag(&self, tag: &str) -> bool {
736 self.tags.iter().any(|t| t == tag)
737 }
738}
739#[allow(dead_code)]
741pub struct MatchBasicPriorityQueue {
742 pub items: Vec<(MatchBasicUtil0, i64)>,
743}
744#[allow(dead_code)]
745impl MatchBasicPriorityQueue {
746 pub fn new() -> Self {
747 MatchBasicPriorityQueue { items: Vec::new() }
748 }
749 pub fn push(&mut self, item: MatchBasicUtil0, priority: i64) {
750 self.items.push((item, priority));
751 self.items.sort_by_key(|(_, p)| -p);
752 }
753 pub fn pop(&mut self) -> Option<(MatchBasicUtil0, i64)> {
754 if self.items.is_empty() {
755 None
756 } else {
757 Some(self.items.remove(0))
758 }
759 }
760 pub fn peek(&self) -> Option<&(MatchBasicUtil0, i64)> {
761 self.items.first()
762 }
763 pub fn is_empty(&self) -> bool {
764 self.items.is_empty()
765 }
766 pub fn len(&self) -> usize {
767 self.items.len()
768 }
769}
770#[allow(dead_code)]
771#[derive(Debug, Clone)]
772pub enum MatchBasicExtResult4100 {
773 Ok(String),
775 Err(String),
777 Partial { done: usize, total: usize },
779 Skipped,
781}
782impl MatchBasicExtResult4100 {
783 #[allow(dead_code)]
784 pub fn is_ok(&self) -> bool {
785 matches!(self, MatchBasicExtResult4100::Ok(_))
786 }
787 #[allow(dead_code)]
788 pub fn is_err(&self) -> bool {
789 matches!(self, MatchBasicExtResult4100::Err(_))
790 }
791 #[allow(dead_code)]
792 pub fn is_partial(&self) -> bool {
793 matches!(self, MatchBasicExtResult4100::Partial { .. })
794 }
795 #[allow(dead_code)]
796 pub fn is_skipped(&self) -> bool {
797 matches!(self, MatchBasicExtResult4100::Skipped)
798 }
799 #[allow(dead_code)]
800 pub fn ok_msg(&self) -> Option<&str> {
801 if let MatchBasicExtResult4100::Ok(s) = self {
802 Some(s)
803 } else {
804 None
805 }
806 }
807 #[allow(dead_code)]
808 pub fn err_msg(&self) -> Option<&str> {
809 if let MatchBasicExtResult4100::Err(s) = self {
810 Some(s)
811 } else {
812 None
813 }
814 }
815 #[allow(dead_code)]
816 pub fn progress(&self) -> f64 {
817 match self {
818 MatchBasicExtResult4100::Ok(_) => 1.0,
819 MatchBasicExtResult4100::Err(_) => 0.0,
820 MatchBasicExtResult4100::Partial { done, total } => {
821 if *total == 0 {
822 0.0
823 } else {
824 *done as f64 / *total as f64
825 }
826 }
827 MatchBasicExtResult4100::Skipped => 0.5,
828 }
829 }
830}
831#[allow(dead_code)]
832pub struct MatchBasicExtDiag4100 {
833 pub errors: Vec<String>,
834 pub warnings: Vec<String>,
835 pub notes: Vec<String>,
836 pub max_errors: usize,
837}
838impl MatchBasicExtDiag4100 {
839 #[allow(dead_code)]
840 pub fn new(max_errors: usize) -> Self {
841 Self {
842 errors: Vec::new(),
843 warnings: Vec::new(),
844 notes: Vec::new(),
845 max_errors,
846 }
847 }
848 #[allow(dead_code)]
849 pub fn error(&mut self, msg: &str) {
850 if self.errors.len() < self.max_errors {
851 self.errors.push(msg.to_string());
852 }
853 }
854 #[allow(dead_code)]
855 pub fn warning(&mut self, msg: &str) {
856 self.warnings.push(msg.to_string());
857 }
858 #[allow(dead_code)]
859 pub fn note(&mut self, msg: &str) {
860 self.notes.push(msg.to_string());
861 }
862 #[allow(dead_code)]
863 pub fn has_errors(&self) -> bool {
864 !self.errors.is_empty()
865 }
866 #[allow(dead_code)]
867 pub fn num_errors(&self) -> usize {
868 self.errors.len()
869 }
870 #[allow(dead_code)]
871 pub fn num_warnings(&self) -> usize {
872 self.warnings.len()
873 }
874 #[allow(dead_code)]
875 pub fn is_clean(&self) -> bool {
876 self.errors.is_empty() && self.warnings.is_empty()
877 }
878 #[allow(dead_code)]
879 pub fn at_error_limit(&self) -> bool {
880 self.errors.len() >= self.max_errors
881 }
882 #[allow(dead_code)]
883 pub fn clear(&mut self) {
884 self.errors.clear();
885 self.warnings.clear();
886 self.notes.clear();
887 }
888 #[allow(dead_code)]
889 pub fn summary(&self) -> String {
890 format!(
891 "{} error(s), {} warning(s)",
892 self.errors.len(),
893 self.warnings.len()
894 )
895 }
896}
897#[derive(Clone, Debug)]
899pub struct PatternRow {
900 pub patterns: Vec<MetaPattern>,
902 pub arm_index: usize,
904 pub guard: Option<Expr>,
906}
907impl PatternRow {
908 pub fn new(patterns: Vec<MetaPattern>, arm_index: usize) -> Self {
910 Self {
911 patterns,
912 arm_index,
913 guard: None,
914 }
915 }
916 pub fn is_all_irrefutable(&self) -> bool {
918 self.patterns.iter().all(|p| p.is_irrefutable())
919 }
920 pub fn first_refutable(&self) -> Option<(usize, &MetaPattern)> {
922 self.patterns
923 .iter()
924 .enumerate()
925 .find(|(_, p)| !p.is_irrefutable())
926 }
927}
928#[allow(dead_code)]
930#[derive(Debug, Clone, Default)]
931pub struct MatchBasicUtil7 {
932 pub id: usize,
933 pub name: String,
934 pub value: i64,
935 pub enabled: bool,
936 pub tags: Vec<String>,
937}
938#[allow(dead_code)]
939impl MatchBasicUtil7 {
940 pub fn new(id: usize, name: &str, value: i64) -> Self {
941 MatchBasicUtil7 {
942 id,
943 name: name.to_string(),
944 value,
945 enabled: true,
946 tags: Vec::new(),
947 }
948 }
949 pub fn with_tag(mut self, tag: &str) -> Self {
950 self.tags.push(tag.to_string());
951 self
952 }
953 pub fn disable(mut self) -> Self {
954 self.enabled = false;
955 self
956 }
957 pub fn is_active(&self) -> bool {
958 self.enabled
959 }
960 pub fn score(&self) -> i64 {
961 if self.enabled {
962 self.value
963 } else {
964 0
965 }
966 }
967 pub fn tag_count(&self) -> usize {
968 self.tags.len()
969 }
970 pub fn has_tag(&self, tag: &str) -> bool {
971 self.tags.iter().any(|t| t == tag)
972 }
973}
974#[allow(dead_code)]
976#[derive(Debug, Clone, Default)]
977pub struct MatchBasicUtil4 {
978 pub id: usize,
979 pub name: String,
980 pub value: i64,
981 pub enabled: bool,
982 pub tags: Vec<String>,
983}
984#[allow(dead_code)]
985impl MatchBasicUtil4 {
986 pub fn new(id: usize, name: &str, value: i64) -> Self {
987 MatchBasicUtil4 {
988 id,
989 name: name.to_string(),
990 value,
991 enabled: true,
992 tags: Vec::new(),
993 }
994 }
995 pub fn with_tag(mut self, tag: &str) -> Self {
996 self.tags.push(tag.to_string());
997 self
998 }
999 pub fn disable(mut self) -> Self {
1000 self.enabled = false;
1001 self
1002 }
1003 pub fn is_active(&self) -> bool {
1004 self.enabled
1005 }
1006 pub fn score(&self) -> i64 {
1007 if self.enabled {
1008 self.value
1009 } else {
1010 0
1011 }
1012 }
1013 pub fn tag_count(&self) -> usize {
1014 self.tags.len()
1015 }
1016 pub fn has_tag(&self, tag: &str) -> bool {
1017 self.tags.iter().any(|t| t == tag)
1018 }
1019}
1020#[allow(dead_code)]
1022pub struct MatchBasicCache {
1023 pub data: std::collections::HashMap<String, i64>,
1024 pub hits: usize,
1025 pub misses: usize,
1026}
1027#[allow(dead_code)]
1028impl MatchBasicCache {
1029 pub fn new() -> Self {
1030 MatchBasicCache {
1031 data: std::collections::HashMap::new(),
1032 hits: 0,
1033 misses: 0,
1034 }
1035 }
1036 pub fn get(&mut self, key: &str) -> Option<i64> {
1037 if let Some(&v) = self.data.get(key) {
1038 self.hits += 1;
1039 Some(v)
1040 } else {
1041 self.misses += 1;
1042 None
1043 }
1044 }
1045 pub fn insert(&mut self, key: &str, value: i64) {
1046 self.data.insert(key.to_string(), value);
1047 }
1048 pub fn hit_rate(&self) -> f64 {
1049 let t = self.hits + self.misses;
1050 if t == 0 {
1051 0.0
1052 } else {
1053 self.hits as f64 / t as f64
1054 }
1055 }
1056 pub fn size(&self) -> usize {
1057 self.data.len()
1058 }
1059 pub fn clear(&mut self) {
1060 self.data.clear();
1061 self.hits = 0;
1062 self.misses = 0;
1063 }
1064}
1065#[allow(dead_code)]
1067#[derive(Debug, Clone)]
1068pub struct MatchBasicDiff {
1069 pub added: Vec<String>,
1070 pub removed: Vec<String>,
1071 pub unchanged: Vec<String>,
1072}
1073#[allow(dead_code)]
1074impl MatchBasicDiff {
1075 pub fn new() -> Self {
1076 MatchBasicDiff {
1077 added: Vec::new(),
1078 removed: Vec::new(),
1079 unchanged: Vec::new(),
1080 }
1081 }
1082 pub fn add(&mut self, s: &str) {
1083 self.added.push(s.to_string());
1084 }
1085 pub fn remove(&mut self, s: &str) {
1086 self.removed.push(s.to_string());
1087 }
1088 pub fn keep(&mut self, s: &str) {
1089 self.unchanged.push(s.to_string());
1090 }
1091 pub fn is_empty(&self) -> bool {
1092 self.added.is_empty() && self.removed.is_empty()
1093 }
1094 pub fn total_changes(&self) -> usize {
1095 self.added.len() + self.removed.len()
1096 }
1097 pub fn net_additions(&self) -> i64 {
1098 self.added.len() as i64 - self.removed.len() as i64
1099 }
1100 pub fn summary(&self) -> String {
1101 format!(
1102 "+{} -{} =={}",
1103 self.added.len(),
1104 self.removed.len(),
1105 self.unchanged.len()
1106 )
1107 }
1108}
1109#[allow(dead_code)]
1111pub struct MatchBasicRegistry {
1112 pub entries: Vec<MatchBasicUtil0>,
1113 pub capacity: usize,
1114}
1115#[allow(dead_code)]
1116impl MatchBasicRegistry {
1117 pub fn new(capacity: usize) -> Self {
1118 MatchBasicRegistry {
1119 entries: Vec::new(),
1120 capacity,
1121 }
1122 }
1123 pub fn register(&mut self, entry: MatchBasicUtil0) -> bool {
1124 if self.entries.len() >= self.capacity {
1125 return false;
1126 }
1127 self.entries.push(entry);
1128 true
1129 }
1130 pub fn lookup(&self, id: usize) -> Option<&MatchBasicUtil0> {
1131 self.entries.iter().find(|e| e.id == id)
1132 }
1133 pub fn remove(&mut self, id: usize) -> bool {
1134 let before = self.entries.len();
1135 self.entries.retain(|e| e.id != id);
1136 self.entries.len() < before
1137 }
1138 pub fn active_entries(&self) -> Vec<&MatchBasicUtil0> {
1139 self.entries.iter().filter(|e| e.is_active()).collect()
1140 }
1141 pub fn total_score(&self) -> i64 {
1142 self.entries.iter().map(|e| e.score()).sum()
1143 }
1144 pub fn count(&self) -> usize {
1145 self.entries.len()
1146 }
1147 pub fn is_full(&self) -> bool {
1148 self.entries.len() >= self.capacity
1149 }
1150 pub fn is_empty(&self) -> bool {
1151 self.entries.is_empty()
1152 }
1153}
1154#[allow(dead_code)]
1156#[derive(Debug, Clone, Default)]
1157pub struct MatchBasicUtil0 {
1158 pub id: usize,
1159 pub name: String,
1160 pub value: i64,
1161 pub enabled: bool,
1162 pub tags: Vec<String>,
1163}
1164#[allow(dead_code)]
1165impl MatchBasicUtil0 {
1166 pub fn new(id: usize, name: &str, value: i64) -> Self {
1167 MatchBasicUtil0 {
1168 id,
1169 name: name.to_string(),
1170 value,
1171 enabled: true,
1172 tags: Vec::new(),
1173 }
1174 }
1175 pub fn with_tag(mut self, tag: &str) -> Self {
1176 self.tags.push(tag.to_string());
1177 self
1178 }
1179 pub fn disable(mut self) -> Self {
1180 self.enabled = false;
1181 self
1182 }
1183 pub fn is_active(&self) -> bool {
1184 self.enabled
1185 }
1186 pub fn score(&self) -> i64 {
1187 if self.enabled {
1188 self.value
1189 } else {
1190 0
1191 }
1192 }
1193 pub fn tag_count(&self) -> usize {
1194 self.tags.len()
1195 }
1196 pub fn has_tag(&self, tag: &str) -> bool {
1197 self.tags.iter().any(|t| t == tag)
1198 }
1199}
1200#[allow(dead_code)]
1202#[derive(Debug, Clone, Default)]
1203pub struct MatchBasicUtil6 {
1204 pub id: usize,
1205 pub name: String,
1206 pub value: i64,
1207 pub enabled: bool,
1208 pub tags: Vec<String>,
1209}
1210#[allow(dead_code)]
1211impl MatchBasicUtil6 {
1212 pub fn new(id: usize, name: &str, value: i64) -> Self {
1213 MatchBasicUtil6 {
1214 id,
1215 name: name.to_string(),
1216 value,
1217 enabled: true,
1218 tags: Vec::new(),
1219 }
1220 }
1221 pub fn with_tag(mut self, tag: &str) -> Self {
1222 self.tags.push(tag.to_string());
1223 self
1224 }
1225 pub fn disable(mut self) -> Self {
1226 self.enabled = false;
1227 self
1228 }
1229 pub fn is_active(&self) -> bool {
1230 self.enabled
1231 }
1232 pub fn score(&self) -> i64 {
1233 if self.enabled {
1234 self.value
1235 } else {
1236 0
1237 }
1238 }
1239 pub fn tag_count(&self) -> usize {
1240 self.tags.len()
1241 }
1242 pub fn has_tag(&self, tag: &str) -> bool {
1243 self.tags.iter().any(|t| t == tag)
1244 }
1245}
1246#[allow(dead_code)]
1248#[derive(Debug, Clone, Default)]
1249pub struct MatchBasicUtil11 {
1250 pub id: usize,
1251 pub name: String,
1252 pub value: i64,
1253 pub enabled: bool,
1254 pub tags: Vec<String>,
1255}
1256#[allow(dead_code)]
1257impl MatchBasicUtil11 {
1258 pub fn new(id: usize, name: &str, value: i64) -> Self {
1259 MatchBasicUtil11 {
1260 id,
1261 name: name.to_string(),
1262 value,
1263 enabled: true,
1264 tags: Vec::new(),
1265 }
1266 }
1267 pub fn with_tag(mut self, tag: &str) -> Self {
1268 self.tags.push(tag.to_string());
1269 self
1270 }
1271 pub fn disable(mut self) -> Self {
1272 self.enabled = false;
1273 self
1274 }
1275 pub fn is_active(&self) -> bool {
1276 self.enabled
1277 }
1278 pub fn score(&self) -> i64 {
1279 if self.enabled {
1280 self.value
1281 } else {
1282 0
1283 }
1284 }
1285 pub fn tag_count(&self) -> usize {
1286 self.tags.len()
1287 }
1288 pub fn has_tag(&self, tag: &str) -> bool {
1289 self.tags.iter().any(|t| t == tag)
1290 }
1291}
1292#[allow(dead_code)]
1294#[derive(Debug, Clone, PartialEq)]
1295pub enum MatchBasicResult {
1296 Ok(String),
1297 Err(String),
1298 Partial { done: usize, total: usize },
1299 Skipped,
1300}
1301#[allow(dead_code)]
1302impl MatchBasicResult {
1303 pub fn is_ok(&self) -> bool {
1304 matches!(self, MatchBasicResult::Ok(_))
1305 }
1306 pub fn is_err(&self) -> bool {
1307 matches!(self, MatchBasicResult::Err(_))
1308 }
1309 pub fn is_partial(&self) -> bool {
1310 matches!(self, MatchBasicResult::Partial { .. })
1311 }
1312 pub fn is_skipped(&self) -> bool {
1313 matches!(self, MatchBasicResult::Skipped)
1314 }
1315 pub fn ok_msg(&self) -> Option<&str> {
1316 match self {
1317 MatchBasicResult::Ok(s) => Some(s),
1318 _ => None,
1319 }
1320 }
1321 pub fn err_msg(&self) -> Option<&str> {
1322 match self {
1323 MatchBasicResult::Err(s) => Some(s),
1324 _ => None,
1325 }
1326 }
1327 pub fn progress(&self) -> f64 {
1328 match self {
1329 MatchBasicResult::Ok(_) => 1.0,
1330 MatchBasicResult::Err(_) => 0.0,
1331 MatchBasicResult::Skipped => 0.0,
1332 MatchBasicResult::Partial { done, total } => {
1333 if *total == 0 {
1334 0.0
1335 } else {
1336 *done as f64 / *total as f64
1337 }
1338 }
1339 }
1340 }
1341}
1342#[allow(dead_code)]
1344#[derive(Debug, Clone, Default)]
1345pub struct MatchBasicUtil10 {
1346 pub id: usize,
1347 pub name: String,
1348 pub value: i64,
1349 pub enabled: bool,
1350 pub tags: Vec<String>,
1351}
1352#[allow(dead_code)]
1353impl MatchBasicUtil10 {
1354 pub fn new(id: usize, name: &str, value: i64) -> Self {
1355 MatchBasicUtil10 {
1356 id,
1357 name: name.to_string(),
1358 value,
1359 enabled: true,
1360 tags: Vec::new(),
1361 }
1362 }
1363 pub fn with_tag(mut self, tag: &str) -> Self {
1364 self.tags.push(tag.to_string());
1365 self
1366 }
1367 pub fn disable(mut self) -> Self {
1368 self.enabled = false;
1369 self
1370 }
1371 pub fn is_active(&self) -> bool {
1372 self.enabled
1373 }
1374 pub fn score(&self) -> i64 {
1375 if self.enabled {
1376 self.value
1377 } else {
1378 0
1379 }
1380 }
1381 pub fn tag_count(&self) -> usize {
1382 self.tags.len()
1383 }
1384 pub fn has_tag(&self, tag: &str) -> bool {
1385 self.tags.iter().any(|t| t == tag)
1386 }
1387}
1388#[derive(Clone, Debug)]
1390pub struct MetaMatchExpr {
1391 pub discriminants: Vec<Expr>,
1393 pub discr_types: Vec<Expr>,
1395 pub arms: Vec<MetaMatchArm>,
1397 pub expected_type: Option<Expr>,
1399}
1400impl MetaMatchExpr {
1401 pub fn new(discriminants: Vec<Expr>, discr_types: Vec<Expr>) -> Self {
1403 Self {
1404 discriminants,
1405 discr_types,
1406 arms: Vec::new(),
1407 expected_type: None,
1408 }
1409 }
1410 pub fn add_arm(&mut self, arm: MetaMatchArm) {
1412 self.arms.push(arm);
1413 }
1414 pub fn set_expected_type(&mut self, ty: Expr) {
1416 self.expected_type = Some(ty);
1417 }
1418 pub fn num_discriminants(&self) -> usize {
1420 self.discriminants.len()
1421 }
1422 pub fn num_arms(&self) -> usize {
1424 self.arms.len()
1425 }
1426 pub fn validate_patterns(&self) -> Result<(), String> {
1428 let expected = self.num_discriminants();
1429 for (i, arm) in self.arms.iter().enumerate() {
1430 if arm.patterns.len() != expected {
1431 return Err(format!(
1432 "Arm {} has {} patterns, expected {}",
1433 i,
1434 arm.patterns.len(),
1435 expected
1436 ));
1437 }
1438 }
1439 Ok(())
1440 }
1441}
1442#[derive(Debug, Clone)]
1447pub enum DecisionTree {
1448 Leaf(usize),
1450 Fail,
1452 Switch {
1454 discr_idx: usize,
1456 cases: Vec<(oxilean_kernel::Name, Box<DecisionTree>)>,
1458 default: Option<Box<DecisionTree>>,
1460 },
1461 Guard {
1463 condition: Expr,
1465 success: Box<DecisionTree>,
1467 failure: Box<DecisionTree>,
1469 },
1470}
1471impl DecisionTree {
1472 pub fn is_leaf(&self) -> bool {
1474 matches!(self, DecisionTree::Leaf(_))
1475 }
1476 pub fn is_fail(&self) -> bool {
1478 matches!(self, DecisionTree::Fail)
1479 }
1480 pub fn num_reachable_arms(&self) -> usize {
1482 match self {
1483 DecisionTree::Leaf(_) => 1,
1484 DecisionTree::Fail => 0,
1485 DecisionTree::Switch { cases, default, .. } => {
1486 let case_count: usize = cases.iter().map(|(_, sub)| sub.num_reachable_arms()).sum();
1487 let default_count = default
1488 .as_ref()
1489 .map(|d| d.num_reachable_arms())
1490 .unwrap_or(0);
1491 case_count + default_count
1492 }
1493 DecisionTree::Guard {
1494 success, failure, ..
1495 } => success.num_reachable_arms() + failure.num_reachable_arms(),
1496 }
1497 }
1498 pub fn depth(&self) -> usize {
1500 match self {
1501 DecisionTree::Leaf(_) | DecisionTree::Fail => 0,
1502 DecisionTree::Switch { cases, default, .. } => {
1503 let case_depth = cases.iter().map(|(_, sub)| sub.depth()).max().unwrap_or(0);
1504 let default_depth = default.as_ref().map(|d| d.depth()).unwrap_or(0);
1505 1 + case_depth.max(default_depth)
1506 }
1507 DecisionTree::Guard {
1508 success, failure, ..
1509 } => 1 + success.depth().max(failure.depth()),
1510 }
1511 }
1512}
1513#[allow(dead_code)]
1515#[derive(Debug, Clone, Default)]
1516pub struct MatchBasicUtil13 {
1517 pub id: usize,
1518 pub name: String,
1519 pub value: i64,
1520 pub enabled: bool,
1521 pub tags: Vec<String>,
1522}
1523#[allow(dead_code)]
1524impl MatchBasicUtil13 {
1525 pub fn new(id: usize, name: &str, value: i64) -> Self {
1526 MatchBasicUtil13 {
1527 id,
1528 name: name.to_string(),
1529 value,
1530 enabled: true,
1531 tags: Vec::new(),
1532 }
1533 }
1534 pub fn with_tag(mut self, tag: &str) -> Self {
1535 self.tags.push(tag.to_string());
1536 self
1537 }
1538 pub fn disable(mut self) -> Self {
1539 self.enabled = false;
1540 self
1541 }
1542 pub fn is_active(&self) -> bool {
1543 self.enabled
1544 }
1545 pub fn score(&self) -> i64 {
1546 if self.enabled {
1547 self.value
1548 } else {
1549 0
1550 }
1551 }
1552 pub fn tag_count(&self) -> usize {
1553 self.tags.len()
1554 }
1555 pub fn has_tag(&self, tag: &str) -> bool {
1556 self.tags.iter().any(|t| t == tag)
1557 }
1558}
1559#[allow(dead_code)]
1561pub struct MatchBasicAnalysisPass {
1562 pub name: String,
1563 pub enabled: bool,
1564 pub results: Vec<MatchBasicResult>,
1565 pub total_runs: usize,
1566}
1567#[allow(dead_code)]
1568impl MatchBasicAnalysisPass {
1569 pub fn new(name: &str) -> Self {
1570 MatchBasicAnalysisPass {
1571 name: name.to_string(),
1572 enabled: true,
1573 results: Vec::new(),
1574 total_runs: 0,
1575 }
1576 }
1577 pub fn run(&mut self, input: &str) -> MatchBasicResult {
1578 self.total_runs += 1;
1579 let result = if input.is_empty() {
1580 MatchBasicResult::Err("empty input".to_string())
1581 } else {
1582 MatchBasicResult::Ok(format!("processed: {}", input))
1583 };
1584 self.results.push(result.clone());
1585 result
1586 }
1587 pub fn success_count(&self) -> usize {
1588 self.results.iter().filter(|r| r.is_ok()).count()
1589 }
1590 pub fn error_count(&self) -> usize {
1591 self.results.iter().filter(|r| r.is_err()).count()
1592 }
1593 pub fn success_rate(&self) -> f64 {
1594 if self.total_runs == 0 {
1595 0.0
1596 } else {
1597 self.success_count() as f64 / self.total_runs as f64
1598 }
1599 }
1600 pub fn disable(&mut self) {
1601 self.enabled = false;
1602 }
1603 pub fn enable(&mut self) {
1604 self.enabled = true;
1605 }
1606 pub fn clear_results(&mut self) {
1607 self.results.clear();
1608 }
1609}
1610#[derive(Clone, Debug)]
1612pub struct MetaMatchArm {
1613 pub patterns: Vec<MetaPattern>,
1615 pub guard: Option<Expr>,
1617 pub rhs: Expr,
1619}
1620#[allow(dead_code)]
1622#[derive(Debug, Clone, Default)]
1623pub struct MatchBasicUtil1 {
1624 pub id: usize,
1625 pub name: String,
1626 pub value: i64,
1627 pub enabled: bool,
1628 pub tags: Vec<String>,
1629}
1630#[allow(dead_code)]
1631impl MatchBasicUtil1 {
1632 pub fn new(id: usize, name: &str, value: i64) -> Self {
1633 MatchBasicUtil1 {
1634 id,
1635 name: name.to_string(),
1636 value,
1637 enabled: true,
1638 tags: Vec::new(),
1639 }
1640 }
1641 pub fn with_tag(mut self, tag: &str) -> Self {
1642 self.tags.push(tag.to_string());
1643 self
1644 }
1645 pub fn disable(mut self) -> Self {
1646 self.enabled = false;
1647 self
1648 }
1649 pub fn is_active(&self) -> bool {
1650 self.enabled
1651 }
1652 pub fn score(&self) -> i64 {
1653 if self.enabled {
1654 self.value
1655 } else {
1656 0
1657 }
1658 }
1659 pub fn tag_count(&self) -> usize {
1660 self.tags.len()
1661 }
1662 pub fn has_tag(&self, tag: &str) -> bool {
1663 self.tags.iter().any(|t| t == tag)
1664 }
1665}
1666#[allow(dead_code)]
1668#[derive(Debug, Clone, Default)]
1669pub struct MatchBasicStats {
1670 pub total_ops: usize,
1671 pub successful_ops: usize,
1672 pub failed_ops: usize,
1673 pub total_time_ns: u64,
1674 pub max_time_ns: u64,
1675}
1676#[allow(dead_code)]
1677impl MatchBasicStats {
1678 pub fn new() -> Self {
1679 MatchBasicStats::default()
1680 }
1681 pub fn record_success(&mut self, time_ns: u64) {
1682 self.total_ops += 1;
1683 self.successful_ops += 1;
1684 self.total_time_ns += time_ns;
1685 if time_ns > self.max_time_ns {
1686 self.max_time_ns = time_ns;
1687 }
1688 }
1689 pub fn record_failure(&mut self) {
1690 self.total_ops += 1;
1691 self.failed_ops += 1;
1692 }
1693 pub fn success_rate(&self) -> f64 {
1694 if self.total_ops == 0 {
1695 0.0
1696 } else {
1697 self.successful_ops as f64 / self.total_ops as f64
1698 }
1699 }
1700 pub fn avg_time_ns(&self) -> f64 {
1701 if self.successful_ops == 0 {
1702 0.0
1703 } else {
1704 self.total_time_ns as f64 / self.successful_ops as f64
1705 }
1706 }
1707 pub fn merge(&mut self, other: &Self) {
1708 self.total_ops += other.total_ops;
1709 self.successful_ops += other.successful_ops;
1710 self.failed_ops += other.failed_ops;
1711 self.total_time_ns += other.total_time_ns;
1712 if other.max_time_ns > self.max_time_ns {
1713 self.max_time_ns = other.max_time_ns;
1714 }
1715 }
1716}
1717#[allow(dead_code)]
1718pub struct MatchBasicExtConfig4100 {
1719 pub(super) values: std::collections::HashMap<String, MatchBasicExtConfigVal4100>,
1720 pub(super) read_only: bool,
1721 pub(super) name: String,
1722}
1723impl MatchBasicExtConfig4100 {
1724 #[allow(dead_code)]
1725 pub fn new() -> Self {
1726 Self {
1727 values: std::collections::HashMap::new(),
1728 read_only: false,
1729 name: String::new(),
1730 }
1731 }
1732 #[allow(dead_code)]
1733 pub fn named(name: &str) -> Self {
1734 Self {
1735 values: std::collections::HashMap::new(),
1736 read_only: false,
1737 name: name.to_string(),
1738 }
1739 }
1740 #[allow(dead_code)]
1741 pub fn set(&mut self, key: &str, value: MatchBasicExtConfigVal4100) -> bool {
1742 if self.read_only {
1743 return false;
1744 }
1745 self.values.insert(key.to_string(), value);
1746 true
1747 }
1748 #[allow(dead_code)]
1749 pub fn get(&self, key: &str) -> Option<&MatchBasicExtConfigVal4100> {
1750 self.values.get(key)
1751 }
1752 #[allow(dead_code)]
1753 pub fn get_bool(&self, key: &str) -> Option<bool> {
1754 self.get(key)?.as_bool()
1755 }
1756 #[allow(dead_code)]
1757 pub fn get_int(&self, key: &str) -> Option<i64> {
1758 self.get(key)?.as_int()
1759 }
1760 #[allow(dead_code)]
1761 pub fn get_str(&self, key: &str) -> Option<&str> {
1762 self.get(key)?.as_str()
1763 }
1764 #[allow(dead_code)]
1765 pub fn set_bool(&mut self, key: &str, v: bool) -> bool {
1766 self.set(key, MatchBasicExtConfigVal4100::Bool(v))
1767 }
1768 #[allow(dead_code)]
1769 pub fn set_int(&mut self, key: &str, v: i64) -> bool {
1770 self.set(key, MatchBasicExtConfigVal4100::Int(v))
1771 }
1772 #[allow(dead_code)]
1773 pub fn set_str(&mut self, key: &str, v: &str) -> bool {
1774 self.set(key, MatchBasicExtConfigVal4100::Str(v.to_string()))
1775 }
1776 #[allow(dead_code)]
1777 pub fn lock(&mut self) {
1778 self.read_only = true;
1779 }
1780 #[allow(dead_code)]
1781 pub fn unlock(&mut self) {
1782 self.read_only = false;
1783 }
1784 #[allow(dead_code)]
1785 pub fn size(&self) -> usize {
1786 self.values.len()
1787 }
1788 #[allow(dead_code)]
1789 pub fn has(&self, key: &str) -> bool {
1790 self.values.contains_key(key)
1791 }
1792 #[allow(dead_code)]
1793 pub fn remove(&mut self, key: &str) -> bool {
1794 self.values.remove(key).is_some()
1795 }
1796}
1797#[allow(dead_code)]
1799#[derive(Debug, Clone, Default)]
1800pub struct MatchBasicUtil2 {
1801 pub id: usize,
1802 pub name: String,
1803 pub value: i64,
1804 pub enabled: bool,
1805 pub tags: Vec<String>,
1806}
1807#[allow(dead_code)]
1808impl MatchBasicUtil2 {
1809 pub fn new(id: usize, name: &str, value: i64) -> Self {
1810 MatchBasicUtil2 {
1811 id,
1812 name: name.to_string(),
1813 value,
1814 enabled: true,
1815 tags: Vec::new(),
1816 }
1817 }
1818 pub fn with_tag(mut self, tag: &str) -> Self {
1819 self.tags.push(tag.to_string());
1820 self
1821 }
1822 pub fn disable(mut self) -> Self {
1823 self.enabled = false;
1824 self
1825 }
1826 pub fn is_active(&self) -> bool {
1827 self.enabled
1828 }
1829 pub fn score(&self) -> i64 {
1830 if self.enabled {
1831 self.value
1832 } else {
1833 0
1834 }
1835 }
1836 pub fn tag_count(&self) -> usize {
1837 self.tags.len()
1838 }
1839 pub fn has_tag(&self, tag: &str) -> bool {
1840 self.tags.iter().any(|t| t == tag)
1841 }
1842}
1843#[allow(dead_code)]
1845#[derive(Debug, Clone, Default)]
1846pub struct MatchBasicUtil5 {
1847 pub id: usize,
1848 pub name: String,
1849 pub value: i64,
1850 pub enabled: bool,
1851 pub tags: Vec<String>,
1852}
1853#[allow(dead_code)]
1854impl MatchBasicUtil5 {
1855 pub fn new(id: usize, name: &str, value: i64) -> Self {
1856 MatchBasicUtil5 {
1857 id,
1858 name: name.to_string(),
1859 value,
1860 enabled: true,
1861 tags: Vec::new(),
1862 }
1863 }
1864 pub fn with_tag(mut self, tag: &str) -> Self {
1865 self.tags.push(tag.to_string());
1866 self
1867 }
1868 pub fn disable(mut self) -> Self {
1869 self.enabled = false;
1870 self
1871 }
1872 pub fn is_active(&self) -> bool {
1873 self.enabled
1874 }
1875 pub fn score(&self) -> i64 {
1876 if self.enabled {
1877 self.value
1878 } else {
1879 0
1880 }
1881 }
1882 pub fn tag_count(&self) -> usize {
1883 self.tags.len()
1884 }
1885 pub fn has_tag(&self, tag: &str) -> bool {
1886 self.tags.iter().any(|t| t == tag)
1887 }
1888}
1889#[allow(dead_code)]
1891pub struct MatchBasicLogger {
1892 pub entries: Vec<String>,
1893 pub max_entries: usize,
1894 pub verbose: bool,
1895}
1896#[allow(dead_code)]
1897impl MatchBasicLogger {
1898 pub fn new(max_entries: usize) -> Self {
1899 MatchBasicLogger {
1900 entries: Vec::new(),
1901 max_entries,
1902 verbose: false,
1903 }
1904 }
1905 pub fn log(&mut self, msg: &str) {
1906 if self.entries.len() < self.max_entries {
1907 self.entries.push(msg.to_string());
1908 }
1909 }
1910 pub fn verbose(&mut self, msg: &str) {
1911 if self.verbose {
1912 self.log(msg);
1913 }
1914 }
1915 pub fn clear(&mut self) {
1916 self.entries.clear();
1917 }
1918 pub fn count(&self) -> usize {
1919 self.entries.len()
1920 }
1921 pub fn last(&self) -> Option<&str> {
1922 self.entries.last().map(|s| s.as_str())
1923 }
1924 pub fn enable_verbose(&mut self) {
1925 self.verbose = true;
1926 }
1927 pub fn disable_verbose(&mut self) {
1928 self.verbose = false;
1929 }
1930}
1931#[allow(dead_code)]
1933#[derive(Debug, Clone, Default)]
1934pub struct MatchBasicUtil8 {
1935 pub id: usize,
1936 pub name: String,
1937 pub value: i64,
1938 pub enabled: bool,
1939 pub tags: Vec<String>,
1940}
1941#[allow(dead_code)]
1942impl MatchBasicUtil8 {
1943 pub fn new(id: usize, name: &str, value: i64) -> Self {
1944 MatchBasicUtil8 {
1945 id,
1946 name: name.to_string(),
1947 value,
1948 enabled: true,
1949 tags: Vec::new(),
1950 }
1951 }
1952 pub fn with_tag(mut self, tag: &str) -> Self {
1953 self.tags.push(tag.to_string());
1954 self
1955 }
1956 pub fn disable(mut self) -> Self {
1957 self.enabled = false;
1958 self
1959 }
1960 pub fn is_active(&self) -> bool {
1961 self.enabled
1962 }
1963 pub fn score(&self) -> i64 {
1964 if self.enabled {
1965 self.value
1966 } else {
1967 0
1968 }
1969 }
1970 pub fn tag_count(&self) -> usize {
1971 self.tags.len()
1972 }
1973 pub fn has_tag(&self, tag: &str) -> bool {
1974 self.tags.iter().any(|t| t == tag)
1975 }
1976}
1977#[allow(dead_code)]
1978pub struct MatchBasicExtPipeline4100 {
1979 pub name: String,
1980 pub passes: Vec<MatchBasicExtPass4100>,
1981 pub run_count: usize,
1982}
1983impl MatchBasicExtPipeline4100 {
1984 #[allow(dead_code)]
1985 pub fn new(name: &str) -> Self {
1986 Self {
1987 name: name.to_string(),
1988 passes: Vec::new(),
1989 run_count: 0,
1990 }
1991 }
1992 #[allow(dead_code)]
1993 pub fn add_pass(&mut self, pass: MatchBasicExtPass4100) {
1994 self.passes.push(pass);
1995 }
1996 #[allow(dead_code)]
1997 pub fn run_all(&mut self, input: &str) -> Vec<MatchBasicExtResult4100> {
1998 self.run_count += 1;
1999 self.passes
2000 .iter_mut()
2001 .filter(|p| p.enabled)
2002 .map(|p| p.run(input))
2003 .collect()
2004 }
2005 #[allow(dead_code)]
2006 pub fn num_passes(&self) -> usize {
2007 self.passes.len()
2008 }
2009 #[allow(dead_code)]
2010 pub fn num_enabled_passes(&self) -> usize {
2011 self.passes.iter().filter(|p| p.enabled).count()
2012 }
2013 #[allow(dead_code)]
2014 pub fn total_success_rate(&self) -> f64 {
2015 let total: usize = self.passes.iter().map(|p| p.total_runs).sum();
2016 let ok: usize = self.passes.iter().map(|p| p.successes).sum();
2017 if total == 0 {
2018 0.0
2019 } else {
2020 ok as f64 / total as f64
2021 }
2022 }
2023}