1use crate::{Expr, FVarId, Name};
6
7use std::collections::HashMap;
8
9use super::functions::alpha_equiv;
10
11#[allow(dead_code)]
13#[allow(missing_docs)]
14pub struct RewriteRule {
15 pub name: String,
17 pub lhs: String,
19 pub rhs: String,
21 pub conditional: bool,
23}
24#[allow(dead_code)]
25impl RewriteRule {
26 pub fn unconditional(
28 name: impl Into<String>,
29 lhs: impl Into<String>,
30 rhs: impl Into<String>,
31 ) -> Self {
32 Self {
33 name: name.into(),
34 lhs: lhs.into(),
35 rhs: rhs.into(),
36 conditional: false,
37 }
38 }
39 pub fn conditional(
41 name: impl Into<String>,
42 lhs: impl Into<String>,
43 rhs: impl Into<String>,
44 ) -> Self {
45 Self {
46 name: name.into(),
47 lhs: lhs.into(),
48 rhs: rhs.into(),
49 conditional: true,
50 }
51 }
52 pub fn display(&self) -> String {
54 format!("{}: {} → {}", self.name, self.lhs, self.rhs)
55 }
56}
57#[allow(dead_code)]
59pub struct WriteOnce<T> {
60 value: std::cell::Cell<Option<T>>,
61}
62#[allow(dead_code)]
63impl<T: Copy> WriteOnce<T> {
64 pub fn new() -> Self {
66 Self {
67 value: std::cell::Cell::new(None),
68 }
69 }
70 pub fn write(&self, val: T) -> bool {
72 if self.value.get().is_some() {
73 return false;
74 }
75 self.value.set(Some(val));
76 true
77 }
78 pub fn read(&self) -> Option<T> {
80 self.value.get()
81 }
82 pub fn is_written(&self) -> bool {
84 self.value.get().is_some()
85 }
86}
87#[allow(dead_code)]
89pub struct TransformStat {
90 before: StatSummary,
91 after: StatSummary,
92}
93#[allow(dead_code)]
94impl TransformStat {
95 pub fn new() -> Self {
97 Self {
98 before: StatSummary::new(),
99 after: StatSummary::new(),
100 }
101 }
102 pub fn record_before(&mut self, v: f64) {
104 self.before.record(v);
105 }
106 pub fn record_after(&mut self, v: f64) {
108 self.after.record(v);
109 }
110 pub fn mean_ratio(&self) -> Option<f64> {
112 let b = self.before.mean()?;
113 let a = self.after.mean()?;
114 if b.abs() < f64::EPSILON {
115 return None;
116 }
117 Some(a / b)
118 }
119}
120#[allow(dead_code)]
122pub struct PrefixCounter {
123 children: std::collections::HashMap<char, PrefixCounter>,
124 count: usize,
125}
126#[allow(dead_code)]
127impl PrefixCounter {
128 pub fn new() -> Self {
130 Self {
131 children: std::collections::HashMap::new(),
132 count: 0,
133 }
134 }
135 pub fn record(&mut self, s: &str) {
137 self.count += 1;
138 let mut node = self;
139 for c in s.chars() {
140 node = node.children.entry(c).or_default();
141 node.count += 1;
142 }
143 }
144 pub fn count_with_prefix(&self, prefix: &str) -> usize {
146 let mut node = self;
147 for c in prefix.chars() {
148 match node.children.get(&c) {
149 Some(n) => node = n,
150 None => return 0,
151 }
152 }
153 node.count
154 }
155}
156#[derive(Clone, Debug, Default)]
160pub struct AlphaCache {
161 known_equiv: Vec<(Expr, Expr)>,
162 known_non_equiv: Vec<(Expr, Expr)>,
163}
164impl AlphaCache {
165 pub fn new() -> Self {
167 Self::default()
168 }
169 pub fn query(&self, e1: &Expr, e2: &Expr) -> Option<bool> {
171 for (a, b) in &self.known_equiv {
172 if (a == e1 && b == e2) || (a == e2 && b == e1) {
173 return Some(true);
174 }
175 }
176 for (a, b) in &self.known_non_equiv {
177 if (a == e1 && b == e2) || (a == e2 && b == e1) {
178 return Some(false);
179 }
180 }
181 None
182 }
183 pub fn alpha_equiv_cached(&mut self, e1: &Expr, e2: &Expr) -> bool {
185 if let Some(result) = self.query(e1, e2) {
186 return result;
187 }
188 let result = alpha_equiv(e1, e2);
189 if result {
190 self.known_equiv.push((e1.clone(), e2.clone()));
191 } else {
192 self.known_non_equiv.push((e1.clone(), e2.clone()));
193 }
194 result
195 }
196 pub fn num_equiv(&self) -> usize {
198 self.known_equiv.len()
199 }
200 pub fn num_non_equiv(&self) -> usize {
202 self.known_non_equiv.len()
203 }
204 pub fn clear(&mut self) {
206 self.known_equiv.clear();
207 self.known_non_equiv.clear();
208 }
209}
210#[allow(dead_code)]
212pub struct SlidingSum {
213 window: Vec<f64>,
214 capacity: usize,
215 pos: usize,
216 sum: f64,
217 count: usize,
218}
219#[allow(dead_code)]
220impl SlidingSum {
221 pub fn new(capacity: usize) -> Self {
223 Self {
224 window: vec![0.0; capacity],
225 capacity,
226 pos: 0,
227 sum: 0.0,
228 count: 0,
229 }
230 }
231 pub fn push(&mut self, val: f64) {
233 let oldest = self.window[self.pos];
234 self.sum -= oldest;
235 self.sum += val;
236 self.window[self.pos] = val;
237 self.pos = (self.pos + 1) % self.capacity;
238 if self.count < self.capacity {
239 self.count += 1;
240 }
241 }
242 pub fn sum(&self) -> f64 {
244 self.sum
245 }
246 pub fn mean(&self) -> Option<f64> {
248 if self.count == 0 {
249 None
250 } else {
251 Some(self.sum / self.count as f64)
252 }
253 }
254 pub fn count(&self) -> usize {
256 self.count
257 }
258}
259#[allow(dead_code)]
261pub struct StringPool {
262 free: Vec<String>,
263}
264#[allow(dead_code)]
265impl StringPool {
266 pub fn new() -> Self {
268 Self { free: Vec::new() }
269 }
270 pub fn take(&mut self) -> String {
272 self.free.pop().unwrap_or_default()
273 }
274 pub fn give(&mut self, mut s: String) {
276 s.clear();
277 self.free.push(s);
278 }
279 pub fn free_count(&self) -> usize {
281 self.free.len()
282 }
283}
284#[allow(dead_code)]
286pub struct SparseVec<T: Default + Clone + PartialEq> {
287 entries: std::collections::HashMap<usize, T>,
288 default_: T,
289 logical_len: usize,
290}
291#[allow(dead_code)]
292impl<T: Default + Clone + PartialEq> SparseVec<T> {
293 pub fn new(len: usize) -> Self {
295 Self {
296 entries: std::collections::HashMap::new(),
297 default_: T::default(),
298 logical_len: len,
299 }
300 }
301 pub fn set(&mut self, idx: usize, val: T) {
303 if val == self.default_ {
304 self.entries.remove(&idx);
305 } else {
306 self.entries.insert(idx, val);
307 }
308 }
309 pub fn get(&self, idx: usize) -> &T {
311 self.entries.get(&idx).unwrap_or(&self.default_)
312 }
313 pub fn len(&self) -> usize {
315 self.logical_len
316 }
317 pub fn is_empty(&self) -> bool {
319 self.len() == 0
320 }
321 pub fn nnz(&self) -> usize {
323 self.entries.len()
324 }
325}
326#[allow(dead_code)]
328pub struct TokenBucket {
329 capacity: u64,
330 tokens: u64,
331 refill_per_ms: u64,
332 last_refill: std::time::Instant,
333}
334#[allow(dead_code)]
335impl TokenBucket {
336 pub fn new(capacity: u64, refill_per_ms: u64) -> Self {
338 Self {
339 capacity,
340 tokens: capacity,
341 refill_per_ms,
342 last_refill: std::time::Instant::now(),
343 }
344 }
345 pub fn try_consume(&mut self, n: u64) -> bool {
347 self.refill();
348 if self.tokens >= n {
349 self.tokens -= n;
350 true
351 } else {
352 false
353 }
354 }
355 fn refill(&mut self) {
356 let now = std::time::Instant::now();
357 let elapsed_ms = now.duration_since(self.last_refill).as_millis() as u64;
358 if elapsed_ms > 0 {
359 let new_tokens = elapsed_ms * self.refill_per_ms;
360 self.tokens = (self.tokens + new_tokens).min(self.capacity);
361 self.last_refill = now;
362 }
363 }
364 pub fn available(&self) -> u64 {
366 self.tokens
367 }
368 pub fn capacity(&self) -> u64 {
370 self.capacity
371 }
372}
373#[allow(dead_code)]
375pub struct StatSummary {
376 count: u64,
377 sum: f64,
378 min: f64,
379 max: f64,
380}
381#[allow(dead_code)]
382impl StatSummary {
383 pub fn new() -> Self {
385 Self {
386 count: 0,
387 sum: 0.0,
388 min: f64::INFINITY,
389 max: f64::NEG_INFINITY,
390 }
391 }
392 pub fn record(&mut self, val: f64) {
394 self.count += 1;
395 self.sum += val;
396 if val < self.min {
397 self.min = val;
398 }
399 if val > self.max {
400 self.max = val;
401 }
402 }
403 pub fn mean(&self) -> Option<f64> {
405 if self.count == 0 {
406 None
407 } else {
408 Some(self.sum / self.count as f64)
409 }
410 }
411 pub fn min(&self) -> Option<f64> {
413 if self.count == 0 {
414 None
415 } else {
416 Some(self.min)
417 }
418 }
419 pub fn max(&self) -> Option<f64> {
421 if self.count == 0 {
422 None
423 } else {
424 Some(self.max)
425 }
426 }
427 pub fn count(&self) -> u64 {
429 self.count
430 }
431}
432#[allow(dead_code)]
434pub enum Either2<A, B> {
435 First(A),
437 Second(B),
439}
440#[allow(dead_code)]
441impl<A, B> Either2<A, B> {
442 pub fn is_first(&self) -> bool {
444 matches!(self, Either2::First(_))
445 }
446 pub fn is_second(&self) -> bool {
448 matches!(self, Either2::Second(_))
449 }
450 pub fn first(self) -> Option<A> {
452 match self {
453 Either2::First(a) => Some(a),
454 _ => None,
455 }
456 }
457 pub fn second(self) -> Option<B> {
459 match self {
460 Either2::Second(b) => Some(b),
461 _ => None,
462 }
463 }
464 pub fn map_first<C, F: FnOnce(A) -> C>(self, f: F) -> Either2<C, B> {
466 match self {
467 Either2::First(a) => Either2::First(f(a)),
468 Either2::Second(b) => Either2::Second(b),
469 }
470 }
471}
472#[allow(dead_code)]
474pub struct RewriteRuleSet {
475 rules: Vec<RewriteRule>,
476}
477#[allow(dead_code)]
478impl RewriteRuleSet {
479 pub fn new() -> Self {
481 Self { rules: Vec::new() }
482 }
483 pub fn add(&mut self, rule: RewriteRule) {
485 self.rules.push(rule);
486 }
487 pub fn len(&self) -> usize {
489 self.rules.len()
490 }
491 pub fn is_empty(&self) -> bool {
493 self.rules.is_empty()
494 }
495 pub fn conditional_rules(&self) -> Vec<&RewriteRule> {
497 self.rules.iter().filter(|r| r.conditional).collect()
498 }
499 pub fn unconditional_rules(&self) -> Vec<&RewriteRule> {
501 self.rules.iter().filter(|r| !r.conditional).collect()
502 }
503 pub fn get(&self, name: &str) -> Option<&RewriteRule> {
505 self.rules.iter().find(|r| r.name == name)
506 }
507}
508#[allow(dead_code)]
510pub struct VersionedRecord<T: Clone> {
511 history: Vec<T>,
512}
513#[allow(dead_code)]
514impl<T: Clone> VersionedRecord<T> {
515 pub fn new(initial: T) -> Self {
517 Self {
518 history: vec![initial],
519 }
520 }
521 pub fn update(&mut self, val: T) {
523 self.history.push(val);
524 }
525 pub fn current(&self) -> &T {
527 self.history
528 .last()
529 .expect("VersionedRecord history is always non-empty after construction")
530 }
531 pub fn at_version(&self, n: usize) -> Option<&T> {
533 self.history.get(n)
534 }
535 pub fn version(&self) -> usize {
537 self.history.len() - 1
538 }
539 pub fn has_history(&self) -> bool {
541 self.history.len() > 1
542 }
543}
544#[allow(dead_code)]
546pub struct Fixture {
547 data: std::collections::HashMap<String, String>,
548}
549#[allow(dead_code)]
550impl Fixture {
551 pub fn new() -> Self {
553 Self {
554 data: std::collections::HashMap::new(),
555 }
556 }
557 pub fn set(&mut self, key: impl Into<String>, val: impl Into<String>) {
559 self.data.insert(key.into(), val.into());
560 }
561 pub fn get(&self, key: &str) -> Option<&str> {
563 self.data.get(key).map(|s| s.as_str())
564 }
565 pub fn len(&self) -> usize {
567 self.data.len()
568 }
569 pub fn is_empty(&self) -> bool {
571 self.len() == 0
572 }
573}
574#[allow(dead_code)]
576pub struct PathBuf {
577 components: Vec<String>,
578}
579#[allow(dead_code)]
580impl PathBuf {
581 pub fn new() -> Self {
583 Self {
584 components: Vec::new(),
585 }
586 }
587 pub fn push(&mut self, comp: impl Into<String>) {
589 self.components.push(comp.into());
590 }
591 pub fn pop(&mut self) {
593 self.components.pop();
594 }
595 pub fn as_str(&self) -> String {
597 self.components.join("/")
598 }
599 pub fn depth(&self) -> usize {
601 self.components.len()
602 }
603 pub fn clear(&mut self) {
605 self.components.clear();
606 }
607}
608#[allow(dead_code)]
610#[allow(missing_docs)]
611pub enum DecisionNode {
612 Leaf(String),
614 Branch {
616 key: String,
617 val: String,
618 yes_branch: Box<DecisionNode>,
619 no_branch: Box<DecisionNode>,
620 },
621}
622#[allow(dead_code)]
623impl DecisionNode {
624 pub fn evaluate(&self, ctx: &std::collections::HashMap<String, String>) -> &str {
626 match self {
627 DecisionNode::Leaf(action) => action.as_str(),
628 DecisionNode::Branch {
629 key,
630 val,
631 yes_branch,
632 no_branch,
633 } => {
634 let actual = ctx.get(key).map(|s| s.as_str()).unwrap_or("");
635 if actual == val.as_str() {
636 yes_branch.evaluate(ctx)
637 } else {
638 no_branch.evaluate(ctx)
639 }
640 }
641 }
642 }
643 pub fn depth(&self) -> usize {
645 match self {
646 DecisionNode::Leaf(_) => 0,
647 DecisionNode::Branch {
648 yes_branch,
649 no_branch,
650 ..
651 } => 1 + yes_branch.depth().max(no_branch.depth()),
652 }
653 }
654}
655#[allow(dead_code)]
657pub struct LabelSet {
658 labels: Vec<String>,
659}
660#[allow(dead_code)]
661impl LabelSet {
662 pub fn new() -> Self {
664 Self { labels: Vec::new() }
665 }
666 pub fn add(&mut self, label: impl Into<String>) {
668 let s = label.into();
669 if !self.labels.contains(&s) {
670 self.labels.push(s);
671 }
672 }
673 pub fn has(&self, label: &str) -> bool {
675 self.labels.iter().any(|l| l == label)
676 }
677 pub fn count(&self) -> usize {
679 self.labels.len()
680 }
681 pub fn all(&self) -> &[String] {
683 &self.labels
684 }
685}
686#[allow(dead_code)]
688pub struct NonEmptyVec<T> {
689 head: T,
690 tail: Vec<T>,
691}
692#[allow(dead_code)]
693impl<T> NonEmptyVec<T> {
694 pub fn singleton(val: T) -> Self {
696 Self {
697 head: val,
698 tail: Vec::new(),
699 }
700 }
701 pub fn push(&mut self, val: T) {
703 self.tail.push(val);
704 }
705 pub fn first(&self) -> &T {
707 &self.head
708 }
709 pub fn last(&self) -> &T {
711 self.tail.last().unwrap_or(&self.head)
712 }
713 pub fn len(&self) -> usize {
715 1 + self.tail.len()
716 }
717 pub fn is_empty(&self) -> bool {
719 self.len() == 0
720 }
721 pub fn to_vec(&self) -> Vec<&T> {
723 let mut v = vec![&self.head];
724 v.extend(self.tail.iter());
725 v
726 }
727}
728#[allow(dead_code)]
730pub struct SmallMap<K: Ord + Clone, V: Clone> {
731 entries: Vec<(K, V)>,
732}
733#[allow(dead_code)]
734impl<K: Ord + Clone, V: Clone> SmallMap<K, V> {
735 pub fn new() -> Self {
737 Self {
738 entries: Vec::new(),
739 }
740 }
741 pub fn insert(&mut self, key: K, val: V) {
743 match self.entries.binary_search_by_key(&&key, |(k, _)| k) {
744 Ok(i) => self.entries[i].1 = val,
745 Err(i) => self.entries.insert(i, (key, val)),
746 }
747 }
748 pub fn get(&self, key: &K) -> Option<&V> {
750 self.entries
751 .binary_search_by_key(&key, |(k, _)| k)
752 .ok()
753 .map(|i| &self.entries[i].1)
754 }
755 pub fn len(&self) -> usize {
757 self.entries.len()
758 }
759 pub fn is_empty(&self) -> bool {
761 self.entries.is_empty()
762 }
763 pub fn keys(&self) -> Vec<&K> {
765 self.entries.iter().map(|(k, _)| k).collect()
766 }
767 pub fn values(&self) -> Vec<&V> {
769 self.entries.iter().map(|(_, v)| v).collect()
770 }
771}
772#[allow(dead_code)]
774pub struct FlatSubstitution {
775 pairs: Vec<(String, String)>,
776}
777#[allow(dead_code)]
778impl FlatSubstitution {
779 pub fn new() -> Self {
781 Self { pairs: Vec::new() }
782 }
783 pub fn add(&mut self, from: impl Into<String>, to: impl Into<String>) {
785 self.pairs.push((from.into(), to.into()));
786 }
787 pub fn apply(&self, s: &str) -> String {
789 let mut result = s.to_string();
790 for (from, to) in &self.pairs {
791 result = result.replace(from.as_str(), to.as_str());
792 }
793 result
794 }
795 pub fn len(&self) -> usize {
797 self.pairs.len()
798 }
799 pub fn is_empty(&self) -> bool {
801 self.pairs.is_empty()
802 }
803}
804#[allow(dead_code)]
806pub struct SimpleDag {
807 edges: Vec<Vec<usize>>,
809}
810#[allow(dead_code)]
811impl SimpleDag {
812 pub fn new(n: usize) -> Self {
814 Self {
815 edges: vec![Vec::new(); n],
816 }
817 }
818 pub fn add_edge(&mut self, from: usize, to: usize) {
820 if from < self.edges.len() {
821 self.edges[from].push(to);
822 }
823 }
824 pub fn successors(&self, node: usize) -> &[usize] {
826 self.edges.get(node).map(|v| v.as_slice()).unwrap_or(&[])
827 }
828 pub fn can_reach(&self, from: usize, to: usize) -> bool {
830 let mut visited = vec![false; self.edges.len()];
831 self.dfs(from, to, &mut visited)
832 }
833 fn dfs(&self, cur: usize, target: usize, visited: &mut Vec<bool>) -> bool {
834 if cur == target {
835 return true;
836 }
837 if cur >= visited.len() || visited[cur] {
838 return false;
839 }
840 visited[cur] = true;
841 for &next in self.successors(cur) {
842 if self.dfs(next, target, visited) {
843 return true;
844 }
845 }
846 false
847 }
848 pub fn topological_sort(&self) -> Option<Vec<usize>> {
850 let n = self.edges.len();
851 let mut in_degree = vec![0usize; n];
852 for succs in &self.edges {
853 for &s in succs {
854 if s < n {
855 in_degree[s] += 1;
856 }
857 }
858 }
859 let mut queue: std::collections::VecDeque<usize> =
860 (0..n).filter(|&i| in_degree[i] == 0).collect();
861 let mut order = Vec::new();
862 while let Some(node) = queue.pop_front() {
863 order.push(node);
864 for &s in self.successors(node) {
865 if s < n {
866 in_degree[s] -= 1;
867 if in_degree[s] == 0 {
868 queue.push_back(s);
869 }
870 }
871 }
872 }
873 if order.len() == n {
874 Some(order)
875 } else {
876 None
877 }
878 }
879 pub fn num_nodes(&self) -> usize {
881 self.edges.len()
882 }
883}
884#[allow(dead_code)]
886pub struct TransitiveClosure {
887 adj: Vec<Vec<usize>>,
888 n: usize,
889}
890#[allow(dead_code)]
891impl TransitiveClosure {
892 pub fn new(n: usize) -> Self {
894 Self {
895 adj: vec![Vec::new(); n],
896 n,
897 }
898 }
899 pub fn add_edge(&mut self, from: usize, to: usize) {
901 if from < self.n {
902 self.adj[from].push(to);
903 }
904 }
905 pub fn reachable_from(&self, start: usize) -> Vec<usize> {
907 let mut visited = vec![false; self.n];
908 let mut queue = std::collections::VecDeque::new();
909 queue.push_back(start);
910 while let Some(node) = queue.pop_front() {
911 if node >= self.n || visited[node] {
912 continue;
913 }
914 visited[node] = true;
915 for &next in &self.adj[node] {
916 queue.push_back(next);
917 }
918 }
919 (0..self.n).filter(|&i| visited[i]).collect()
920 }
921 pub fn can_reach(&self, from: usize, to: usize) -> bool {
923 self.reachable_from(from).contains(&to)
924 }
925}
926#[allow(dead_code)]
928pub struct RawFnPtr {
929 ptr: usize,
931 arity: usize,
932 name: String,
933}
934#[allow(dead_code)]
935impl RawFnPtr {
936 pub fn new(ptr: usize, arity: usize, name: impl Into<String>) -> Self {
938 Self {
939 ptr,
940 arity,
941 name: name.into(),
942 }
943 }
944 pub fn arity(&self) -> usize {
946 self.arity
947 }
948 pub fn name(&self) -> &str {
950 &self.name
951 }
952 pub fn raw(&self) -> usize {
954 self.ptr
955 }
956}
957#[allow(dead_code)]
959pub struct WindowIterator<'a, T> {
960 pub(super) data: &'a [T],
961 pub(super) pos: usize,
962 pub(super) window: usize,
963}
964#[allow(dead_code)]
965impl<'a, T> WindowIterator<'a, T> {
966 pub fn new(data: &'a [T], window: usize) -> Self {
968 Self {
969 data,
970 pos: 0,
971 window,
972 }
973 }
974}
975#[allow(dead_code)]
977pub struct Stopwatch {
978 start: std::time::Instant,
979 splits: Vec<f64>,
980}
981#[allow(dead_code)]
982impl Stopwatch {
983 pub fn start() -> Self {
985 Self {
986 start: std::time::Instant::now(),
987 splits: Vec::new(),
988 }
989 }
990 pub fn split(&mut self) {
992 self.splits.push(self.elapsed_ms());
993 }
994 pub fn elapsed_ms(&self) -> f64 {
996 self.start.elapsed().as_secs_f64() * 1000.0
997 }
998 pub fn splits(&self) -> &[f64] {
1000 &self.splits
1001 }
1002 pub fn num_splits(&self) -> usize {
1004 self.splits.len()
1005 }
1006}
1007#[allow(dead_code)]
1009pub struct ConfigNode {
1010 key: String,
1011 value: Option<String>,
1012 children: Vec<ConfigNode>,
1013}
1014#[allow(dead_code)]
1015impl ConfigNode {
1016 pub fn leaf(key: impl Into<String>, value: impl Into<String>) -> Self {
1018 Self {
1019 key: key.into(),
1020 value: Some(value.into()),
1021 children: Vec::new(),
1022 }
1023 }
1024 pub fn section(key: impl Into<String>) -> Self {
1026 Self {
1027 key: key.into(),
1028 value: None,
1029 children: Vec::new(),
1030 }
1031 }
1032 pub fn add_child(&mut self, child: ConfigNode) {
1034 self.children.push(child);
1035 }
1036 pub fn key(&self) -> &str {
1038 &self.key
1039 }
1040 pub fn value(&self) -> Option<&str> {
1042 self.value.as_deref()
1043 }
1044 pub fn num_children(&self) -> usize {
1046 self.children.len()
1047 }
1048 pub fn lookup(&self, path: &str) -> Option<&str> {
1050 let mut parts = path.splitn(2, '.');
1051 let head = parts.next()?;
1052 let tail = parts.next();
1053 if head != self.key {
1054 return None;
1055 }
1056 match tail {
1057 None => self.value.as_deref(),
1058 Some(rest) => self.children.iter().find_map(|c| c.lookup_relative(rest)),
1059 }
1060 }
1061 fn lookup_relative(&self, path: &str) -> Option<&str> {
1062 let mut parts = path.splitn(2, '.');
1063 let head = parts.next()?;
1064 let tail = parts.next();
1065 if head != self.key {
1066 return None;
1067 }
1068 match tail {
1069 None => self.value.as_deref(),
1070 Some(rest) => self.children.iter().find_map(|c| c.lookup_relative(rest)),
1071 }
1072 }
1073}
1074#[allow(dead_code)]
1076pub struct MinHeap<T: Ord> {
1077 data: Vec<T>,
1078}
1079#[allow(dead_code)]
1080impl<T: Ord> MinHeap<T> {
1081 pub fn new() -> Self {
1083 Self { data: Vec::new() }
1084 }
1085 pub fn push(&mut self, val: T) {
1087 self.data.push(val);
1088 self.sift_up(self.data.len() - 1);
1089 }
1090 pub fn pop(&mut self) -> Option<T> {
1092 if self.data.is_empty() {
1093 return None;
1094 }
1095 let n = self.data.len();
1096 self.data.swap(0, n - 1);
1097 let min = self.data.pop();
1098 if !self.data.is_empty() {
1099 self.sift_down(0);
1100 }
1101 min
1102 }
1103 pub fn peek(&self) -> Option<&T> {
1105 self.data.first()
1106 }
1107 pub fn len(&self) -> usize {
1109 self.data.len()
1110 }
1111 pub fn is_empty(&self) -> bool {
1113 self.data.is_empty()
1114 }
1115 fn sift_up(&mut self, mut i: usize) {
1116 while i > 0 {
1117 let parent = (i - 1) / 2;
1118 if self.data[i] < self.data[parent] {
1119 self.data.swap(i, parent);
1120 i = parent;
1121 } else {
1122 break;
1123 }
1124 }
1125 }
1126 fn sift_down(&mut self, mut i: usize) {
1127 let n = self.data.len();
1128 loop {
1129 let left = 2 * i + 1;
1130 let right = 2 * i + 2;
1131 let mut smallest = i;
1132 if left < n && self.data[left] < self.data[smallest] {
1133 smallest = left;
1134 }
1135 if right < n && self.data[right] < self.data[smallest] {
1136 smallest = right;
1137 }
1138 if smallest == i {
1139 break;
1140 }
1141 self.data.swap(i, smallest);
1142 i = smallest;
1143 }
1144 }
1145}
1146#[allow(dead_code)]
1148pub struct StackCalc {
1149 stack: Vec<i64>,
1150}
1151#[allow(dead_code)]
1152impl StackCalc {
1153 pub fn new() -> Self {
1155 Self { stack: Vec::new() }
1156 }
1157 pub fn push(&mut self, n: i64) {
1159 self.stack.push(n);
1160 }
1161 pub fn add(&mut self) {
1163 let b = self
1164 .stack
1165 .pop()
1166 .expect("stack must have at least two values for add");
1167 let a = self
1168 .stack
1169 .pop()
1170 .expect("stack must have at least two values for add");
1171 self.stack.push(a + b);
1172 }
1173 pub fn sub(&mut self) {
1175 let b = self
1176 .stack
1177 .pop()
1178 .expect("stack must have at least two values for sub");
1179 let a = self
1180 .stack
1181 .pop()
1182 .expect("stack must have at least two values for sub");
1183 self.stack.push(a - b);
1184 }
1185 pub fn mul(&mut self) {
1187 let b = self
1188 .stack
1189 .pop()
1190 .expect("stack must have at least two values for mul");
1191 let a = self
1192 .stack
1193 .pop()
1194 .expect("stack must have at least two values for mul");
1195 self.stack.push(a * b);
1196 }
1197 pub fn peek(&self) -> Option<i64> {
1199 self.stack.last().copied()
1200 }
1201 pub fn depth(&self) -> usize {
1203 self.stack.len()
1204 }
1205}
1206#[allow(dead_code)]
1208pub struct FocusStack<T> {
1209 items: Vec<T>,
1210}
1211#[allow(dead_code)]
1212impl<T> FocusStack<T> {
1213 pub fn new() -> Self {
1215 Self { items: Vec::new() }
1216 }
1217 pub fn focus(&mut self, item: T) {
1219 self.items.push(item);
1220 }
1221 pub fn blur(&mut self) -> Option<T> {
1223 self.items.pop()
1224 }
1225 pub fn current(&self) -> Option<&T> {
1227 self.items.last()
1228 }
1229 pub fn depth(&self) -> usize {
1231 self.items.len()
1232 }
1233 pub fn is_empty(&self) -> bool {
1235 self.items.is_empty()
1236 }
1237}