1use std::collections::{HashMap, HashSet, VecDeque};
6
7#[allow(dead_code)]
9pub struct LoopClock {
10 start: std::time::Instant,
11 iters: u64,
12}
13#[allow(dead_code)]
14impl LoopClock {
15 pub fn start() -> Self {
17 Self {
18 start: std::time::Instant::now(),
19 iters: 0,
20 }
21 }
22 pub fn tick(&mut self) {
24 self.iters += 1;
25 }
26 pub fn elapsed_us(&self) -> f64 {
28 self.start.elapsed().as_secs_f64() * 1e6
29 }
30 pub fn avg_us_per_iter(&self) -> f64 {
32 if self.iters == 0 {
33 return 0.0;
34 }
35 self.elapsed_us() / self.iters as f64
36 }
37 pub fn iters(&self) -> u64 {
39 self.iters
40 }
41}
42#[allow(dead_code)]
44#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
45pub struct Timestamp(u64);
46#[allow(dead_code)]
47impl Timestamp {
48 pub const fn from_us(us: u64) -> Self {
50 Self(us)
51 }
52 pub fn as_us(self) -> u64 {
54 self.0
55 }
56 pub fn elapsed_since(self, earlier: Timestamp) -> u64 {
58 self.0.saturating_sub(earlier.0)
59 }
60}
61#[derive(Debug, Clone)]
65pub struct NameGenerator {
66 base: Name,
67 counter: u64,
68}
69impl NameGenerator {
70 pub fn new(base: Name) -> Self {
72 Self { base, counter: 0 }
73 }
74 pub fn with_base(s: impl Into<String>) -> Self {
76 Self::new(Name::str(s))
77 }
78 #[allow(clippy::should_implement_trait)]
80 pub fn next(&mut self) -> Name {
81 let n = self.base.clone().append_num(self.counter);
82 self.counter += 1;
83 n
84 }
85 pub fn peek(&self) -> Name {
87 self.base.clone().append_num(self.counter)
88 }
89 pub fn reset(&mut self) {
91 self.counter = 0;
92 }
93 pub fn count(&self) -> u64 {
95 self.counter
96 }
97}
98#[allow(dead_code)]
100#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
101pub struct TypedId<T> {
102 pub(super) id: u32,
103 _phantom: std::marker::PhantomData<T>,
104}
105#[allow(dead_code)]
106impl<T> TypedId<T> {
107 pub const fn new(id: u32) -> Self {
109 Self {
110 id,
111 _phantom: std::marker::PhantomData,
112 }
113 }
114 pub fn raw(&self) -> u32 {
116 self.id
117 }
118}
119#[allow(dead_code)]
121pub struct StringInterner {
122 strings: Vec<String>,
123 map: std::collections::HashMap<String, u32>,
124}
125#[allow(dead_code)]
126impl StringInterner {
127 pub fn new() -> Self {
129 Self {
130 strings: Vec::new(),
131 map: std::collections::HashMap::new(),
132 }
133 }
134 pub fn intern(&mut self, s: &str) -> u32 {
136 if let Some(&id) = self.map.get(s) {
137 return id;
138 }
139 let id = self.strings.len() as u32;
140 self.strings.push(s.to_string());
141 self.map.insert(s.to_string(), id);
142 id
143 }
144 pub fn get(&self, id: u32) -> Option<&str> {
146 self.strings.get(id as usize).map(|s| s.as_str())
147 }
148 pub fn len(&self) -> usize {
150 self.strings.len()
151 }
152 pub fn is_empty(&self) -> bool {
154 self.strings.is_empty()
155 }
156}
157#[derive(Debug, Clone)]
162pub struct NameTrie<V> {
163 pub(super) value: Option<V>,
165 pub(super) string_children: Vec<(String, NameTrie<V>)>,
167 pub(super) num_children: Vec<(u64, NameTrie<V>)>,
169}
170impl<V: Clone> NameTrie<V> {
171 pub fn new() -> Self {
173 Self::default()
174 }
175 pub fn insert(&mut self, name: &Name, value: V) {
177 match name {
178 Name::Anonymous => {
179 self.value = Some(value);
180 }
181 Name::Str(parent, s) => {
182 let child = if let Some(idx) = self.string_children.iter().position(|(k, _)| k == s)
183 {
184 &mut self.string_children[idx].1
185 } else {
186 self.string_children.push((s.clone(), NameTrie::new()));
187 let last = self.string_children.len() - 1;
188 &mut self.string_children[last].1
189 };
190 child.insert(parent, value);
191 }
192 Name::Num(parent, n) => {
193 let child = if let Some(idx) = self.num_children.iter().position(|(k, _)| k == n) {
194 &mut self.num_children[idx].1
195 } else {
196 self.num_children.push((*n, NameTrie::new()));
197 let last = self.num_children.len() - 1;
198 &mut self.num_children[last].1
199 };
200 child.insert(parent, value);
201 }
202 }
203 }
204 pub fn lookup(&self, name: &Name) -> Option<&V> {
206 match name {
207 Name::Anonymous => self.value.as_ref(),
208 Name::Str(parent, s) => {
209 let child = self
210 .string_children
211 .iter()
212 .find(|(k, _)| k == s)
213 .map(|(_, v)| v)?;
214 child.lookup(parent)
215 }
216 Name::Num(parent, n) => {
217 let child = self
218 .num_children
219 .iter()
220 .find(|(k, _)| k == n)
221 .map(|(_, v)| v)?;
222 child.lookup(parent)
223 }
224 }
225 }
226 pub fn contains(&self, name: &Name) -> bool {
228 self.lookup(name).is_some()
229 }
230 pub fn count(&self) -> usize {
232 let self_count = if self.value.is_some() { 1 } else { 0 };
233 let str_count: usize = self.string_children.iter().map(|(_, c)| c.count()).sum();
234 let num_count: usize = self.num_children.iter().map(|(_, c)| c.count()).sum();
235 self_count + str_count + num_count
236 }
237 pub fn to_vec(&self) -> Vec<(Name, V)> {
239 let mut result = Vec::new();
240 self.collect_all(Name::Anonymous, &mut result);
241 result
242 }
243 fn collect_all(&self, prefix: Name, result: &mut Vec<(Name, V)>) {
244 if let Some(v) = &self.value {
245 result.push((prefix.clone(), v.clone()));
246 }
247 for (s, child) in &self.string_children {
248 let name = prefix.clone().append_str(s.as_str());
249 child.collect_all(name, result);
250 }
251 for (n, child) in &self.num_children {
252 let name = prefix.clone().append_num(*n);
253 child.collect_all(name, result);
254 }
255 }
256}
257#[allow(dead_code)]
259pub struct WorkQueue<T> {
260 items: std::collections::VecDeque<T>,
261}
262#[allow(dead_code)]
263impl<T> WorkQueue<T> {
264 pub fn new() -> Self {
266 Self {
267 items: std::collections::VecDeque::new(),
268 }
269 }
270 pub fn enqueue(&mut self, item: T) {
272 self.items.push_back(item);
273 }
274 pub fn dequeue(&mut self) -> Option<T> {
276 self.items.pop_front()
277 }
278 pub fn is_empty(&self) -> bool {
280 self.items.is_empty()
281 }
282 pub fn len(&self) -> usize {
284 self.items.len()
285 }
286}
287#[allow(dead_code)]
289#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
290pub struct SeqNum(u64);
291#[allow(dead_code)]
292impl SeqNum {
293 pub const ZERO: SeqNum = SeqNum(0);
295 pub fn next(self) -> SeqNum {
297 SeqNum(self.0 + 1)
298 }
299 pub fn value(self) -> u64 {
301 self.0
302 }
303}
304#[allow(dead_code)]
306pub struct IntervalSet {
307 intervals: Vec<(i64, i64)>,
308}
309#[allow(dead_code)]
310impl IntervalSet {
311 pub fn new() -> Self {
313 Self {
314 intervals: Vec::new(),
315 }
316 }
317 pub fn add(&mut self, lo: i64, hi: i64) {
319 if lo > hi {
320 return;
321 }
322 let mut new_lo = lo;
323 let mut new_hi = hi;
324 let mut i = 0;
325 while i < self.intervals.len() {
326 let (il, ih) = self.intervals[i];
327 if ih < new_lo - 1 {
328 i += 1;
329 continue;
330 }
331 if il > new_hi + 1 {
332 break;
333 }
334 new_lo = new_lo.min(il);
335 new_hi = new_hi.max(ih);
336 self.intervals.remove(i);
337 }
338 self.intervals.insert(i, (new_lo, new_hi));
339 }
340 pub fn contains(&self, x: i64) -> bool {
342 self.intervals.iter().any(|&(lo, hi)| x >= lo && x <= hi)
343 }
344 pub fn num_intervals(&self) -> usize {
346 self.intervals.len()
347 }
348 pub fn cardinality(&self) -> i64 {
350 self.intervals.iter().map(|&(lo, hi)| hi - lo + 1).sum()
351 }
352}
353#[derive(Debug, Clone, Default)]
357pub struct NameMap<V> {
358 pub(super) inner: HashMap<Name, V>,
359}
360impl<V> NameMap<V> {
361 pub fn new() -> Self {
363 Self {
364 inner: HashMap::new(),
365 }
366 }
367 pub fn with_capacity(cap: usize) -> Self {
369 Self {
370 inner: HashMap::with_capacity(cap),
371 }
372 }
373 pub fn insert(&mut self, name: Name, value: V) -> Option<V> {
375 self.inner.insert(name, value)
376 }
377 pub fn get(&self, name: &Name) -> Option<&V> {
379 self.inner.get(name)
380 }
381 pub fn get_mut(&mut self, name: &Name) -> Option<&mut V> {
383 self.inner.get_mut(name)
384 }
385 pub fn remove(&mut self, name: &Name) -> Option<V> {
387 self.inner.remove(name)
388 }
389 pub fn contains_key(&self, name: &Name) -> bool {
391 self.inner.contains_key(name)
392 }
393 pub fn len(&self) -> usize {
395 self.inner.len()
396 }
397 pub fn is_empty(&self) -> bool {
399 self.inner.is_empty()
400 }
401 pub fn iter(&self) -> impl Iterator<Item = (&Name, &V)> {
403 self.inner.iter()
404 }
405 pub fn keys(&self) -> impl Iterator<Item = &Name> {
407 self.inner.keys()
408 }
409 pub fn values(&self) -> impl Iterator<Item = &V> {
411 self.inner.values()
412 }
413 pub fn filter_by_namespace(&self, ns: &Name) -> Vec<(&Name, &V)> {
415 self.inner
416 .iter()
417 .filter(|(n, _)| n.has_prefix(ns))
418 .collect()
419 }
420 pub fn sorted_names(&self) -> Vec<Name> {
422 let mut names: Vec<Name> = self.inner.keys().cloned().collect();
423 names.sort();
424 names
425 }
426 pub fn entry_or_insert(&mut self, name: Name, value: V) -> &mut V {
428 self.inner.entry(name).or_insert(value)
429 }
430}
431#[allow(dead_code)]
433#[allow(missing_docs)]
434pub struct BeforeAfter<T> {
435 pub before: T,
437 pub after: T,
439}
440#[allow(dead_code)]
441impl<T: PartialEq> BeforeAfter<T> {
442 pub fn new(before: T, after: T) -> Self {
444 Self { before, after }
445 }
446 pub fn unchanged(&self) -> bool {
448 self.before == self.after
449 }
450}
451#[allow(dead_code)]
453pub struct WorkStack<T> {
454 items: Vec<T>,
455}
456#[allow(dead_code)]
457impl<T> WorkStack<T> {
458 pub fn new() -> Self {
460 Self { items: Vec::new() }
461 }
462 pub fn push(&mut self, item: T) {
464 self.items.push(item);
465 }
466 pub fn pop(&mut self) -> Option<T> {
468 self.items.pop()
469 }
470 pub fn is_empty(&self) -> bool {
472 self.items.is_empty()
473 }
474 pub fn len(&self) -> usize {
476 self.items.len()
477 }
478}
479#[allow(dead_code)]
481#[derive(Clone, Copy, Debug, PartialEq, Eq)]
482pub struct Generation(u32);
483#[allow(dead_code)]
484impl Generation {
485 pub const INITIAL: Generation = Generation(0);
487 pub fn advance(self) -> Generation {
489 Generation(self.0 + 1)
490 }
491 pub fn number(self) -> u32 {
493 self.0
494 }
495}
496#[derive(Debug, Clone, PartialEq, Eq)]
500pub struct QualifiedName {
501 pub canonical: Name,
503 pub alias: Option<Name>,
505}
506impl QualifiedName {
507 pub fn new(canonical: Name) -> Self {
509 Self {
510 canonical,
511 alias: None,
512 }
513 }
514 pub fn with_alias(canonical: Name, alias: Name) -> Self {
516 Self {
517 canonical,
518 alias: Some(alias),
519 }
520 }
521 pub fn preferred(&self) -> &Name {
523 self.alias.as_ref().unwrap_or(&self.canonical)
524 }
525}
526#[allow(dead_code)]
528pub struct NamePool {
529 names: Vec<String>,
530 index: std::collections::HashMap<String, usize>,
531}
532#[allow(dead_code)]
533impl NamePool {
534 pub fn new() -> Self {
536 Self {
537 names: Vec::new(),
538 index: std::collections::HashMap::new(),
539 }
540 }
541 pub fn intern(&mut self, name: &str) -> usize {
543 if let Some(&id) = self.index.get(name) {
544 return id;
545 }
546 let id = self.names.len();
547 self.names.push(name.to_string());
548 self.index.insert(name.to_string(), id);
549 id
550 }
551 pub fn get(&self, id: usize) -> Option<&str> {
553 self.names.get(id).map(|s| s.as_str())
554 }
555 pub fn len(&self) -> usize {
557 self.names.len()
558 }
559 pub fn is_empty(&self) -> bool {
561 self.names.is_empty()
562 }
563}
564#[allow(dead_code)]
566pub struct NameResolver {
567 namespace: Vec<String>,
568 registered: std::collections::HashSet<String>,
569}
570#[allow(dead_code)]
571impl NameResolver {
572 pub fn new() -> Self {
574 Self {
575 namespace: Vec::new(),
576 registered: std::collections::HashSet::new(),
577 }
578 }
579 pub fn register(&mut self, fqn: impl Into<String>) {
581 self.registered.insert(fqn.into());
582 }
583 pub fn enter(&mut self, ns: impl Into<String>) {
585 self.namespace.push(ns.into());
586 }
587 pub fn exit(&mut self) {
589 self.namespace.pop();
590 }
591 pub fn current_ns(&self) -> String {
593 self.namespace.join(".")
594 }
595 pub fn resolve(&self, name: &str) -> String {
597 if self.namespace.is_empty() {
598 return name.to_string();
599 }
600 let fqn = format!("{}.{}", self.namespace.join("."), name);
601 if self.registered.contains(&fqn) {
602 fqn
603 } else {
604 name.to_string()
605 }
606 }
607}
608#[allow(dead_code)]
610pub struct RingBuffer<T> {
611 data: Vec<Option<T>>,
612 head: usize,
613 tail: usize,
614 count: usize,
615 capacity: usize,
616}
617#[allow(dead_code)]
618impl<T> RingBuffer<T> {
619 pub fn new(capacity: usize) -> Self {
621 let mut data = Vec::with_capacity(capacity);
622 for _ in 0..capacity {
623 data.push(None);
624 }
625 Self {
626 data,
627 head: 0,
628 tail: 0,
629 count: 0,
630 capacity,
631 }
632 }
633 pub fn push(&mut self, val: T) {
635 if self.count == self.capacity {
636 self.data[self.head] = Some(val);
637 self.head = (self.head + 1) % self.capacity;
638 self.tail = (self.tail + 1) % self.capacity;
639 } else {
640 self.data[self.tail] = Some(val);
641 self.tail = (self.tail + 1) % self.capacity;
642 self.count += 1;
643 }
644 }
645 pub fn pop(&mut self) -> Option<T> {
647 if self.count == 0 {
648 return None;
649 }
650 let val = self.data[self.head].take();
651 self.head = (self.head + 1) % self.capacity;
652 self.count -= 1;
653 val
654 }
655 pub fn len(&self) -> usize {
657 self.count
658 }
659 pub fn is_empty(&self) -> bool {
661 self.count == 0
662 }
663 pub fn is_full(&self) -> bool {
665 self.count == self.capacity
666 }
667}
668#[allow(dead_code)]
670pub struct BiMap<A: std::hash::Hash + Eq + Clone, B: std::hash::Hash + Eq + Clone> {
671 forward: std::collections::HashMap<A, B>,
672 backward: std::collections::HashMap<B, A>,
673}
674#[allow(dead_code)]
675impl<A: std::hash::Hash + Eq + Clone, B: std::hash::Hash + Eq + Clone> BiMap<A, B> {
676 pub fn new() -> Self {
678 Self {
679 forward: std::collections::HashMap::new(),
680 backward: std::collections::HashMap::new(),
681 }
682 }
683 pub fn insert(&mut self, a: A, b: B) {
685 self.forward.insert(a.clone(), b.clone());
686 self.backward.insert(b, a);
687 }
688 pub fn get_b(&self, a: &A) -> Option<&B> {
690 self.forward.get(a)
691 }
692 pub fn get_a(&self, b: &B) -> Option<&A> {
694 self.backward.get(b)
695 }
696 pub fn len(&self) -> usize {
698 self.forward.len()
699 }
700 pub fn is_empty(&self) -> bool {
702 self.forward.is_empty()
703 }
704}
705#[derive(Clone, PartialEq, Eq, Hash, Debug, Default)]
711pub enum Name {
712 #[default]
714 Anonymous,
715 Str(Box<Name>, String),
717 Num(Box<Name>, u64),
719}
720impl Name {
721 pub fn str(s: impl Into<String>) -> Self {
723 Name::Str(Box::new(Name::Anonymous), s.into())
724 }
725 pub fn append_str(self, s: impl Into<String>) -> Self {
727 Name::Str(Box::new(self), s.into())
728 }
729 pub fn append_num(self, n: u64) -> Self {
731 Name::Num(Box::new(self), n)
732 }
733 pub fn is_anonymous(&self) -> bool {
735 matches!(self, Name::Anonymous)
736 }
737 #[allow(clippy::should_implement_trait)]
742 pub fn from_str(s: &str) -> Self {
743 let mut parts = s.split('.');
744 let first = match parts.next() {
745 None | Some("") => return Name::Anonymous,
746 Some(f) => f,
747 };
748 let mut name = Name::str(first);
749 for part in parts {
750 if part.is_empty() {
751 continue;
752 }
753 if let Ok(n) = part.parse::<u64>() {
754 name = name.append_num(n);
755 } else {
756 name = name.append_str(part);
757 }
758 }
759 name
760 }
761 pub fn depth(&self) -> usize {
766 match self {
767 Name::Anonymous => 0,
768 Name::Str(parent, _) | Name::Num(parent, _) => 1 + parent.depth(),
769 }
770 }
771 pub fn last_str(&self) -> Option<&str> {
775 match self {
776 Name::Anonymous => None,
777 Name::Str(_, s) => Some(s.as_str()),
778 Name::Num(parent, _) => parent.last_str(),
779 }
780 }
781 pub fn last_num(&self) -> Option<u64> {
783 match self {
784 Name::Num(_, n) => Some(*n),
785 Name::Str(parent, _) => parent.last_num(),
786 Name::Anonymous => None,
787 }
788 }
789 pub fn root(&self) -> Option<&str> {
793 match self {
794 Name::Anonymous => None,
795 Name::Str(parent, s) => {
796 if parent.is_anonymous() {
797 Some(s.as_str())
798 } else {
799 parent.root()
800 }
801 }
802 Name::Num(parent, _) => parent.root(),
803 }
804 }
805 pub fn prefix(&self) -> Name {
807 match self {
808 Name::Anonymous => Name::Anonymous,
809 Name::Str(parent, _) | Name::Num(parent, _) => *parent.clone(),
810 }
811 }
812 pub fn has_prefix(&self, prefix: &Name) -> bool {
816 if self == prefix {
817 return false;
818 }
819 let mut current = self;
820 loop {
821 match current {
822 Name::Anonymous => return false,
823 Name::Str(parent, _) | Name::Num(parent, _) => {
824 if parent.as_ref() == prefix {
825 return true;
826 }
827 current = parent;
828 }
829 }
830 }
831 }
832 pub fn components(&self) -> Vec<String> {
836 let mut comps = Vec::new();
837 let mut current = self;
838 loop {
839 match current {
840 Name::Anonymous => break,
841 Name::Str(parent, s) => {
842 comps.push(s.clone());
843 current = parent;
844 }
845 Name::Num(parent, n) => {
846 comps.push(n.to_string());
847 current = parent;
848 }
849 }
850 }
851 comps.reverse();
852 comps
853 }
854 pub fn from_components(comps: &[String]) -> Self {
858 let mut name = Name::Anonymous;
859 for comp in comps {
860 if let Ok(n) = comp.parse::<u64>() {
861 name = name.append_num(n);
862 } else {
863 name = name.append_str(comp.as_str());
864 }
865 }
866 name
867 }
868 pub fn replace_last(self, new_last: impl Into<String>) -> Self {
872 match self {
873 Name::Anonymous => Name::str(new_last),
874 Name::Str(parent, _) => Name::Str(parent, new_last.into()),
875 Name::Num(parent, _) => Name::Str(parent, new_last.into()),
876 }
877 }
878 pub fn freshen(self, suffix: u64) -> Self {
882 self.append_num(suffix)
883 }
884 pub fn in_namespace(&self, ns: &Name) -> bool {
888 self.has_prefix(ns)
889 }
890 pub fn with_suffix(self, suffix: impl Into<String>) -> Self {
892 self.append_str(suffix)
893 }
894 pub fn to_ident_string(&self) -> String {
898 self.to_string()
899 .chars()
900 .map(|c| {
901 if c.is_alphanumeric() || c == '_' {
902 c
903 } else {
904 '_'
905 }
906 })
907 .collect()
908 }
909 pub fn prepend(self, prefix: Name) -> Self {
911 let comps = self.components();
912 let mut name = prefix;
913 for comp in comps {
914 if let Ok(n) = comp.parse::<u64>() {
915 name = name.append_num(n);
916 } else {
917 name = name.append_str(comp);
918 }
919 }
920 name
921 }
922 pub fn is_str_name(&self) -> bool {
924 matches!(self, Name::Str(_, _))
925 }
926 pub fn is_num_name(&self) -> bool {
928 matches!(self, Name::Num(_, _))
929 }
930}
931#[allow(dead_code)]
933pub struct NameMapping {
934 name_to_id: std::collections::HashMap<String, u32>,
935 id_to_name: std::collections::HashMap<u32, String>,
936 next_id: u32,
937}
938#[allow(dead_code)]
939impl NameMapping {
940 pub fn new() -> Self {
942 Self {
943 name_to_id: std::collections::HashMap::new(),
944 id_to_name: std::collections::HashMap::new(),
945 next_id: 0,
946 }
947 }
948 pub fn register(&mut self, name: impl Into<String>) -> u32 {
950 let name = name.into();
951 if let Some(&id) = self.name_to_id.get(&name) {
952 return id;
953 }
954 let id = self.next_id;
955 self.next_id += 1;
956 self.name_to_id.insert(name.clone(), id);
957 self.id_to_name.insert(id, name);
958 id
959 }
960 pub fn id_of(&self, name: &str) -> Option<u32> {
962 self.name_to_id.get(name).copied()
963 }
964 pub fn name_of(&self, id: u32) -> Option<&str> {
966 self.id_to_name.get(&id).map(|s| s.as_str())
967 }
968 pub fn len(&self) -> usize {
970 self.name_to_id.len()
971 }
972 pub fn is_empty(&self) -> bool {
974 self.name_to_id.is_empty()
975 }
976}
977#[allow(dead_code)]
979pub struct DiagMeta {
980 pub(super) entries: Vec<(String, String)>,
981}
982#[allow(dead_code)]
983impl DiagMeta {
984 pub fn new() -> Self {
986 Self {
987 entries: Vec::new(),
988 }
989 }
990 pub fn add(&mut self, key: impl Into<String>, val: impl Into<String>) {
992 self.entries.push((key.into(), val.into()));
993 }
994 pub fn get(&self, key: &str) -> Option<&str> {
996 self.entries
997 .iter()
998 .find(|(k, _)| k == key)
999 .map(|(_, v)| v.as_str())
1000 }
1001 pub fn len(&self) -> usize {
1003 self.entries.len()
1004 }
1005 pub fn is_empty(&self) -> bool {
1007 self.entries.is_empty()
1008 }
1009}
1010#[allow(dead_code)]
1012pub struct SparseBitSet {
1013 words: Vec<u64>,
1014}
1015#[allow(dead_code)]
1016impl SparseBitSet {
1017 pub fn new(capacity: usize) -> Self {
1019 let words = (capacity + 63) / 64;
1020 Self {
1021 words: vec![0u64; words],
1022 }
1023 }
1024 pub fn set(&mut self, i: usize) {
1026 let word = i / 64;
1027 let bit = i % 64;
1028 if word < self.words.len() {
1029 self.words[word] |= 1u64 << bit;
1030 }
1031 }
1032 pub fn clear(&mut self, i: usize) {
1034 let word = i / 64;
1035 let bit = i % 64;
1036 if word < self.words.len() {
1037 self.words[word] &= !(1u64 << bit);
1038 }
1039 }
1040 pub fn get(&self, i: usize) -> bool {
1042 let word = i / 64;
1043 let bit = i % 64;
1044 self.words.get(word).is_some_and(|w| w & (1u64 << bit) != 0)
1045 }
1046 pub fn count_ones(&self) -> u32 {
1048 self.words.iter().map(|w| w.count_ones()).sum()
1049 }
1050 pub fn union(&self, other: &SparseBitSet) -> SparseBitSet {
1052 let len = self.words.len().max(other.words.len());
1053 let mut result = SparseBitSet {
1054 words: vec![0u64; len],
1055 };
1056 for i in 0..self.words.len() {
1057 result.words[i] |= self.words[i];
1058 }
1059 for i in 0..other.words.len() {
1060 result.words[i] |= other.words[i];
1061 }
1062 result
1063 }
1064}
1065#[allow(dead_code)]
1067pub struct NameSetExt {
1068 inner: std::collections::HashSet<String>,
1069}
1070#[allow(dead_code)]
1071impl NameSetExt {
1072 pub fn new() -> Self {
1074 Self {
1075 inner: std::collections::HashSet::new(),
1076 }
1077 }
1078 pub fn insert(&mut self, name: impl Into<String>) {
1080 self.inner.insert(name.into());
1081 }
1082 pub fn contains(&self, name: &str) -> bool {
1084 self.inner.contains(name)
1085 }
1086 pub fn remove(&mut self, name: &str) {
1088 self.inner.remove(name);
1089 }
1090 pub fn len(&self) -> usize {
1092 self.inner.len()
1093 }
1094 pub fn is_empty(&self) -> bool {
1096 self.inner.is_empty()
1097 }
1098 pub fn union(&self, other: &NameSetExt) -> NameSetExt {
1100 let mut result = NameSetExt::new();
1101 for n in &self.inner {
1102 result.insert(n.as_str());
1103 }
1104 for n in &other.inner {
1105 result.insert(n.as_str());
1106 }
1107 result
1108 }
1109 pub fn intersect(&self, other: &NameSetExt) -> NameSetExt {
1111 let mut result = NameSetExt::new();
1112 for n in &self.inner {
1113 if other.contains(n) {
1114 result.insert(n.as_str());
1115 }
1116 }
1117 result
1118 }
1119}
1120#[allow(dead_code)]
1122pub struct ScopeStack {
1123 names: Vec<String>,
1124}
1125#[allow(dead_code)]
1126impl ScopeStack {
1127 pub fn new() -> Self {
1129 Self { names: Vec::new() }
1130 }
1131 pub fn push(&mut self, name: impl Into<String>) {
1133 self.names.push(name.into());
1134 }
1135 pub fn pop(&mut self) -> Option<String> {
1137 self.names.pop()
1138 }
1139 pub fn current(&self) -> Option<&str> {
1141 self.names.last().map(|s| s.as_str())
1142 }
1143 pub fn depth(&self) -> usize {
1145 self.names.len()
1146 }
1147 pub fn is_empty(&self) -> bool {
1149 self.names.is_empty()
1150 }
1151 pub fn path(&self) -> String {
1153 self.names.join(".")
1154 }
1155}
1156#[allow(dead_code)]
1158pub struct NameTrieExt {
1159 children: std::collections::HashMap<char, NameTrieExt>,
1160 terminal: bool,
1161 name: Option<String>,
1162}
1163#[allow(dead_code)]
1164impl NameTrieExt {
1165 pub fn new() -> Self {
1167 Self {
1168 children: std::collections::HashMap::new(),
1169 terminal: false,
1170 name: None,
1171 }
1172 }
1173 pub fn insert(&mut self, name: &str) {
1175 let mut node = self;
1176 for c in name.chars() {
1177 node = node.children.entry(c).or_default();
1178 }
1179 node.terminal = true;
1180 node.name = Some(name.to_string());
1181 }
1182 pub fn contains(&self, name: &str) -> bool {
1184 let mut node = self;
1185 for c in name.chars() {
1186 match node.children.get(&c) {
1187 Some(n) => node = n,
1188 None => return false,
1189 }
1190 }
1191 node.terminal
1192 }
1193 pub fn with_prefix(&self, prefix: &str) -> Vec<String> {
1195 let mut node = self;
1196 for c in prefix.chars() {
1197 match node.children.get(&c) {
1198 Some(n) => node = n,
1199 None => return Vec::new(),
1200 }
1201 }
1202 let mut results = Vec::new();
1203 node.collect_all(&mut results);
1204 results
1205 }
1206 fn collect_all(&self, out: &mut Vec<String>) {
1207 if let Some(ref n) = self.name {
1208 out.push(n.clone());
1209 }
1210 for child in self.children.values() {
1211 let c: &NameTrieExt = child;
1212 c.collect_all(out);
1213 }
1214 }
1215}
1216#[allow(dead_code)]
1218pub struct EventCounter {
1219 counts: std::collections::HashMap<String, u64>,
1220}
1221#[allow(dead_code)]
1222impl EventCounter {
1223 pub fn new() -> Self {
1225 Self {
1226 counts: std::collections::HashMap::new(),
1227 }
1228 }
1229 pub fn inc(&mut self, event: &str) {
1231 *self.counts.entry(event.to_string()).or_insert(0) += 1;
1232 }
1233 pub fn add(&mut self, event: &str, n: u64) {
1235 *self.counts.entry(event.to_string()).or_insert(0) += n;
1236 }
1237 pub fn get(&self, event: &str) -> u64 {
1239 self.counts.get(event).copied().unwrap_or(0)
1240 }
1241 pub fn total(&self) -> u64 {
1243 self.counts.values().sum()
1244 }
1245 pub fn reset(&mut self) {
1247 self.counts.clear();
1248 }
1249 pub fn event_names(&self) -> Vec<&str> {
1251 self.counts.keys().map(|s| s.as_str()).collect()
1252 }
1253}
1254#[derive(Debug, Clone, Default)]
1258pub struct NameSet {
1259 pub(super) inner: HashSet<Name>,
1260}
1261impl NameSet {
1262 pub fn new() -> Self {
1264 Self {
1265 inner: HashSet::new(),
1266 }
1267 }
1268 pub fn insert(&mut self, name: Name) -> bool {
1270 self.inner.insert(name)
1271 }
1272 pub fn remove(&mut self, name: &Name) -> bool {
1274 self.inner.remove(name)
1275 }
1276 pub fn contains(&self, name: &Name) -> bool {
1278 self.inner.contains(name)
1279 }
1280 pub fn len(&self) -> usize {
1282 self.inner.len()
1283 }
1284 pub fn is_empty(&self) -> bool {
1286 self.inner.is_empty()
1287 }
1288 pub fn iter(&self) -> impl Iterator<Item = &Name> {
1290 self.inner.iter()
1291 }
1292 pub fn union(&self, other: &NameSet) -> NameSet {
1294 NameSet {
1295 inner: self.inner.union(&other.inner).cloned().collect(),
1296 }
1297 }
1298 pub fn intersection(&self, other: &NameSet) -> NameSet {
1300 NameSet {
1301 inner: self.inner.intersection(&other.inner).cloned().collect(),
1302 }
1303 }
1304 pub fn difference(&self, other: &NameSet) -> NameSet {
1306 NameSet {
1307 inner: self.inner.difference(&other.inner).cloned().collect(),
1308 }
1309 }
1310 pub fn in_namespace(&self, ns: &Name) -> NameSet {
1312 NameSet {
1313 inner: self
1314 .inner
1315 .iter()
1316 .filter(|n| n.has_prefix(ns))
1317 .cloned()
1318 .collect(),
1319 }
1320 }
1321 pub fn to_sorted_vec(&self) -> Vec<Name> {
1323 let mut v: Vec<Name> = self.inner.iter().cloned().collect();
1324 v.sort();
1325 v
1326 }
1327}
1328#[allow(dead_code)]
1330pub struct AnnotationTable {
1331 map: std::collections::HashMap<String, Vec<String>>,
1332}
1333#[allow(dead_code)]
1334impl AnnotationTable {
1335 pub fn new() -> Self {
1337 Self {
1338 map: std::collections::HashMap::new(),
1339 }
1340 }
1341 pub fn annotate(&mut self, key: impl Into<String>, val: impl Into<String>) {
1343 self.map.entry(key.into()).or_default().push(val.into());
1344 }
1345 pub fn get_all(&self, key: &str) -> &[String] {
1347 self.map.get(key).map(|v| v.as_slice()).unwrap_or(&[])
1348 }
1349 pub fn num_keys(&self) -> usize {
1351 self.map.len()
1352 }
1353 pub fn has(&self, key: &str) -> bool {
1355 self.map.contains_key(key)
1356 }
1357}
1358#[allow(dead_code)]
1360pub struct SimpleLruCache<K: std::hash::Hash + Eq + Clone, V: Clone> {
1361 capacity: usize,
1362 map: std::collections::HashMap<K, usize>,
1363 keys: Vec<K>,
1364 vals: Vec<V>,
1365 order: Vec<usize>,
1366}
1367#[allow(dead_code)]
1368impl<K: std::hash::Hash + Eq + Clone, V: Clone> SimpleLruCache<K, V> {
1369 pub fn new(capacity: usize) -> Self {
1371 assert!(capacity > 0);
1372 Self {
1373 capacity,
1374 map: std::collections::HashMap::new(),
1375 keys: Vec::new(),
1376 vals: Vec::new(),
1377 order: Vec::new(),
1378 }
1379 }
1380 pub fn put(&mut self, key: K, val: V) {
1382 if let Some(&idx) = self.map.get(&key) {
1383 self.vals[idx] = val;
1384 self.order.retain(|&x| x != idx);
1385 self.order.insert(0, idx);
1386 return;
1387 }
1388 if self.keys.len() >= self.capacity {
1389 let evict_idx = *self
1390 .order
1391 .last()
1392 .expect("order list must be non-empty before eviction");
1393 self.map.remove(&self.keys[evict_idx]);
1394 self.order.pop();
1395 self.keys[evict_idx] = key.clone();
1396 self.vals[evict_idx] = val;
1397 self.map.insert(key, evict_idx);
1398 self.order.insert(0, evict_idx);
1399 } else {
1400 let idx = self.keys.len();
1401 self.keys.push(key.clone());
1402 self.vals.push(val);
1403 self.map.insert(key, idx);
1404 self.order.insert(0, idx);
1405 }
1406 }
1407 pub fn get(&mut self, key: &K) -> Option<&V> {
1409 let idx = *self.map.get(key)?;
1410 self.order.retain(|&x| x != idx);
1411 self.order.insert(0, idx);
1412 Some(&self.vals[idx])
1413 }
1414 pub fn len(&self) -> usize {
1416 self.keys.len()
1417 }
1418 pub fn is_empty(&self) -> bool {
1420 self.keys.is_empty()
1421 }
1422}
1423#[allow(dead_code)]
1425pub struct Slot<T> {
1426 inner: Option<T>,
1427}
1428#[allow(dead_code)]
1429impl<T> Slot<T> {
1430 pub fn empty() -> Self {
1432 Self { inner: None }
1433 }
1434 pub fn fill(&mut self, val: T) {
1436 assert!(self.inner.is_none(), "Slot: already filled");
1437 self.inner = Some(val);
1438 }
1439 pub fn get(&self) -> Option<&T> {
1441 self.inner.as_ref()
1442 }
1443 pub fn is_filled(&self) -> bool {
1445 self.inner.is_some()
1446 }
1447 pub fn take(&mut self) -> Option<T> {
1449 self.inner.take()
1450 }
1451 pub fn get_or_fill_with(&mut self, f: impl FnOnce() -> T) -> &T {
1453 if self.inner.is_none() {
1454 self.inner = Some(f());
1455 }
1456 self.inner
1457 .as_ref()
1458 .expect("inner value must be initialized before access")
1459 }
1460}
1461#[allow(dead_code)]
1463pub struct NameGeneratorExt {
1464 prefix: String,
1465 counter: u64,
1466}
1467#[allow(dead_code)]
1468impl NameGeneratorExt {
1469 pub fn new(prefix: impl Into<String>) -> Self {
1471 Self {
1472 prefix: prefix.into(),
1473 counter: 0,
1474 }
1475 }
1476 #[allow(clippy::should_implement_trait)]
1478 pub fn next(&mut self) -> String {
1479 let n = self.counter;
1480 self.counter += 1;
1481 format!("{}{}", self.prefix, n)
1482 }
1483 pub fn count(&self) -> u64 {
1485 self.counter
1486 }
1487 pub fn reset(&mut self) {
1489 self.counter = 0;
1490 }
1491}
1492#[allow(dead_code)]
1494#[allow(missing_docs)]
1495pub struct StatCache<K: std::hash::Hash + Eq + Clone, V: Clone> {
1496 pub inner: SimpleLruCache<K, V>,
1498 pub hits: u64,
1500 pub misses: u64,
1502}
1503#[allow(dead_code)]
1504impl<K: std::hash::Hash + Eq + Clone, V: Clone> StatCache<K, V> {
1505 pub fn new(capacity: usize) -> Self {
1507 Self {
1508 inner: SimpleLruCache::new(capacity),
1509 hits: 0,
1510 misses: 0,
1511 }
1512 }
1513 pub fn get(&mut self, key: &K) -> Option<&V> {
1515 let result = self.inner.get(key);
1516 if result.is_some() {
1517 self.hits += 1;
1518 } else {
1519 self.misses += 1;
1520 }
1521 None
1522 }
1523 pub fn put(&mut self, key: K, val: V) {
1525 self.inner.put(key, val);
1526 }
1527 pub fn hit_rate(&self) -> f64 {
1529 let total = self.hits + self.misses;
1530 if total == 0 {
1531 return 0.0;
1532 }
1533 self.hits as f64 / total as f64
1534 }
1535}
1536#[allow(dead_code)]
1538pub struct FrequencyTable<T: std::hash::Hash + Eq + Clone> {
1539 counts: std::collections::HashMap<T, u64>,
1540}
1541#[allow(dead_code)]
1542impl<T: std::hash::Hash + Eq + Clone> FrequencyTable<T> {
1543 pub fn new() -> Self {
1545 Self {
1546 counts: std::collections::HashMap::new(),
1547 }
1548 }
1549 pub fn record(&mut self, item: T) {
1551 *self.counts.entry(item).or_insert(0) += 1;
1552 }
1553 pub fn freq(&self, item: &T) -> u64 {
1555 self.counts.get(item).copied().unwrap_or(0)
1556 }
1557 pub fn most_frequent(&self) -> Option<(&T, u64)> {
1559 self.counts
1560 .iter()
1561 .max_by_key(|(_, &v)| v)
1562 .map(|(k, &v)| (k, v))
1563 }
1564 pub fn total(&self) -> u64 {
1566 self.counts.values().sum()
1567 }
1568 pub fn distinct(&self) -> usize {
1570 self.counts.len()
1571 }
1572}
1573#[allow(dead_code)]
1575pub struct IdDispenser<T> {
1576 next: u32,
1577 _phantom: std::marker::PhantomData<T>,
1578}
1579#[allow(dead_code)]
1580impl<T> IdDispenser<T> {
1581 pub fn new() -> Self {
1583 Self {
1584 next: 0,
1585 _phantom: std::marker::PhantomData,
1586 }
1587 }
1588 #[allow(clippy::should_implement_trait)]
1590 pub fn next(&mut self) -> TypedId<T> {
1591 let id = TypedId::new(self.next);
1592 self.next += 1;
1593 id
1594 }
1595 pub fn count(&self) -> u32 {
1597 self.next
1598 }
1599}
1600#[allow(dead_code)]
1602#[allow(missing_docs)]
1603pub struct QualifiedNameExt {
1604 pub parts: Vec<String>,
1606}
1607#[allow(dead_code)]
1608impl QualifiedNameExt {
1609 pub fn from_dot_str(s: &str) -> Self {
1611 s.parse().unwrap_or_else(|_| unreachable!())
1612 }
1613 pub fn simple(name: impl Into<String>) -> Self {
1615 Self {
1616 parts: vec![name.into()],
1617 }
1618 }
1619 pub fn unqualified(&self) -> &str {
1621 self.parts.last().map(|s| s.as_str()).unwrap_or("")
1622 }
1623 pub fn namespace(&self) -> Option<QualifiedNameExt> {
1625 if self.parts.len() <= 1 {
1626 return None;
1627 }
1628 let parts = self.parts[..self.parts.len() - 1].to_vec();
1629 Some(QualifiedNameExt { parts })
1630 }
1631 pub fn is_sub_of(&self, other: &QualifiedNameExt) -> bool {
1633 self.parts.starts_with(&other.parts)
1634 }
1635 pub fn depth(&self) -> usize {
1637 self.parts.len()
1638 }
1639}
1640#[allow(dead_code)]
1642pub struct MemoSlot<T: Clone> {
1643 cached: Option<T>,
1644}
1645#[allow(dead_code)]
1646impl<T: Clone> MemoSlot<T> {
1647 pub fn new() -> Self {
1649 Self { cached: None }
1650 }
1651 pub fn get_or_compute(&mut self, f: impl FnOnce() -> T) -> &T {
1653 if self.cached.is_none() {
1654 self.cached = Some(f());
1655 }
1656 self.cached
1657 .as_ref()
1658 .expect("cached value must be initialized before access")
1659 }
1660 pub fn invalidate(&mut self) {
1662 self.cached = None;
1663 }
1664 pub fn is_cached(&self) -> bool {
1666 self.cached.is_some()
1667 }
1668}