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: crate::wall_clock::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: crate::wall_clock::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 = crate::wall_clock::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 earlier: Vec<T>,
513 current: T,
515}
516#[allow(dead_code)]
517impl<T: Clone> VersionedRecord<T> {
518 pub fn new(initial: T) -> Self {
520 Self {
521 earlier: Vec::new(),
522 current: initial,
523 }
524 }
525 pub fn update(&mut self, val: T) {
527 let previous = std::mem::replace(&mut self.current, val);
528 self.earlier.push(previous);
529 }
530 pub fn current(&self) -> &T {
532 &self.current
533 }
534 pub fn at_version(&self, n: usize) -> Option<&T> {
536 match self.earlier.get(n) {
537 Some(value) => Some(value),
538 None if n == self.earlier.len() => Some(&self.current),
539 None => None,
540 }
541 }
542 pub fn version(&self) -> usize {
544 self.earlier.len()
545 }
546 pub fn has_history(&self) -> bool {
548 !self.earlier.is_empty()
549 }
550}
551#[allow(dead_code)]
553pub struct Fixture {
554 data: std::collections::HashMap<String, String>,
555}
556#[allow(dead_code)]
557impl Fixture {
558 pub fn new() -> Self {
560 Self {
561 data: std::collections::HashMap::new(),
562 }
563 }
564 pub fn set(&mut self, key: impl Into<String>, val: impl Into<String>) {
566 self.data.insert(key.into(), val.into());
567 }
568 pub fn get(&self, key: &str) -> Option<&str> {
570 self.data.get(key).map(|s| s.as_str())
571 }
572 pub fn len(&self) -> usize {
574 self.data.len()
575 }
576 pub fn is_empty(&self) -> bool {
578 self.len() == 0
579 }
580}
581#[allow(dead_code)]
583pub struct PathBuf {
584 components: Vec<String>,
585}
586#[allow(dead_code)]
587impl PathBuf {
588 pub fn new() -> Self {
590 Self {
591 components: Vec::new(),
592 }
593 }
594 pub fn push(&mut self, comp: impl Into<String>) {
596 self.components.push(comp.into());
597 }
598 pub fn pop(&mut self) {
600 self.components.pop();
601 }
602 pub fn as_str(&self) -> String {
604 self.components.join("/")
605 }
606 pub fn depth(&self) -> usize {
608 self.components.len()
609 }
610 pub fn clear(&mut self) {
612 self.components.clear();
613 }
614}
615#[allow(dead_code)]
617#[allow(missing_docs)]
618pub enum DecisionNode {
619 Leaf(String),
621 Branch {
623 key: String,
624 val: String,
625 yes_branch: Box<DecisionNode>,
626 no_branch: Box<DecisionNode>,
627 },
628}
629#[allow(dead_code)]
630impl DecisionNode {
631 pub fn evaluate(&self, ctx: &std::collections::HashMap<String, String>) -> &str {
633 match self {
634 DecisionNode::Leaf(action) => action.as_str(),
635 DecisionNode::Branch {
636 key,
637 val,
638 yes_branch,
639 no_branch,
640 } => {
641 let actual = ctx.get(key).map(|s| s.as_str()).unwrap_or("");
642 if actual == val.as_str() {
643 yes_branch.evaluate(ctx)
644 } else {
645 no_branch.evaluate(ctx)
646 }
647 }
648 }
649 }
650 pub fn depth(&self) -> usize {
652 match self {
653 DecisionNode::Leaf(_) => 0,
654 DecisionNode::Branch {
655 yes_branch,
656 no_branch,
657 ..
658 } => 1 + yes_branch.depth().max(no_branch.depth()),
659 }
660 }
661}
662#[allow(dead_code)]
664pub struct LabelSet {
665 labels: Vec<String>,
666}
667#[allow(dead_code)]
668impl LabelSet {
669 pub fn new() -> Self {
671 Self { labels: Vec::new() }
672 }
673 pub fn add(&mut self, label: impl Into<String>) {
675 let s = label.into();
676 if !self.labels.contains(&s) {
677 self.labels.push(s);
678 }
679 }
680 pub fn has(&self, label: &str) -> bool {
682 self.labels.iter().any(|l| l == label)
683 }
684 pub fn count(&self) -> usize {
686 self.labels.len()
687 }
688 pub fn all(&self) -> &[String] {
690 &self.labels
691 }
692}
693#[allow(dead_code)]
695pub struct NonEmptyVec<T> {
696 head: T,
697 tail: Vec<T>,
698}
699#[allow(dead_code)]
700impl<T> NonEmptyVec<T> {
701 pub fn singleton(val: T) -> Self {
703 Self {
704 head: val,
705 tail: Vec::new(),
706 }
707 }
708 pub fn push(&mut self, val: T) {
710 self.tail.push(val);
711 }
712 pub fn first(&self) -> &T {
714 &self.head
715 }
716 pub fn last(&self) -> &T {
718 self.tail.last().unwrap_or(&self.head)
719 }
720 pub fn len(&self) -> usize {
722 1 + self.tail.len()
723 }
724 pub fn is_empty(&self) -> bool {
726 self.len() == 0
727 }
728 pub fn to_vec(&self) -> Vec<&T> {
730 let mut v = vec![&self.head];
731 v.extend(self.tail.iter());
732 v
733 }
734}
735#[allow(dead_code)]
737pub struct SmallMap<K: Ord + Clone, V: Clone> {
738 entries: Vec<(K, V)>,
739}
740#[allow(dead_code)]
741impl<K: Ord + Clone, V: Clone> SmallMap<K, V> {
742 pub fn new() -> Self {
744 Self {
745 entries: Vec::new(),
746 }
747 }
748 pub fn insert(&mut self, key: K, val: V) {
750 match self.entries.binary_search_by_key(&&key, |(k, _)| k) {
751 Ok(i) => self.entries[i].1 = val,
752 Err(i) => self.entries.insert(i, (key, val)),
753 }
754 }
755 pub fn get(&self, key: &K) -> Option<&V> {
757 self.entries
758 .binary_search_by_key(&key, |(k, _)| k)
759 .ok()
760 .map(|i| &self.entries[i].1)
761 }
762 pub fn len(&self) -> usize {
764 self.entries.len()
765 }
766 pub fn is_empty(&self) -> bool {
768 self.entries.is_empty()
769 }
770 pub fn keys(&self) -> Vec<&K> {
772 self.entries.iter().map(|(k, _)| k).collect()
773 }
774 pub fn values(&self) -> Vec<&V> {
776 self.entries.iter().map(|(_, v)| v).collect()
777 }
778}
779#[allow(dead_code)]
781pub struct FlatSubstitution {
782 pairs: Vec<(String, String)>,
783}
784#[allow(dead_code)]
785impl FlatSubstitution {
786 pub fn new() -> Self {
788 Self { pairs: Vec::new() }
789 }
790 pub fn add(&mut self, from: impl Into<String>, to: impl Into<String>) {
792 self.pairs.push((from.into(), to.into()));
793 }
794 pub fn apply(&self, s: &str) -> String {
796 let mut result = s.to_string();
797 for (from, to) in &self.pairs {
798 result = result.replace(from.as_str(), to.as_str());
799 }
800 result
801 }
802 pub fn len(&self) -> usize {
804 self.pairs.len()
805 }
806 pub fn is_empty(&self) -> bool {
808 self.pairs.is_empty()
809 }
810}
811#[allow(dead_code)]
813pub struct SimpleDag {
814 edges: Vec<Vec<usize>>,
816}
817#[allow(dead_code)]
818impl SimpleDag {
819 pub fn new(n: usize) -> Self {
821 Self {
822 edges: vec![Vec::new(); n],
823 }
824 }
825 pub fn add_edge(&mut self, from: usize, to: usize) {
827 if from < self.edges.len() {
828 self.edges[from].push(to);
829 }
830 }
831 pub fn successors(&self, node: usize) -> &[usize] {
833 self.edges.get(node).map(|v| v.as_slice()).unwrap_or(&[])
834 }
835 pub fn can_reach(&self, from: usize, to: usize) -> bool {
837 let mut visited = vec![false; self.edges.len()];
838 self.dfs(from, to, &mut visited)
839 }
840 fn dfs(&self, cur: usize, target: usize, visited: &mut Vec<bool>) -> bool {
841 if cur == target {
842 return true;
843 }
844 if cur >= visited.len() || visited[cur] {
845 return false;
846 }
847 visited[cur] = true;
848 for &next in self.successors(cur) {
849 if self.dfs(next, target, visited) {
850 return true;
851 }
852 }
853 false
854 }
855 pub fn topological_sort(&self) -> Option<Vec<usize>> {
857 let n = self.edges.len();
858 let mut in_degree = vec![0usize; n];
859 for succs in &self.edges {
860 for &s in succs {
861 if s < n {
862 in_degree[s] += 1;
863 }
864 }
865 }
866 let mut queue: std::collections::VecDeque<usize> =
867 (0..n).filter(|&i| in_degree[i] == 0).collect();
868 let mut order = Vec::new();
869 while let Some(node) = queue.pop_front() {
870 order.push(node);
871 for &s in self.successors(node) {
872 if s < n {
873 in_degree[s] -= 1;
874 if in_degree[s] == 0 {
875 queue.push_back(s);
876 }
877 }
878 }
879 }
880 if order.len() == n {
881 Some(order)
882 } else {
883 None
884 }
885 }
886 pub fn num_nodes(&self) -> usize {
888 self.edges.len()
889 }
890}
891#[allow(dead_code)]
893pub struct TransitiveClosure {
894 adj: Vec<Vec<usize>>,
895 n: usize,
896}
897#[allow(dead_code)]
898impl TransitiveClosure {
899 pub fn new(n: usize) -> Self {
901 Self {
902 adj: vec![Vec::new(); n],
903 n,
904 }
905 }
906 pub fn add_edge(&mut self, from: usize, to: usize) {
908 if from < self.n {
909 self.adj[from].push(to);
910 }
911 }
912 pub fn reachable_from(&self, start: usize) -> Vec<usize> {
914 let mut visited = vec![false; self.n];
915 let mut queue = std::collections::VecDeque::new();
916 queue.push_back(start);
917 while let Some(node) = queue.pop_front() {
918 if node >= self.n || visited[node] {
919 continue;
920 }
921 visited[node] = true;
922 for &next in &self.adj[node] {
923 queue.push_back(next);
924 }
925 }
926 (0..self.n).filter(|&i| visited[i]).collect()
927 }
928 pub fn can_reach(&self, from: usize, to: usize) -> bool {
930 self.reachable_from(from).contains(&to)
931 }
932}
933#[allow(dead_code)]
935pub struct RawFnPtr {
936 ptr: usize,
938 arity: usize,
939 name: String,
940}
941#[allow(dead_code)]
942impl RawFnPtr {
943 pub fn new(ptr: usize, arity: usize, name: impl Into<String>) -> Self {
945 Self {
946 ptr,
947 arity,
948 name: name.into(),
949 }
950 }
951 pub fn arity(&self) -> usize {
953 self.arity
954 }
955 pub fn name(&self) -> &str {
957 &self.name
958 }
959 pub fn raw(&self) -> usize {
961 self.ptr
962 }
963}
964#[allow(dead_code)]
966pub struct WindowIterator<'a, T> {
967 pub(super) data: &'a [T],
968 pub(super) pos: usize,
969 pub(super) window: usize,
970}
971#[allow(dead_code)]
972impl<'a, T> WindowIterator<'a, T> {
973 pub fn new(data: &'a [T], window: usize) -> Self {
975 Self {
976 data,
977 pos: 0,
978 window,
979 }
980 }
981}
982#[allow(dead_code)]
984pub struct Stopwatch {
985 start: crate::wall_clock::Instant,
986 splits: Vec<f64>,
987}
988#[allow(dead_code)]
989impl Stopwatch {
990 pub fn start() -> Self {
992 Self {
993 start: crate::wall_clock::Instant::now(),
994 splits: Vec::new(),
995 }
996 }
997 pub fn split(&mut self) {
999 self.splits.push(self.elapsed_ms());
1000 }
1001 pub fn elapsed_ms(&self) -> f64 {
1003 self.start.elapsed().as_secs_f64() * 1000.0
1004 }
1005 pub fn splits(&self) -> &[f64] {
1007 &self.splits
1008 }
1009 pub fn num_splits(&self) -> usize {
1011 self.splits.len()
1012 }
1013}
1014#[allow(dead_code)]
1016pub struct ConfigNode {
1017 key: String,
1018 value: Option<String>,
1019 children: Vec<ConfigNode>,
1020}
1021#[allow(dead_code)]
1022impl ConfigNode {
1023 pub fn leaf(key: impl Into<String>, value: impl Into<String>) -> Self {
1025 Self {
1026 key: key.into(),
1027 value: Some(value.into()),
1028 children: Vec::new(),
1029 }
1030 }
1031 pub fn section(key: impl Into<String>) -> Self {
1033 Self {
1034 key: key.into(),
1035 value: None,
1036 children: Vec::new(),
1037 }
1038 }
1039 pub fn add_child(&mut self, child: ConfigNode) {
1041 self.children.push(child);
1042 }
1043 pub fn key(&self) -> &str {
1045 &self.key
1046 }
1047 pub fn value(&self) -> Option<&str> {
1049 self.value.as_deref()
1050 }
1051 pub fn num_children(&self) -> usize {
1053 self.children.len()
1054 }
1055 pub fn lookup(&self, path: &str) -> Option<&str> {
1057 let mut parts = path.splitn(2, '.');
1058 let head = parts.next()?;
1059 let tail = parts.next();
1060 if head != self.key {
1061 return None;
1062 }
1063 match tail {
1064 None => self.value.as_deref(),
1065 Some(rest) => self.children.iter().find_map(|c| c.lookup_relative(rest)),
1066 }
1067 }
1068 fn lookup_relative(&self, path: &str) -> Option<&str> {
1069 let mut parts = path.splitn(2, '.');
1070 let head = parts.next()?;
1071 let tail = parts.next();
1072 if head != self.key {
1073 return None;
1074 }
1075 match tail {
1076 None => self.value.as_deref(),
1077 Some(rest) => self.children.iter().find_map(|c| c.lookup_relative(rest)),
1078 }
1079 }
1080}
1081#[allow(dead_code)]
1083pub struct MinHeap<T: Ord> {
1084 data: Vec<T>,
1085}
1086#[allow(dead_code)]
1087impl<T: Ord> MinHeap<T> {
1088 pub fn new() -> Self {
1090 Self { data: Vec::new() }
1091 }
1092 pub fn push(&mut self, val: T) {
1094 self.data.push(val);
1095 self.sift_up(self.data.len() - 1);
1096 }
1097 pub fn pop(&mut self) -> Option<T> {
1099 if self.data.is_empty() {
1100 return None;
1101 }
1102 let n = self.data.len();
1103 self.data.swap(0, n - 1);
1104 let min = self.data.pop();
1105 if !self.data.is_empty() {
1106 self.sift_down(0);
1107 }
1108 min
1109 }
1110 pub fn peek(&self) -> Option<&T> {
1112 self.data.first()
1113 }
1114 pub fn len(&self) -> usize {
1116 self.data.len()
1117 }
1118 pub fn is_empty(&self) -> bool {
1120 self.data.is_empty()
1121 }
1122 fn sift_up(&mut self, mut i: usize) {
1123 while i > 0 {
1124 let parent = (i - 1) / 2;
1125 if self.data[i] < self.data[parent] {
1126 self.data.swap(i, parent);
1127 i = parent;
1128 } else {
1129 break;
1130 }
1131 }
1132 }
1133 fn sift_down(&mut self, mut i: usize) {
1134 let n = self.data.len();
1135 loop {
1136 let left = 2 * i + 1;
1137 let right = 2 * i + 2;
1138 let mut smallest = i;
1139 if left < n && self.data[left] < self.data[smallest] {
1140 smallest = left;
1141 }
1142 if right < n && self.data[right] < self.data[smallest] {
1143 smallest = right;
1144 }
1145 if smallest == i {
1146 break;
1147 }
1148 self.data.swap(i, smallest);
1149 i = smallest;
1150 }
1151 }
1152}
1153#[allow(dead_code)]
1155pub struct StackCalc {
1156 stack: Vec<i64>,
1157}
1158#[allow(dead_code)]
1159impl StackCalc {
1160 pub fn new() -> Self {
1162 Self { stack: Vec::new() }
1163 }
1164 pub fn push(&mut self, n: i64) {
1166 self.stack.push(n);
1167 }
1168 fn apply_binary(&mut self, op: impl FnOnce(i64, i64) -> i64) -> Option<i64> {
1172 let (rest_len, a, b) = match self.stack[..] {
1173 [ref rest @ .., a, b] => (rest.len(), a, b),
1174 _ => return None,
1175 };
1176 let value = op(a, b);
1177 self.stack.truncate(rest_len);
1178 self.stack.push(value);
1179 Some(value)
1180 }
1181 pub fn add(&mut self) -> Option<i64> {
1185 self.apply_binary(|a, b| a + b)
1186 }
1187 pub fn sub(&mut self) -> Option<i64> {
1191 self.apply_binary(|a, b| a - b)
1192 }
1193 pub fn mul(&mut self) -> Option<i64> {
1197 self.apply_binary(|a, b| a * b)
1198 }
1199 pub fn peek(&self) -> Option<i64> {
1201 self.stack.last().copied()
1202 }
1203 pub fn depth(&self) -> usize {
1205 self.stack.len()
1206 }
1207}
1208#[allow(dead_code)]
1210pub struct FocusStack<T> {
1211 items: Vec<T>,
1212}
1213#[allow(dead_code)]
1214impl<T> FocusStack<T> {
1215 pub fn new() -> Self {
1217 Self { items: Vec::new() }
1218 }
1219 pub fn focus(&mut self, item: T) {
1221 self.items.push(item);
1222 }
1223 pub fn blur(&mut self) -> Option<T> {
1225 self.items.pop()
1226 }
1227 pub fn current(&self) -> Option<&T> {
1229 self.items.last()
1230 }
1231 pub fn depth(&self) -> usize {
1233 self.items.len()
1234 }
1235 pub fn is_empty(&self) -> bool {
1237 self.items.is_empty()
1238 }
1239}