1use std::collections::{HashMap, HashSet, VecDeque};
6use std::rc::Rc;
7
8#[allow(dead_code)]
10pub struct LoopClock {
11 start: crate::wall_clock::Instant,
12 iters: u64,
13}
14#[allow(dead_code)]
15impl LoopClock {
16 pub fn start() -> Self {
18 Self {
19 start: crate::wall_clock::Instant::now(),
20 iters: 0,
21 }
22 }
23 pub fn tick(&mut self) {
25 self.iters += 1;
26 }
27 pub fn elapsed_us(&self) -> f64 {
29 self.start.elapsed().as_secs_f64() * 1e6
30 }
31 pub fn avg_us_per_iter(&self) -> f64 {
33 if self.iters == 0 {
34 return 0.0;
35 }
36 self.elapsed_us() / self.iters as f64
37 }
38 pub fn iters(&self) -> u64 {
40 self.iters
41 }
42}
43#[allow(dead_code)]
45#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
46pub struct Timestamp(u64);
47#[allow(dead_code)]
48impl Timestamp {
49 pub const fn from_us(us: u64) -> Self {
51 Self(us)
52 }
53 pub fn as_us(self) -> u64 {
55 self.0
56 }
57 pub fn elapsed_since(self, earlier: Timestamp) -> u64 {
59 self.0.saturating_sub(earlier.0)
60 }
61}
62#[derive(Debug, Clone)]
66pub struct NameGenerator {
67 base: Name,
68 counter: u64,
69}
70impl NameGenerator {
71 pub fn new(base: Name) -> Self {
73 Self { base, counter: 0 }
74 }
75 pub fn with_base(s: impl Into<String>) -> Self {
77 Self::new(Name::str(s))
78 }
79 #[allow(clippy::should_implement_trait)]
81 pub fn next(&mut self) -> Name {
82 let n = self.base.clone().append_num(self.counter);
83 self.counter += 1;
84 n
85 }
86 pub fn peek(&self) -> Name {
88 self.base.clone().append_num(self.counter)
89 }
90 pub fn reset(&mut self) {
92 self.counter = 0;
93 }
94 pub fn count(&self) -> u64 {
96 self.counter
97 }
98}
99#[allow(dead_code)]
101#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
102pub struct TypedId<T> {
103 pub(super) id: u32,
104 _phantom: std::marker::PhantomData<T>,
105}
106#[allow(dead_code)]
107impl<T> TypedId<T> {
108 pub const fn new(id: u32) -> Self {
110 Self {
111 id,
112 _phantom: std::marker::PhantomData,
113 }
114 }
115 pub fn raw(&self) -> u32 {
117 self.id
118 }
119}
120#[allow(dead_code)]
122pub struct StringInterner {
123 strings: Vec<String>,
124 map: std::collections::HashMap<String, u32>,
125}
126#[allow(dead_code)]
127impl StringInterner {
128 pub fn new() -> Self {
130 Self {
131 strings: Vec::new(),
132 map: std::collections::HashMap::new(),
133 }
134 }
135 pub fn intern(&mut self, s: &str) -> u32 {
137 if let Some(&id) = self.map.get(s) {
138 return id;
139 }
140 let id = self.strings.len() as u32;
141 self.strings.push(s.to_string());
142 self.map.insert(s.to_string(), id);
143 id
144 }
145 pub fn get(&self, id: u32) -> Option<&str> {
147 self.strings.get(id as usize).map(|s| s.as_str())
148 }
149 pub fn len(&self) -> usize {
151 self.strings.len()
152 }
153 pub fn is_empty(&self) -> bool {
155 self.strings.is_empty()
156 }
157}
158#[derive(Debug, Clone)]
163pub struct NameTrie<V> {
164 pub(super) value: Option<V>,
166 pub(super) string_children: Vec<(String, NameTrie<V>)>,
168 pub(super) num_children: Vec<(u64, NameTrie<V>)>,
170}
171impl<V: Clone> NameTrie<V> {
172 pub fn new() -> Self {
174 Self::default()
175 }
176 pub fn insert(&mut self, name: &Name, value: V) {
178 match name.view() {
179 NameView::Anonymous => {
180 self.value = Some(value);
181 }
182 NameView::Str(parent, s) => {
183 let child = if let Some(idx) = self
184 .string_children
185 .iter()
186 .position(|(k, _)| k.as_str() == s)
187 {
188 &mut self.string_children[idx].1
189 } else {
190 self.string_children.push((s.to_string(), NameTrie::new()));
191 let last = self.string_children.len() - 1;
192 &mut self.string_children[last].1
193 };
194 child.insert(parent, value);
195 }
196 NameView::Num(parent, n) => {
197 let child = if let Some(idx) = self.num_children.iter().position(|(k, _)| *k == n) {
198 &mut self.num_children[idx].1
199 } else {
200 self.num_children.push((n, NameTrie::new()));
201 let last = self.num_children.len() - 1;
202 &mut self.num_children[last].1
203 };
204 child.insert(parent, value);
205 }
206 }
207 }
208 pub fn lookup(&self, name: &Name) -> Option<&V> {
210 match name.view() {
211 NameView::Anonymous => self.value.as_ref(),
212 NameView::Str(parent, s) => {
213 let child = self
214 .string_children
215 .iter()
216 .find(|(k, _)| k.as_str() == s)
217 .map(|(_, v)| v)?;
218 child.lookup(parent)
219 }
220 NameView::Num(parent, n) => {
221 let child = self
222 .num_children
223 .iter()
224 .find(|(k, _)| *k == n)
225 .map(|(_, v)| v)?;
226 child.lookup(parent)
227 }
228 }
229 }
230 pub fn contains(&self, name: &Name) -> bool {
232 self.lookup(name).is_some()
233 }
234 pub fn count(&self) -> usize {
236 let self_count = if self.value.is_some() { 1 } else { 0 };
237 let str_count: usize = self.string_children.iter().map(|(_, c)| c.count()).sum();
238 let num_count: usize = self.num_children.iter().map(|(_, c)| c.count()).sum();
239 self_count + str_count + num_count
240 }
241 pub fn to_vec(&self) -> Vec<(Name, V)> {
243 let mut result = Vec::new();
244 self.collect_all(Name::anonymous(), &mut result);
245 result
246 }
247 fn collect_all(&self, prefix: Name, result: &mut Vec<(Name, V)>) {
248 if let Some(v) = &self.value {
249 result.push((prefix.clone(), v.clone()));
250 }
251 for (s, child) in &self.string_children {
252 let name = prefix.clone().append_str(s.as_str());
253 child.collect_all(name, result);
254 }
255 for (n, child) in &self.num_children {
256 let name = prefix.clone().append_num(*n);
257 child.collect_all(name, result);
258 }
259 }
260}
261#[allow(dead_code)]
263pub struct WorkQueue<T> {
264 items: std::collections::VecDeque<T>,
265}
266#[allow(dead_code)]
267impl<T> WorkQueue<T> {
268 pub fn new() -> Self {
270 Self {
271 items: std::collections::VecDeque::new(),
272 }
273 }
274 pub fn enqueue(&mut self, item: T) {
276 self.items.push_back(item);
277 }
278 pub fn dequeue(&mut self) -> Option<T> {
280 self.items.pop_front()
281 }
282 pub fn is_empty(&self) -> bool {
284 self.items.is_empty()
285 }
286 pub fn len(&self) -> usize {
288 self.items.len()
289 }
290}
291#[allow(dead_code)]
293#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
294pub struct SeqNum(u64);
295#[allow(dead_code)]
296impl SeqNum {
297 pub const ZERO: SeqNum = SeqNum(0);
299 pub fn next(self) -> SeqNum {
301 SeqNum(self.0 + 1)
302 }
303 pub fn value(self) -> u64 {
305 self.0
306 }
307}
308#[allow(dead_code)]
310pub struct IntervalSet {
311 intervals: Vec<(i64, i64)>,
312}
313#[allow(dead_code)]
314impl IntervalSet {
315 pub fn new() -> Self {
317 Self {
318 intervals: Vec::new(),
319 }
320 }
321 pub fn add(&mut self, lo: i64, hi: i64) {
323 if lo > hi {
324 return;
325 }
326 let mut new_lo = lo;
327 let mut new_hi = hi;
328 let mut i = 0;
329 while i < self.intervals.len() {
330 let (il, ih) = self.intervals[i];
331 if ih < new_lo - 1 {
332 i += 1;
333 continue;
334 }
335 if il > new_hi + 1 {
336 break;
337 }
338 new_lo = new_lo.min(il);
339 new_hi = new_hi.max(ih);
340 self.intervals.remove(i);
341 }
342 self.intervals.insert(i, (new_lo, new_hi));
343 }
344 pub fn contains(&self, x: i64) -> bool {
346 self.intervals.iter().any(|&(lo, hi)| x >= lo && x <= hi)
347 }
348 pub fn num_intervals(&self) -> usize {
350 self.intervals.len()
351 }
352 pub fn cardinality(&self) -> i64 {
354 self.intervals.iter().map(|&(lo, hi)| hi - lo + 1).sum()
355 }
356}
357#[derive(Debug, Clone, Default)]
361pub struct NameMap<V> {
362 pub(super) inner: HashMap<Name, V>,
363}
364impl<V> NameMap<V> {
365 pub fn new() -> Self {
367 Self {
368 inner: HashMap::new(),
369 }
370 }
371 pub fn with_capacity(cap: usize) -> Self {
373 Self {
374 inner: HashMap::with_capacity(cap),
375 }
376 }
377 pub fn insert(&mut self, name: Name, value: V) -> Option<V> {
379 self.inner.insert(name, value)
380 }
381 pub fn get(&self, name: &Name) -> Option<&V> {
383 self.inner.get(name)
384 }
385 pub fn get_mut(&mut self, name: &Name) -> Option<&mut V> {
387 self.inner.get_mut(name)
388 }
389 pub fn remove(&mut self, name: &Name) -> Option<V> {
391 self.inner.remove(name)
392 }
393 pub fn contains_key(&self, name: &Name) -> bool {
395 self.inner.contains_key(name)
396 }
397 pub fn len(&self) -> usize {
399 self.inner.len()
400 }
401 pub fn is_empty(&self) -> bool {
403 self.inner.is_empty()
404 }
405 pub fn iter(&self) -> impl Iterator<Item = (&Name, &V)> {
407 self.inner.iter()
408 }
409 pub fn keys(&self) -> impl Iterator<Item = &Name> {
411 self.inner.keys()
412 }
413 pub fn values(&self) -> impl Iterator<Item = &V> {
415 self.inner.values()
416 }
417 pub fn filter_by_namespace(&self, ns: &Name) -> Vec<(&Name, &V)> {
419 self.inner
420 .iter()
421 .filter(|(n, _)| n.has_prefix(ns))
422 .collect()
423 }
424 pub fn sorted_names(&self) -> Vec<Name> {
426 let mut names: Vec<Name> = self.inner.keys().cloned().collect();
427 names.sort();
428 names
429 }
430 pub fn entry_or_insert(&mut self, name: Name, value: V) -> &mut V {
432 self.inner.entry(name).or_insert(value)
433 }
434}
435#[allow(dead_code)]
437#[allow(missing_docs)]
438pub struct BeforeAfter<T> {
439 pub before: T,
441 pub after: T,
443}
444#[allow(dead_code)]
445impl<T: PartialEq> BeforeAfter<T> {
446 pub fn new(before: T, after: T) -> Self {
448 Self { before, after }
449 }
450 pub fn unchanged(&self) -> bool {
452 self.before == self.after
453 }
454}
455#[allow(dead_code)]
457pub struct WorkStack<T> {
458 items: Vec<T>,
459}
460#[allow(dead_code)]
461impl<T> WorkStack<T> {
462 pub fn new() -> Self {
464 Self { items: Vec::new() }
465 }
466 pub fn push(&mut self, item: T) {
468 self.items.push(item);
469 }
470 pub fn pop(&mut self) -> Option<T> {
472 self.items.pop()
473 }
474 pub fn is_empty(&self) -> bool {
476 self.items.is_empty()
477 }
478 pub fn len(&self) -> usize {
480 self.items.len()
481 }
482}
483#[allow(dead_code)]
485#[derive(Clone, Copy, Debug, PartialEq, Eq)]
486pub struct Generation(u32);
487#[allow(dead_code)]
488impl Generation {
489 pub const INITIAL: Generation = Generation(0);
491 pub fn advance(self) -> Generation {
493 Generation(self.0 + 1)
494 }
495 pub fn number(self) -> u32 {
497 self.0
498 }
499}
500#[derive(Debug, Clone, PartialEq, Eq)]
504pub struct QualifiedName {
505 pub canonical: Name,
507 pub alias: Option<Name>,
509}
510impl QualifiedName {
511 pub fn new(canonical: Name) -> Self {
513 Self {
514 canonical,
515 alias: None,
516 }
517 }
518 pub fn with_alias(canonical: Name, alias: Name) -> Self {
520 Self {
521 canonical,
522 alias: Some(alias),
523 }
524 }
525 pub fn preferred(&self) -> &Name {
527 self.alias.as_ref().unwrap_or(&self.canonical)
528 }
529}
530#[allow(dead_code)]
532pub struct NamePool {
533 names: Vec<String>,
534 index: std::collections::HashMap<String, usize>,
535}
536#[allow(dead_code)]
537impl NamePool {
538 pub fn new() -> Self {
540 Self {
541 names: Vec::new(),
542 index: std::collections::HashMap::new(),
543 }
544 }
545 pub fn intern(&mut self, name: &str) -> usize {
547 if let Some(&id) = self.index.get(name) {
548 return id;
549 }
550 let id = self.names.len();
551 self.names.push(name.to_string());
552 self.index.insert(name.to_string(), id);
553 id
554 }
555 pub fn get(&self, id: usize) -> Option<&str> {
557 self.names.get(id).map(|s| s.as_str())
558 }
559 pub fn len(&self) -> usize {
561 self.names.len()
562 }
563 pub fn is_empty(&self) -> bool {
565 self.names.is_empty()
566 }
567}
568#[allow(dead_code)]
570pub struct NameResolver {
571 namespace: Vec<String>,
572 registered: std::collections::HashSet<String>,
573}
574#[allow(dead_code)]
575impl NameResolver {
576 pub fn new() -> Self {
578 Self {
579 namespace: Vec::new(),
580 registered: std::collections::HashSet::new(),
581 }
582 }
583 pub fn register(&mut self, fqn: impl Into<String>) {
585 self.registered.insert(fqn.into());
586 }
587 pub fn enter(&mut self, ns: impl Into<String>) {
589 self.namespace.push(ns.into());
590 }
591 pub fn exit(&mut self) {
593 self.namespace.pop();
594 }
595 pub fn current_ns(&self) -> String {
597 self.namespace.join(".")
598 }
599 pub fn resolve(&self, name: &str) -> String {
601 if self.namespace.is_empty() {
602 return name.to_string();
603 }
604 let fqn = format!("{}.{}", self.namespace.join("."), name);
605 if self.registered.contains(&fqn) {
606 fqn
607 } else {
608 name.to_string()
609 }
610 }
611}
612#[allow(dead_code)]
614pub struct RingBuffer<T> {
615 data: Vec<Option<T>>,
616 head: usize,
617 tail: usize,
618 count: usize,
619 capacity: usize,
620}
621#[allow(dead_code)]
622impl<T> RingBuffer<T> {
623 pub fn new(capacity: usize) -> Self {
625 let mut data = Vec::with_capacity(capacity);
626 for _ in 0..capacity {
627 data.push(None);
628 }
629 Self {
630 data,
631 head: 0,
632 tail: 0,
633 count: 0,
634 capacity,
635 }
636 }
637 pub fn push(&mut self, val: T) {
639 if self.count == self.capacity {
640 self.data[self.head] = Some(val);
641 self.head = (self.head + 1) % self.capacity;
642 self.tail = (self.tail + 1) % self.capacity;
643 } else {
644 self.data[self.tail] = Some(val);
645 self.tail = (self.tail + 1) % self.capacity;
646 self.count += 1;
647 }
648 }
649 pub fn pop(&mut self) -> Option<T> {
651 if self.count == 0 {
652 return None;
653 }
654 let val = self.data[self.head].take();
655 self.head = (self.head + 1) % self.capacity;
656 self.count -= 1;
657 val
658 }
659 pub fn len(&self) -> usize {
661 self.count
662 }
663 pub fn is_empty(&self) -> bool {
665 self.count == 0
666 }
667 pub fn is_full(&self) -> bool {
669 self.count == self.capacity
670 }
671}
672#[allow(dead_code)]
674pub struct BiMap<A: std::hash::Hash + Eq + Clone, B: std::hash::Hash + Eq + Clone> {
675 forward: std::collections::HashMap<A, B>,
676 backward: std::collections::HashMap<B, A>,
677}
678#[allow(dead_code)]
679impl<A: std::hash::Hash + Eq + Clone, B: std::hash::Hash + Eq + Clone> BiMap<A, B> {
680 pub fn new() -> Self {
682 Self {
683 forward: std::collections::HashMap::new(),
684 backward: std::collections::HashMap::new(),
685 }
686 }
687 pub fn insert(&mut self, a: A, b: B) {
689 self.forward.insert(a.clone(), b.clone());
690 self.backward.insert(b, a);
691 }
692 pub fn get_b(&self, a: &A) -> Option<&B> {
694 self.forward.get(a)
695 }
696 pub fn get_a(&self, b: &B) -> Option<&A> {
698 self.backward.get(b)
699 }
700 pub fn len(&self) -> usize {
702 self.forward.len()
703 }
704 pub fn is_empty(&self) -> bool {
706 self.forward.is_empty()
707 }
708}
709#[derive(Clone)]
738pub struct Name(Rc<NameCell>);
739
740struct NameCell {
747 hash: u64,
748 kind: NameKind,
749}
750
751impl PartialEq for Name {
752 #[inline]
753 fn eq(&self, other: &Name) -> bool {
754 Rc::ptr_eq(&self.0, &other.0)
755 || (self.0.hash == other.0.hash && self.0.kind == other.0.kind)
756 }
757}
758impl Eq for Name {}
759impl std::hash::Hash for Name {
760 #[inline]
763 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
764 self.0.kind.hash(state);
765 }
766}
767impl std::fmt::Debug for Name {
768 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
772 f.debug_tuple("Name").field(&self.0.kind).finish()
773 }
774}
775impl Default for Name {
776 fn default() -> Self {
778 Name::anonymous()
779 }
780}
781
782#[derive(PartialEq, Eq, Hash, Debug, Default)]
785enum NameKind {
786 #[default]
788 Anonymous,
789 Str(Name, String),
791 Num(Name, u64),
793}
794
795pub enum NameView<'a> {
799 Anonymous,
801 Str(&'a Name, &'a str),
803 Num(&'a Name, u64),
805}
806
807impl Name {
808 #[inline]
810 pub fn view(&self) -> NameView<'_> {
811 match &self.0.kind {
812 NameKind::Anonymous => NameView::Anonymous,
813 NameKind::Str(parent, s) => NameView::Str(parent, s.as_str()),
814 NameKind::Num(parent, n) => NameView::Num(parent, *n),
815 }
816 }
817 #[inline]
820 #[must_use]
821 pub(crate) fn structural_hash(&self) -> u64 {
822 self.0.hash
823 }
824 #[inline]
826 pub fn anonymous() -> Name {
827 Name(Rc::new(NameCell {
828 hash: crate::structural_hash::NAME_ANONYMOUS,
829 kind: NameKind::Anonymous,
830 }))
831 }
832 #[inline]
835 pub fn mk_str(parent: Name, s: impl Into<String>) -> Name {
836 use crate::structural_hash::{mix, mix_bytes, NAME_STR};
837 let s: String = s.into();
838 let hash = mix_bytes(mix(NAME_STR, parent.0.hash), s.as_bytes());
839 Name(Rc::new(NameCell {
840 hash,
841 kind: NameKind::Str(parent, s),
842 }))
843 }
844 #[inline]
847 pub fn mk_num(parent: Name, n: u64) -> Name {
848 use crate::structural_hash::{mix, NAME_NUM};
849 let hash = mix(mix(NAME_NUM, parent.0.hash), n);
850 Name(Rc::new(NameCell {
851 hash,
852 kind: NameKind::Num(parent, n),
853 }))
854 }
855 pub fn str(s: impl Into<String>) -> Self {
857 Name::mk_str(Name::anonymous(), s)
858 }
859 pub fn append_str(self, s: impl Into<String>) -> Self {
861 Name::mk_str(self, s)
862 }
863 pub fn append_num(self, n: u64) -> Self {
865 Name::mk_num(self, n)
866 }
867 pub fn is_anonymous(&self) -> bool {
869 matches!(&self.0.kind, NameKind::Anonymous)
870 }
871 #[allow(clippy::should_implement_trait)]
876 pub fn from_str(s: &str) -> Self {
877 let mut parts = s.split('.');
878 let first = match parts.next() {
879 None | Some("") => return Name::anonymous(),
880 Some(f) => f,
881 };
882 let mut name = Name::str(first);
883 for part in parts {
884 if part.is_empty() {
885 continue;
886 }
887 if let Ok(n) = part.parse::<u64>() {
888 name = name.append_num(n);
889 } else {
890 name = name.append_str(part);
891 }
892 }
893 name
894 }
895 pub fn depth(&self) -> usize {
900 match &self.0.kind {
901 NameKind::Anonymous => 0,
902 NameKind::Str(parent, _) | NameKind::Num(parent, _) => 1 + parent.depth(),
903 }
904 }
905 pub fn last_str(&self) -> Option<&str> {
909 match &self.0.kind {
910 NameKind::Anonymous => None,
911 NameKind::Str(_, s) => Some(s.as_str()),
912 NameKind::Num(parent, _) => parent.last_str(),
913 }
914 }
915 pub fn last_num(&self) -> Option<u64> {
917 match &self.0.kind {
918 NameKind::Num(_, n) => Some(*n),
919 NameKind::Str(parent, _) => parent.last_num(),
920 NameKind::Anonymous => None,
921 }
922 }
923 pub fn root(&self) -> Option<&str> {
927 match &self.0.kind {
928 NameKind::Anonymous => None,
929 NameKind::Str(parent, s) => {
930 if parent.is_anonymous() {
931 Some(s.as_str())
932 } else {
933 parent.root()
934 }
935 }
936 NameKind::Num(parent, _) => parent.root(),
937 }
938 }
939 pub fn prefix(&self) -> Name {
941 match &self.0.kind {
942 NameKind::Anonymous => Name::anonymous(),
943 NameKind::Str(parent, _) | NameKind::Num(parent, _) => parent.clone(),
944 }
945 }
946 pub fn has_prefix(&self, prefix: &Name) -> bool {
950 if self == prefix {
951 return false;
952 }
953 let mut current = self.clone();
954 loop {
955 let parent = match ¤t.0.kind {
956 NameKind::Anonymous => return false,
957 NameKind::Str(parent, _) | NameKind::Num(parent, _) => parent.clone(),
958 };
959 if &parent == prefix {
960 return true;
961 }
962 current = parent;
963 }
964 }
965 pub fn components(&self) -> Vec<String> {
969 let mut comps = Vec::new();
970 let mut current = self.clone();
971 loop {
972 let parent = match ¤t.0.kind {
973 NameKind::Anonymous => break,
974 NameKind::Str(parent, s) => {
975 comps.push(s.clone());
976 parent.clone()
977 }
978 NameKind::Num(parent, n) => {
979 comps.push(n.to_string());
980 parent.clone()
981 }
982 };
983 current = parent;
984 }
985 comps.reverse();
986 comps
987 }
988 pub fn from_components(comps: &[String]) -> Self {
992 let mut name = Name::anonymous();
993 for comp in comps {
994 if let Ok(n) = comp.parse::<u64>() {
995 name = name.append_num(n);
996 } else {
997 name = name.append_str(comp.as_str());
998 }
999 }
1000 name
1001 }
1002 pub fn replace_last(self, new_last: impl Into<String>) -> Self {
1006 match &self.0.kind {
1007 NameKind::Anonymous => Name::str(new_last),
1008 NameKind::Str(parent, _) | NameKind::Num(parent, _) => {
1009 Name::mk_str(parent.clone(), new_last)
1010 }
1011 }
1012 }
1013 pub fn freshen(self, suffix: u64) -> Self {
1017 self.append_num(suffix)
1018 }
1019 pub fn in_namespace(&self, ns: &Name) -> bool {
1023 self.has_prefix(ns)
1024 }
1025 pub fn with_suffix(self, suffix: impl Into<String>) -> Self {
1027 self.append_str(suffix)
1028 }
1029 pub fn to_ident_string(&self) -> String {
1033 self.to_string()
1034 .chars()
1035 .map(|c| {
1036 if c.is_alphanumeric() || c == '_' {
1037 c
1038 } else {
1039 '_'
1040 }
1041 })
1042 .collect()
1043 }
1044 pub fn prepend(self, prefix: Name) -> Self {
1046 let comps = self.components();
1047 let mut name = prefix;
1048 for comp in comps {
1049 if let Ok(n) = comp.parse::<u64>() {
1050 name = name.append_num(n);
1051 } else {
1052 name = name.append_str(comp);
1053 }
1054 }
1055 name
1056 }
1057 pub fn is_str_name(&self) -> bool {
1059 matches!(&self.0.kind, NameKind::Str(_, _))
1060 }
1061 pub fn is_num_name(&self) -> bool {
1063 matches!(&self.0.kind, NameKind::Num(_, _))
1064 }
1065}
1066#[allow(dead_code)]
1068pub struct NameMapping {
1069 name_to_id: std::collections::HashMap<String, u32>,
1070 id_to_name: std::collections::HashMap<u32, String>,
1071 next_id: u32,
1072}
1073#[allow(dead_code)]
1074impl NameMapping {
1075 pub fn new() -> Self {
1077 Self {
1078 name_to_id: std::collections::HashMap::new(),
1079 id_to_name: std::collections::HashMap::new(),
1080 next_id: 0,
1081 }
1082 }
1083 pub fn register(&mut self, name: impl Into<String>) -> u32 {
1085 let name = name.into();
1086 if let Some(&id) = self.name_to_id.get(&name) {
1087 return id;
1088 }
1089 let id = self.next_id;
1090 self.next_id += 1;
1091 self.name_to_id.insert(name.clone(), id);
1092 self.id_to_name.insert(id, name);
1093 id
1094 }
1095 pub fn id_of(&self, name: &str) -> Option<u32> {
1097 self.name_to_id.get(name).copied()
1098 }
1099 pub fn name_of(&self, id: u32) -> Option<&str> {
1101 self.id_to_name.get(&id).map(|s| s.as_str())
1102 }
1103 pub fn len(&self) -> usize {
1105 self.name_to_id.len()
1106 }
1107 pub fn is_empty(&self) -> bool {
1109 self.name_to_id.is_empty()
1110 }
1111}
1112#[allow(dead_code)]
1114pub struct DiagMeta {
1115 pub(super) entries: Vec<(String, String)>,
1116}
1117#[allow(dead_code)]
1118impl DiagMeta {
1119 pub fn new() -> Self {
1121 Self {
1122 entries: Vec::new(),
1123 }
1124 }
1125 pub fn add(&mut self, key: impl Into<String>, val: impl Into<String>) {
1127 self.entries.push((key.into(), val.into()));
1128 }
1129 pub fn get(&self, key: &str) -> Option<&str> {
1131 self.entries
1132 .iter()
1133 .find(|(k, _)| k == key)
1134 .map(|(_, v)| v.as_str())
1135 }
1136 pub fn len(&self) -> usize {
1138 self.entries.len()
1139 }
1140 pub fn is_empty(&self) -> bool {
1142 self.entries.is_empty()
1143 }
1144}
1145#[allow(dead_code)]
1147pub struct SparseBitSet {
1148 words: Vec<u64>,
1149}
1150#[allow(dead_code)]
1151impl SparseBitSet {
1152 pub fn new(capacity: usize) -> Self {
1154 let words = capacity.div_ceil(64);
1155 Self {
1156 words: vec![0u64; words],
1157 }
1158 }
1159 pub fn set(&mut self, i: usize) {
1161 let word = i / 64;
1162 let bit = i % 64;
1163 if word < self.words.len() {
1164 self.words[word] |= 1u64 << bit;
1165 }
1166 }
1167 pub fn clear(&mut self, i: usize) {
1169 let word = i / 64;
1170 let bit = i % 64;
1171 if word < self.words.len() {
1172 self.words[word] &= !(1u64 << bit);
1173 }
1174 }
1175 pub fn get(&self, i: usize) -> bool {
1177 let word = i / 64;
1178 let bit = i % 64;
1179 self.words.get(word).is_some_and(|w| w & (1u64 << bit) != 0)
1180 }
1181 pub fn count_ones(&self) -> u32 {
1183 self.words.iter().map(|w| w.count_ones()).sum()
1184 }
1185 pub fn union(&self, other: &SparseBitSet) -> SparseBitSet {
1187 let len = self.words.len().max(other.words.len());
1188 let mut result = SparseBitSet {
1189 words: vec![0u64; len],
1190 };
1191 for i in 0..self.words.len() {
1192 result.words[i] |= self.words[i];
1193 }
1194 for i in 0..other.words.len() {
1195 result.words[i] |= other.words[i];
1196 }
1197 result
1198 }
1199}
1200#[allow(dead_code)]
1202pub struct NameSetExt {
1203 inner: std::collections::HashSet<String>,
1204}
1205#[allow(dead_code)]
1206impl NameSetExt {
1207 pub fn new() -> Self {
1209 Self {
1210 inner: std::collections::HashSet::new(),
1211 }
1212 }
1213 pub fn insert(&mut self, name: impl Into<String>) {
1215 self.inner.insert(name.into());
1216 }
1217 pub fn contains(&self, name: &str) -> bool {
1219 self.inner.contains(name)
1220 }
1221 pub fn remove(&mut self, name: &str) {
1223 self.inner.remove(name);
1224 }
1225 pub fn len(&self) -> usize {
1227 self.inner.len()
1228 }
1229 pub fn is_empty(&self) -> bool {
1231 self.inner.is_empty()
1232 }
1233 pub fn union(&self, other: &NameSetExt) -> NameSetExt {
1235 let mut result = NameSetExt::new();
1236 for n in &self.inner {
1237 result.insert(n.as_str());
1238 }
1239 for n in &other.inner {
1240 result.insert(n.as_str());
1241 }
1242 result
1243 }
1244 pub fn intersect(&self, other: &NameSetExt) -> NameSetExt {
1246 let mut result = NameSetExt::new();
1247 for n in &self.inner {
1248 if other.contains(n) {
1249 result.insert(n.as_str());
1250 }
1251 }
1252 result
1253 }
1254}
1255#[allow(dead_code)]
1257pub struct ScopeStack {
1258 names: Vec<String>,
1259}
1260#[allow(dead_code)]
1261impl ScopeStack {
1262 pub fn new() -> Self {
1264 Self { names: Vec::new() }
1265 }
1266 pub fn push(&mut self, name: impl Into<String>) {
1268 self.names.push(name.into());
1269 }
1270 pub fn pop(&mut self) -> Option<String> {
1272 self.names.pop()
1273 }
1274 pub fn current(&self) -> Option<&str> {
1276 self.names.last().map(|s| s.as_str())
1277 }
1278 pub fn depth(&self) -> usize {
1280 self.names.len()
1281 }
1282 pub fn is_empty(&self) -> bool {
1284 self.names.is_empty()
1285 }
1286 pub fn path(&self) -> String {
1288 self.names.join(".")
1289 }
1290}
1291#[allow(dead_code)]
1293pub struct NameTrieExt {
1294 children: std::collections::HashMap<char, NameTrieExt>,
1295 terminal: bool,
1296 name: Option<String>,
1297}
1298#[allow(dead_code)]
1299impl NameTrieExt {
1300 pub fn new() -> Self {
1302 Self {
1303 children: std::collections::HashMap::new(),
1304 terminal: false,
1305 name: None,
1306 }
1307 }
1308 pub fn insert(&mut self, name: &str) {
1310 let mut node = self;
1311 for c in name.chars() {
1312 node = node.children.entry(c).or_default();
1313 }
1314 node.terminal = true;
1315 node.name = Some(name.to_string());
1316 }
1317 pub fn contains(&self, name: &str) -> bool {
1319 let mut node = self;
1320 for c in name.chars() {
1321 match node.children.get(&c) {
1322 Some(n) => node = n,
1323 None => return false,
1324 }
1325 }
1326 node.terminal
1327 }
1328 pub fn with_prefix(&self, prefix: &str) -> Vec<String> {
1330 let mut node = self;
1331 for c in prefix.chars() {
1332 match node.children.get(&c) {
1333 Some(n) => node = n,
1334 None => return Vec::new(),
1335 }
1336 }
1337 let mut results = Vec::new();
1338 node.collect_all(&mut results);
1339 results
1340 }
1341 fn collect_all(&self, out: &mut Vec<String>) {
1342 if let Some(ref n) = self.name {
1343 out.push(n.clone());
1344 }
1345 for child in self.children.values() {
1346 let c: &NameTrieExt = child;
1347 c.collect_all(out);
1348 }
1349 }
1350}
1351#[allow(dead_code)]
1353pub struct EventCounter {
1354 counts: std::collections::HashMap<String, u64>,
1355}
1356#[allow(dead_code)]
1357impl EventCounter {
1358 pub fn new() -> Self {
1360 Self {
1361 counts: std::collections::HashMap::new(),
1362 }
1363 }
1364 pub fn inc(&mut self, event: &str) {
1366 *self.counts.entry(event.to_string()).or_insert(0) += 1;
1367 }
1368 pub fn add(&mut self, event: &str, n: u64) {
1370 *self.counts.entry(event.to_string()).or_insert(0) += n;
1371 }
1372 pub fn get(&self, event: &str) -> u64 {
1374 self.counts.get(event).copied().unwrap_or(0)
1375 }
1376 pub fn total(&self) -> u64 {
1378 self.counts.values().sum()
1379 }
1380 pub fn reset(&mut self) {
1382 self.counts.clear();
1383 }
1384 pub fn event_names(&self) -> Vec<&str> {
1386 self.counts.keys().map(|s| s.as_str()).collect()
1387 }
1388}
1389#[derive(Debug, Clone, Default)]
1393pub struct NameSet {
1394 pub(super) inner: HashSet<Name>,
1395}
1396impl NameSet {
1397 pub fn new() -> Self {
1399 Self {
1400 inner: HashSet::new(),
1401 }
1402 }
1403 pub fn insert(&mut self, name: Name) -> bool {
1405 self.inner.insert(name)
1406 }
1407 pub fn remove(&mut self, name: &Name) -> bool {
1409 self.inner.remove(name)
1410 }
1411 pub fn contains(&self, name: &Name) -> bool {
1413 self.inner.contains(name)
1414 }
1415 pub fn len(&self) -> usize {
1417 self.inner.len()
1418 }
1419 pub fn is_empty(&self) -> bool {
1421 self.inner.is_empty()
1422 }
1423 pub fn iter(&self) -> impl Iterator<Item = &Name> {
1425 self.inner.iter()
1426 }
1427 pub fn union(&self, other: &NameSet) -> NameSet {
1429 NameSet {
1430 inner: self.inner.union(&other.inner).cloned().collect(),
1431 }
1432 }
1433 pub fn intersection(&self, other: &NameSet) -> NameSet {
1435 NameSet {
1436 inner: self.inner.intersection(&other.inner).cloned().collect(),
1437 }
1438 }
1439 pub fn difference(&self, other: &NameSet) -> NameSet {
1441 NameSet {
1442 inner: self.inner.difference(&other.inner).cloned().collect(),
1443 }
1444 }
1445 pub fn in_namespace(&self, ns: &Name) -> NameSet {
1447 NameSet {
1448 inner: self
1449 .inner
1450 .iter()
1451 .filter(|n| n.has_prefix(ns))
1452 .cloned()
1453 .collect(),
1454 }
1455 }
1456 pub fn to_sorted_vec(&self) -> Vec<Name> {
1458 let mut v: Vec<Name> = self.inner.iter().cloned().collect();
1459 v.sort();
1460 v
1461 }
1462}
1463#[allow(dead_code)]
1465pub struct AnnotationTable {
1466 map: std::collections::HashMap<String, Vec<String>>,
1467}
1468#[allow(dead_code)]
1469impl AnnotationTable {
1470 pub fn new() -> Self {
1472 Self {
1473 map: std::collections::HashMap::new(),
1474 }
1475 }
1476 pub fn annotate(&mut self, key: impl Into<String>, val: impl Into<String>) {
1478 self.map.entry(key.into()).or_default().push(val.into());
1479 }
1480 pub fn get_all(&self, key: &str) -> &[String] {
1482 self.map.get(key).map(|v| v.as_slice()).unwrap_or(&[])
1483 }
1484 pub fn num_keys(&self) -> usize {
1486 self.map.len()
1487 }
1488 pub fn has(&self, key: &str) -> bool {
1490 self.map.contains_key(key)
1491 }
1492}
1493#[allow(dead_code)]
1495pub struct SimpleLruCache<K: std::hash::Hash + Eq + Clone, V: Clone> {
1496 capacity: usize,
1497 map: std::collections::HashMap<K, usize>,
1498 keys: Vec<K>,
1499 vals: Vec<V>,
1500 order: Vec<usize>,
1501}
1502#[allow(dead_code)]
1503impl<K: std::hash::Hash + Eq + Clone, V: Clone> SimpleLruCache<K, V> {
1504 pub fn new(capacity: usize) -> Self {
1506 assert!(capacity > 0);
1507 Self {
1508 capacity,
1509 map: std::collections::HashMap::new(),
1510 keys: Vec::new(),
1511 vals: Vec::new(),
1512 order: Vec::new(),
1513 }
1514 }
1515 pub fn put(&mut self, key: K, val: V) {
1517 if let Some(&idx) = self.map.get(&key) {
1526 self.vals[idx] = val;
1529 self.order.retain(|&x| x != idx);
1532 self.order.insert(0, idx);
1533 return;
1534 }
1535 match self.order.last() {
1536 Some(&evict_idx) if self.keys.len() >= self.capacity => {
1540 let map_key = key.clone();
1545 let removed = self.map.remove_entry(&self.keys[evict_idx]);
1546 let old_key = std::mem::replace(&mut self.keys[evict_idx], key);
1550 let old_val = std::mem::replace(&mut self.vals[evict_idx], val);
1551 self.order.rotate_right(1);
1552 self.map.insert(map_key, evict_idx);
1555 drop((removed, old_key, old_val));
1556 }
1557 _ => {
1560 let map_key = key.clone();
1561 let idx = self.keys.len();
1562 self.keys.reserve(1);
1566 self.vals.reserve(1);
1567 self.order.reserve(1);
1568 self.keys.push(key);
1569 self.vals.push(val);
1570 self.order.insert(0, idx);
1571 self.map.insert(map_key, idx);
1572 }
1573 }
1574 }
1575 pub fn get(&mut self, key: &K) -> Option<&V> {
1577 let idx = *self.map.get(key)?;
1580 self.order.retain(|&x| x != idx);
1581 self.order.insert(0, idx);
1582 Some(&self.vals[idx])
1583 }
1584 pub fn len(&self) -> usize {
1586 self.keys.len()
1587 }
1588 pub fn is_empty(&self) -> bool {
1590 self.keys.is_empty()
1591 }
1592}
1593#[allow(dead_code)]
1595pub struct Slot<T> {
1596 inner: Option<T>,
1597}
1598#[allow(dead_code)]
1599impl<T> Slot<T> {
1600 pub fn empty() -> Self {
1602 Self { inner: None }
1603 }
1604 pub fn fill(&mut self, val: T) {
1606 assert!(self.inner.is_none(), "Slot: already filled");
1607 self.inner = Some(val);
1608 }
1609 pub fn get(&self) -> Option<&T> {
1611 self.inner.as_ref()
1612 }
1613 pub fn is_filled(&self) -> bool {
1615 self.inner.is_some()
1616 }
1617 pub fn take(&mut self) -> Option<T> {
1619 self.inner.take()
1620 }
1621 pub fn get_or_fill_with(&mut self, f: impl FnOnce() -> T) -> &T {
1623 self.inner.get_or_insert_with(f)
1624 }
1625}
1626#[allow(dead_code)]
1628pub struct NameGeneratorExt {
1629 prefix: String,
1630 counter: u64,
1631}
1632#[allow(dead_code)]
1633impl NameGeneratorExt {
1634 pub fn new(prefix: impl Into<String>) -> Self {
1636 Self {
1637 prefix: prefix.into(),
1638 counter: 0,
1639 }
1640 }
1641 #[allow(clippy::should_implement_trait)]
1643 pub fn next(&mut self) -> String {
1644 let n = self.counter;
1645 self.counter += 1;
1646 format!("{}{}", self.prefix, n)
1647 }
1648 pub fn count(&self) -> u64 {
1650 self.counter
1651 }
1652 pub fn reset(&mut self) {
1654 self.counter = 0;
1655 }
1656}
1657#[allow(dead_code)]
1659#[allow(missing_docs)]
1660pub struct StatCache<K: std::hash::Hash + Eq + Clone, V: Clone> {
1661 pub inner: SimpleLruCache<K, V>,
1663 pub hits: u64,
1665 pub misses: u64,
1667}
1668#[allow(dead_code)]
1669impl<K: std::hash::Hash + Eq + Clone, V: Clone> StatCache<K, V> {
1670 pub fn new(capacity: usize) -> Self {
1672 Self {
1673 inner: SimpleLruCache::new(capacity),
1674 hits: 0,
1675 misses: 0,
1676 }
1677 }
1678 pub fn get(&mut self, key: &K) -> Option<&V> {
1680 let result = self.inner.get(key);
1681 if result.is_some() {
1682 self.hits += 1;
1683 } else {
1684 self.misses += 1;
1685 }
1686 None
1687 }
1688 pub fn put(&mut self, key: K, val: V) {
1690 self.inner.put(key, val);
1691 }
1692 pub fn hit_rate(&self) -> f64 {
1694 let total = self.hits + self.misses;
1695 if total == 0 {
1696 return 0.0;
1697 }
1698 self.hits as f64 / total as f64
1699 }
1700}
1701#[allow(dead_code)]
1703pub struct FrequencyTable<T: std::hash::Hash + Eq + Clone> {
1704 counts: std::collections::HashMap<T, u64>,
1705}
1706#[allow(dead_code)]
1707impl<T: std::hash::Hash + Eq + Clone> FrequencyTable<T> {
1708 pub fn new() -> Self {
1710 Self {
1711 counts: std::collections::HashMap::new(),
1712 }
1713 }
1714 pub fn record(&mut self, item: T) {
1716 *self.counts.entry(item).or_insert(0) += 1;
1717 }
1718 pub fn freq(&self, item: &T) -> u64 {
1720 self.counts.get(item).copied().unwrap_or(0)
1721 }
1722 pub fn most_frequent(&self) -> Option<(&T, u64)> {
1724 self.counts
1725 .iter()
1726 .max_by_key(|(_, &v)| v)
1727 .map(|(k, &v)| (k, v))
1728 }
1729 pub fn total(&self) -> u64 {
1731 self.counts.values().sum()
1732 }
1733 pub fn distinct(&self) -> usize {
1735 self.counts.len()
1736 }
1737}
1738#[allow(dead_code)]
1740pub struct IdDispenser<T> {
1741 next: u32,
1742 _phantom: std::marker::PhantomData<T>,
1743}
1744#[allow(dead_code)]
1745impl<T> IdDispenser<T> {
1746 pub fn new() -> Self {
1748 Self {
1749 next: 0,
1750 _phantom: std::marker::PhantomData,
1751 }
1752 }
1753 #[allow(clippy::should_implement_trait)]
1755 pub fn next(&mut self) -> TypedId<T> {
1756 let id = TypedId::new(self.next);
1757 self.next += 1;
1758 id
1759 }
1760 pub fn count(&self) -> u32 {
1762 self.next
1763 }
1764}
1765#[allow(dead_code)]
1767#[allow(missing_docs)]
1768pub struct QualifiedNameExt {
1769 pub parts: Vec<String>,
1771}
1772#[allow(dead_code)]
1773impl QualifiedNameExt {
1774 pub fn from_dot_str(s: &str) -> Self {
1776 s.parse().unwrap_or_else(|_| unreachable!())
1777 }
1778 pub fn simple(name: impl Into<String>) -> Self {
1780 Self {
1781 parts: vec![name.into()],
1782 }
1783 }
1784 pub fn unqualified(&self) -> &str {
1786 self.parts.last().map(|s| s.as_str()).unwrap_or("")
1787 }
1788 pub fn namespace(&self) -> Option<QualifiedNameExt> {
1790 if self.parts.len() <= 1 {
1791 return None;
1792 }
1793 let parts = self.parts[..self.parts.len() - 1].to_vec();
1794 Some(QualifiedNameExt { parts })
1795 }
1796 pub fn is_sub_of(&self, other: &QualifiedNameExt) -> bool {
1798 self.parts.starts_with(&other.parts)
1799 }
1800 pub fn depth(&self) -> usize {
1802 self.parts.len()
1803 }
1804}
1805#[allow(dead_code)]
1807pub struct MemoSlot<T: Clone> {
1808 cached: Option<T>,
1809}
1810#[allow(dead_code)]
1811impl<T: Clone> MemoSlot<T> {
1812 pub fn new() -> Self {
1814 Self { cached: None }
1815 }
1816 pub fn get_or_compute(&mut self, f: impl FnOnce() -> T) -> &T {
1818 self.cached.get_or_insert_with(f)
1819 }
1820 pub fn invalidate(&mut self) {
1822 self.cached = None;
1823 }
1824 pub fn is_cached(&self) -> bool {
1826 self.cached.is_some()
1827 }
1828}