1use std::collections::HashMap;
6
7#[allow(dead_code)]
9pub struct VersionedRecord<T: Clone> {
10 history: Vec<T>,
11}
12#[allow(dead_code)]
13impl<T: Clone> VersionedRecord<T> {
14 pub fn new(initial: T) -> Self {
16 Self {
17 history: vec![initial],
18 }
19 }
20 pub fn update(&mut self, val: T) {
22 self.history.push(val);
23 }
24 pub fn current(&self) -> &T {
26 self.history
27 .last()
28 .expect("VersionedRecord history is always non-empty after construction")
29 }
30 pub fn at_version(&self, n: usize) -> Option<&T> {
32 self.history.get(n)
33 }
34 pub fn version(&self) -> usize {
36 self.history.len() - 1
37 }
38 pub fn has_history(&self) -> bool {
40 self.history.len() > 1
41 }
42}
43#[allow(dead_code)]
45pub struct FlatSubstitution {
46 pairs: Vec<(String, String)>,
47}
48#[allow(dead_code)]
49impl FlatSubstitution {
50 pub fn new() -> Self {
52 Self { pairs: Vec::new() }
53 }
54 pub fn add(&mut self, from: impl Into<String>, to: impl Into<String>) {
56 self.pairs.push((from.into(), to.into()));
57 }
58 pub fn apply(&self, s: &str) -> String {
60 let mut result = s.to_string();
61 for (from, to) in &self.pairs {
62 result = result.replace(from.as_str(), to.as_str());
63 }
64 result
65 }
66 pub fn len(&self) -> usize {
68 self.pairs.len()
69 }
70 pub fn is_empty(&self) -> bool {
72 self.pairs.is_empty()
73 }
74}
75#[allow(dead_code)]
77#[allow(missing_docs)]
78pub struct RewriteRule {
79 pub name: String,
81 pub lhs: String,
83 pub rhs: String,
85 pub conditional: bool,
87}
88#[allow(dead_code)]
89impl RewriteRule {
90 pub fn unconditional(
92 name: impl Into<String>,
93 lhs: impl Into<String>,
94 rhs: impl Into<String>,
95 ) -> Self {
96 Self {
97 name: name.into(),
98 lhs: lhs.into(),
99 rhs: rhs.into(),
100 conditional: false,
101 }
102 }
103 pub fn conditional(
105 name: impl Into<String>,
106 lhs: impl Into<String>,
107 rhs: impl Into<String>,
108 ) -> Self {
109 Self {
110 name: name.into(),
111 lhs: lhs.into(),
112 rhs: rhs.into(),
113 conditional: true,
114 }
115 }
116 pub fn display(&self) -> String {
118 format!("{}: {} → {}", self.name, self.lhs, self.rhs)
119 }
120}
121#[allow(dead_code)]
123pub struct TokenBucket {
124 capacity: u64,
125 tokens: u64,
126 refill_per_ms: u64,
127 last_refill: std::time::Instant,
128}
129#[allow(dead_code)]
130impl TokenBucket {
131 pub fn new(capacity: u64, refill_per_ms: u64) -> Self {
133 Self {
134 capacity,
135 tokens: capacity,
136 refill_per_ms,
137 last_refill: std::time::Instant::now(),
138 }
139 }
140 pub fn try_consume(&mut self, n: u64) -> bool {
142 self.refill();
143 if self.tokens >= n {
144 self.tokens -= n;
145 true
146 } else {
147 false
148 }
149 }
150 fn refill(&mut self) {
151 let now = std::time::Instant::now();
152 let elapsed_ms = now.duration_since(self.last_refill).as_millis() as u64;
153 if elapsed_ms > 0 {
154 let new_tokens = elapsed_ms * self.refill_per_ms;
155 self.tokens = (self.tokens + new_tokens).min(self.capacity);
156 self.last_refill = now;
157 }
158 }
159 pub fn available(&self) -> u64 {
161 self.tokens
162 }
163 pub fn capacity(&self) -> u64 {
165 self.capacity
166 }
167}
168#[allow(dead_code)]
170pub struct Fixture {
171 data: std::collections::HashMap<String, String>,
172}
173#[allow(dead_code)]
174impl Fixture {
175 pub fn new() -> Self {
177 Self {
178 data: std::collections::HashMap::new(),
179 }
180 }
181 pub fn set(&mut self, key: impl Into<String>, val: impl Into<String>) {
183 self.data.insert(key.into(), val.into());
184 }
185 pub fn get(&self, key: &str) -> Option<&str> {
187 self.data.get(key).map(|s| s.as_str())
188 }
189 pub fn len(&self) -> usize {
191 self.data.len()
192 }
193 pub fn is_empty(&self) -> bool {
195 self.len() == 0
196 }
197}
198#[allow(dead_code)]
200pub struct NonEmptyVec<T> {
201 head: T,
202 tail: Vec<T>,
203}
204#[allow(dead_code)]
205impl<T> NonEmptyVec<T> {
206 pub fn singleton(val: T) -> Self {
208 Self {
209 head: val,
210 tail: Vec::new(),
211 }
212 }
213 pub fn push(&mut self, val: T) {
215 self.tail.push(val);
216 }
217 pub fn first(&self) -> &T {
219 &self.head
220 }
221 pub fn last(&self) -> &T {
223 self.tail.last().unwrap_or(&self.head)
224 }
225 pub fn len(&self) -> usize {
227 1 + self.tail.len()
228 }
229 pub fn is_empty(&self) -> bool {
231 self.len() == 0
232 }
233 pub fn to_vec(&self) -> Vec<&T> {
235 let mut v = vec![&self.head];
236 v.extend(self.tail.iter());
237 v
238 }
239}
240#[allow(dead_code)]
242pub struct RawFnPtr {
243 ptr: usize,
245 arity: usize,
246 name: String,
247}
248#[allow(dead_code)]
249impl RawFnPtr {
250 pub fn new(ptr: usize, arity: usize, name: impl Into<String>) -> Self {
252 Self {
253 ptr,
254 arity,
255 name: name.into(),
256 }
257 }
258 pub fn arity(&self) -> usize {
260 self.arity
261 }
262 pub fn name(&self) -> &str {
264 &self.name
265 }
266 pub fn raw(&self) -> usize {
268 self.ptr
269 }
270}
271#[allow(dead_code)]
273pub struct StringPool {
274 free: Vec<String>,
275}
276#[allow(dead_code)]
277impl StringPool {
278 pub fn new() -> Self {
280 Self { free: Vec::new() }
281 }
282 pub fn take(&mut self) -> String {
284 self.free.pop().unwrap_or_default()
285 }
286 pub fn give(&mut self, mut s: String) {
288 s.clear();
289 self.free.push(s);
290 }
291 pub fn free_count(&self) -> usize {
293 self.free.len()
294 }
295}
296#[allow(dead_code)]
298pub struct LabelSet {
299 labels: Vec<String>,
300}
301#[allow(dead_code)]
302impl LabelSet {
303 pub fn new() -> Self {
305 Self { labels: Vec::new() }
306 }
307 pub fn add(&mut self, label: impl Into<String>) {
309 let s = label.into();
310 if !self.labels.contains(&s) {
311 self.labels.push(s);
312 }
313 }
314 pub fn has(&self, label: &str) -> bool {
316 self.labels.iter().any(|l| l == label)
317 }
318 pub fn count(&self) -> usize {
320 self.labels.len()
321 }
322 pub fn all(&self) -> &[String] {
324 &self.labels
325 }
326}
327#[allow(dead_code)]
329pub struct SparseVec<T: Default + Clone + PartialEq> {
330 entries: std::collections::HashMap<usize, T>,
331 default_: T,
332 logical_len: usize,
333}
334#[allow(dead_code)]
335impl<T: Default + Clone + PartialEq> SparseVec<T> {
336 pub fn new(len: usize) -> Self {
338 Self {
339 entries: std::collections::HashMap::new(),
340 default_: T::default(),
341 logical_len: len,
342 }
343 }
344 pub fn set(&mut self, idx: usize, val: T) {
346 if val == self.default_ {
347 self.entries.remove(&idx);
348 } else {
349 self.entries.insert(idx, val);
350 }
351 }
352 pub fn get(&self, idx: usize) -> &T {
354 self.entries.get(&idx).unwrap_or(&self.default_)
355 }
356 pub fn len(&self) -> usize {
358 self.logical_len
359 }
360 pub fn is_empty(&self) -> bool {
362 self.len() == 0
363 }
364 pub fn nnz(&self) -> usize {
366 self.entries.len()
367 }
368}
369#[allow(dead_code)]
371pub struct Stopwatch {
372 start: std::time::Instant,
373 splits: Vec<f64>,
374}
375#[allow(dead_code)]
376impl Stopwatch {
377 pub fn start() -> Self {
379 Self {
380 start: std::time::Instant::now(),
381 splits: Vec::new(),
382 }
383 }
384 pub fn split(&mut self) {
386 self.splits.push(self.elapsed_ms());
387 }
388 pub fn elapsed_ms(&self) -> f64 {
390 self.start.elapsed().as_secs_f64() * 1000.0
391 }
392 pub fn splits(&self) -> &[f64] {
394 &self.splits
395 }
396 pub fn num_splits(&self) -> usize {
398 self.splits.len()
399 }
400}
401#[allow(dead_code)]
403pub enum Either2<A, B> {
404 First(A),
406 Second(B),
408}
409#[allow(dead_code)]
410impl<A, B> Either2<A, B> {
411 pub fn is_first(&self) -> bool {
413 matches!(self, Either2::First(_))
414 }
415 pub fn is_second(&self) -> bool {
417 matches!(self, Either2::Second(_))
418 }
419 pub fn first(self) -> Option<A> {
421 match self {
422 Either2::First(a) => Some(a),
423 _ => None,
424 }
425 }
426 pub fn second(self) -> Option<B> {
428 match self {
429 Either2::Second(b) => Some(b),
430 _ => None,
431 }
432 }
433 pub fn map_first<C, F: FnOnce(A) -> C>(self, f: F) -> Either2<C, B> {
435 match self {
436 Either2::First(a) => Either2::First(f(a)),
437 Either2::Second(b) => Either2::Second(b),
438 }
439 }
440}
441#[allow(dead_code)]
443pub struct SlidingSum {
444 window: Vec<f64>,
445 capacity: usize,
446 pos: usize,
447 sum: f64,
448 count: usize,
449}
450#[allow(dead_code)]
451impl SlidingSum {
452 pub fn new(capacity: usize) -> Self {
454 Self {
455 window: vec![0.0; capacity],
456 capacity,
457 pos: 0,
458 sum: 0.0,
459 count: 0,
460 }
461 }
462 pub fn push(&mut self, val: f64) {
464 let oldest = self.window[self.pos];
465 self.sum -= oldest;
466 self.sum += val;
467 self.window[self.pos] = val;
468 self.pos = (self.pos + 1) % self.capacity;
469 if self.count < self.capacity {
470 self.count += 1;
471 }
472 }
473 pub fn sum(&self) -> f64 {
475 self.sum
476 }
477 pub fn mean(&self) -> Option<f64> {
479 if self.count == 0 {
480 None
481 } else {
482 Some(self.sum / self.count as f64)
483 }
484 }
485 pub fn count(&self) -> usize {
487 self.count
488 }
489}
490#[allow(dead_code)]
492pub struct ConfigNode {
493 key: String,
494 value: Option<String>,
495 children: Vec<ConfigNode>,
496}
497#[allow(dead_code)]
498impl ConfigNode {
499 pub fn leaf(key: impl Into<String>, value: impl Into<String>) -> Self {
501 Self {
502 key: key.into(),
503 value: Some(value.into()),
504 children: Vec::new(),
505 }
506 }
507 pub fn section(key: impl Into<String>) -> Self {
509 Self {
510 key: key.into(),
511 value: None,
512 children: Vec::new(),
513 }
514 }
515 pub fn add_child(&mut self, child: ConfigNode) {
517 self.children.push(child);
518 }
519 pub fn key(&self) -> &str {
521 &self.key
522 }
523 pub fn value(&self) -> Option<&str> {
525 self.value.as_deref()
526 }
527 pub fn num_children(&self) -> usize {
529 self.children.len()
530 }
531 pub fn lookup(&self, path: &str) -> Option<&str> {
533 let mut parts = path.splitn(2, '.');
534 let head = parts.next()?;
535 let tail = parts.next();
536 if head != self.key {
537 return None;
538 }
539 match tail {
540 None => self.value.as_deref(),
541 Some(rest) => self.children.iter().find_map(|c| c.lookup_relative(rest)),
542 }
543 }
544 fn lookup_relative(&self, path: &str) -> Option<&str> {
545 let mut parts = path.splitn(2, '.');
546 let head = parts.next()?;
547 let tail = parts.next();
548 if head != self.key {
549 return None;
550 }
551 match tail {
552 None => self.value.as_deref(),
553 Some(rest) => self.children.iter().find_map(|c| c.lookup_relative(rest)),
554 }
555 }
556}
557#[allow(dead_code)]
559pub struct StatSummary {
560 count: u64,
561 sum: f64,
562 min: f64,
563 max: f64,
564}
565#[allow(dead_code)]
566impl StatSummary {
567 pub fn new() -> Self {
569 Self {
570 count: 0,
571 sum: 0.0,
572 min: f64::INFINITY,
573 max: f64::NEG_INFINITY,
574 }
575 }
576 pub fn record(&mut self, val: f64) {
578 self.count += 1;
579 self.sum += val;
580 if val < self.min {
581 self.min = val;
582 }
583 if val > self.max {
584 self.max = val;
585 }
586 }
587 pub fn mean(&self) -> Option<f64> {
589 if self.count == 0 {
590 None
591 } else {
592 Some(self.sum / self.count as f64)
593 }
594 }
595 pub fn min(&self) -> Option<f64> {
597 if self.count == 0 {
598 None
599 } else {
600 Some(self.min)
601 }
602 }
603 pub fn max(&self) -> Option<f64> {
605 if self.count == 0 {
606 None
607 } else {
608 Some(self.max)
609 }
610 }
611 pub fn count(&self) -> u64 {
613 self.count
614 }
615}
616#[allow(dead_code)]
618pub struct TransformStat {
619 before: StatSummary,
620 after: StatSummary,
621}
622#[allow(dead_code)]
623impl TransformStat {
624 pub fn new() -> Self {
626 Self {
627 before: StatSummary::new(),
628 after: StatSummary::new(),
629 }
630 }
631 pub fn record_before(&mut self, v: f64) {
633 self.before.record(v);
634 }
635 pub fn record_after(&mut self, v: f64) {
637 self.after.record(v);
638 }
639 pub fn mean_ratio(&self) -> Option<f64> {
641 let b = self.before.mean()?;
642 let a = self.after.mean()?;
643 if b.abs() < f64::EPSILON {
644 return None;
645 }
646 Some(a / b)
647 }
648}
649#[allow(dead_code)]
651pub struct WindowIterator<'a, T> {
652 pub(super) data: &'a [T],
653 pub(super) pos: usize,
654 pub(super) window: usize,
655}
656#[allow(dead_code)]
657impl<'a, T> WindowIterator<'a, T> {
658 pub fn new(data: &'a [T], window: usize) -> Self {
660 Self {
661 data,
662 pos: 0,
663 window,
664 }
665 }
666}
667#[allow(dead_code)]
669pub struct RewriteRuleSet {
670 rules: Vec<RewriteRule>,
671}
672#[allow(dead_code)]
673impl RewriteRuleSet {
674 pub fn new() -> Self {
676 Self { rules: Vec::new() }
677 }
678 pub fn add(&mut self, rule: RewriteRule) {
680 self.rules.push(rule);
681 }
682 pub fn len(&self) -> usize {
684 self.rules.len()
685 }
686 pub fn is_empty(&self) -> bool {
688 self.rules.is_empty()
689 }
690 pub fn conditional_rules(&self) -> Vec<&RewriteRule> {
692 self.rules.iter().filter(|r| r.conditional).collect()
693 }
694 pub fn unconditional_rules(&self) -> Vec<&RewriteRule> {
696 self.rules.iter().filter(|r| !r.conditional).collect()
697 }
698 pub fn get(&self, name: &str) -> Option<&RewriteRule> {
700 self.rules.iter().find(|r| r.name == name)
701 }
702}
703#[allow(dead_code)]
705pub struct TransitiveClosure {
706 adj: Vec<Vec<usize>>,
707 n: usize,
708}
709#[allow(dead_code)]
710impl TransitiveClosure {
711 pub fn new(n: usize) -> Self {
713 Self {
714 adj: vec![Vec::new(); n],
715 n,
716 }
717 }
718 pub fn add_edge(&mut self, from: usize, to: usize) {
720 if from < self.n {
721 self.adj[from].push(to);
722 }
723 }
724 pub fn reachable_from(&self, start: usize) -> Vec<usize> {
726 let mut visited = vec![false; self.n];
727 let mut queue = std::collections::VecDeque::new();
728 queue.push_back(start);
729 while let Some(node) = queue.pop_front() {
730 if node >= self.n || visited[node] {
731 continue;
732 }
733 visited[node] = true;
734 for &next in &self.adj[node] {
735 queue.push_back(next);
736 }
737 }
738 (0..self.n).filter(|&i| visited[i]).collect()
739 }
740 pub fn can_reach(&self, from: usize, to: usize) -> bool {
742 self.reachable_from(from).contains(&to)
743 }
744}
745#[allow(dead_code)]
747#[allow(missing_docs)]
748pub enum DecisionNode {
749 Leaf(String),
751 Branch {
753 key: String,
754 val: String,
755 yes_branch: Box<DecisionNode>,
756 no_branch: Box<DecisionNode>,
757 },
758}
759#[allow(dead_code)]
760impl DecisionNode {
761 pub fn evaluate(&self, ctx: &std::collections::HashMap<String, String>) -> &str {
763 match self {
764 DecisionNode::Leaf(action) => action.as_str(),
765 DecisionNode::Branch {
766 key,
767 val,
768 yes_branch,
769 no_branch,
770 } => {
771 let actual = ctx.get(key).map(|s| s.as_str()).unwrap_or("");
772 if actual == val.as_str() {
773 yes_branch.evaluate(ctx)
774 } else {
775 no_branch.evaluate(ctx)
776 }
777 }
778 }
779 }
780 pub fn depth(&self) -> usize {
782 match self {
783 DecisionNode::Leaf(_) => 0,
784 DecisionNode::Branch {
785 yes_branch,
786 no_branch,
787 ..
788 } => 1 + yes_branch.depth().max(no_branch.depth()),
789 }
790 }
791}
792#[allow(dead_code)]
794pub struct SimpleDag {
795 edges: Vec<Vec<usize>>,
797}
798#[allow(dead_code)]
799impl SimpleDag {
800 pub fn new(n: usize) -> Self {
802 Self {
803 edges: vec![Vec::new(); n],
804 }
805 }
806 pub fn add_edge(&mut self, from: usize, to: usize) {
808 if from < self.edges.len() {
809 self.edges[from].push(to);
810 }
811 }
812 pub fn successors(&self, node: usize) -> &[usize] {
814 self.edges.get(node).map(|v| v.as_slice()).unwrap_or(&[])
815 }
816 pub fn can_reach(&self, from: usize, to: usize) -> bool {
818 let mut visited = vec![false; self.edges.len()];
819 self.dfs(from, to, &mut visited)
820 }
821 fn dfs(&self, cur: usize, target: usize, visited: &mut Vec<bool>) -> bool {
822 if cur == target {
823 return true;
824 }
825 if cur >= visited.len() || visited[cur] {
826 return false;
827 }
828 visited[cur] = true;
829 for &next in self.successors(cur) {
830 if self.dfs(next, target, visited) {
831 return true;
832 }
833 }
834 false
835 }
836 pub fn topological_sort(&self) -> Option<Vec<usize>> {
838 let n = self.edges.len();
839 let mut in_degree = vec![0usize; n];
840 for succs in &self.edges {
841 for &s in succs {
842 if s < n {
843 in_degree[s] += 1;
844 }
845 }
846 }
847 let mut queue: std::collections::VecDeque<usize> =
848 (0..n).filter(|&i| in_degree[i] == 0).collect();
849 let mut order = Vec::new();
850 while let Some(node) = queue.pop_front() {
851 order.push(node);
852 for &s in self.successors(node) {
853 if s < n {
854 in_degree[s] -= 1;
855 if in_degree[s] == 0 {
856 queue.push_back(s);
857 }
858 }
859 }
860 }
861 if order.len() == n {
862 Some(order)
863 } else {
864 None
865 }
866 }
867 pub fn num_nodes(&self) -> usize {
869 self.edges.len()
870 }
871}
872#[allow(dead_code)]
874pub struct WriteOnce<T> {
875 value: std::cell::Cell<Option<T>>,
876}
877#[allow(dead_code)]
878impl<T: Copy> WriteOnce<T> {
879 pub fn new() -> Self {
881 Self {
882 value: std::cell::Cell::new(None),
883 }
884 }
885 pub fn write(&self, val: T) -> bool {
887 if self.value.get().is_some() {
888 return false;
889 }
890 self.value.set(Some(val));
891 true
892 }
893 pub fn read(&self) -> Option<T> {
895 self.value.get()
896 }
897 pub fn is_written(&self) -> bool {
899 self.value.get().is_some()
900 }
901}
902#[allow(dead_code)]
904pub struct StackCalc {
905 stack: Vec<i64>,
906}
907#[allow(dead_code)]
908impl StackCalc {
909 pub fn new() -> Self {
911 Self { stack: Vec::new() }
912 }
913 pub fn push(&mut self, n: i64) {
915 self.stack.push(n);
916 }
917 pub fn add(&mut self) {
919 let b = self
920 .stack
921 .pop()
922 .expect("stack must have at least two values for add");
923 let a = self
924 .stack
925 .pop()
926 .expect("stack must have at least two values for add");
927 self.stack.push(a + b);
928 }
929 pub fn sub(&mut self) {
931 let b = self
932 .stack
933 .pop()
934 .expect("stack must have at least two values for sub");
935 let a = self
936 .stack
937 .pop()
938 .expect("stack must have at least two values for sub");
939 self.stack.push(a - b);
940 }
941 pub fn mul(&mut self) {
943 let b = self
944 .stack
945 .pop()
946 .expect("stack must have at least two values for mul");
947 let a = self
948 .stack
949 .pop()
950 .expect("stack must have at least two values for mul");
951 self.stack.push(a * b);
952 }
953 pub fn peek(&self) -> Option<i64> {
955 self.stack.last().copied()
956 }
957 pub fn depth(&self) -> usize {
959 self.stack.len()
960 }
961}
962#[allow(dead_code)]
964pub struct PrefixCounter {
965 children: std::collections::HashMap<char, PrefixCounter>,
966 count: usize,
967}
968#[allow(dead_code)]
969impl PrefixCounter {
970 pub fn new() -> Self {
972 Self {
973 children: std::collections::HashMap::new(),
974 count: 0,
975 }
976 }
977 pub fn record(&mut self, s: &str) {
979 self.count += 1;
980 let mut node = self;
981 for c in s.chars() {
982 node = node.children.entry(c).or_default();
983 node.count += 1;
984 }
985 }
986 pub fn count_with_prefix(&self, prefix: &str) -> usize {
988 let mut node = self;
989 for c in prefix.chars() {
990 match node.children.get(&c) {
991 Some(n) => node = n,
992 None => return 0,
993 }
994 }
995 node.count
996 }
997}
998#[allow(dead_code)]
1000pub struct SmallMap<K: Ord + Clone, V: Clone> {
1001 entries: Vec<(K, V)>,
1002}
1003#[allow(dead_code)]
1004impl<K: Ord + Clone, V: Clone> SmallMap<K, V> {
1005 pub fn new() -> Self {
1007 Self {
1008 entries: Vec::new(),
1009 }
1010 }
1011 pub fn insert(&mut self, key: K, val: V) {
1013 match self.entries.binary_search_by_key(&&key, |(k, _)| k) {
1014 Ok(i) => self.entries[i].1 = val,
1015 Err(i) => self.entries.insert(i, (key, val)),
1016 }
1017 }
1018 pub fn get(&self, key: &K) -> Option<&V> {
1020 self.entries
1021 .binary_search_by_key(&key, |(k, _)| k)
1022 .ok()
1023 .map(|i| &self.entries[i].1)
1024 }
1025 pub fn len(&self) -> usize {
1027 self.entries.len()
1028 }
1029 pub fn is_empty(&self) -> bool {
1031 self.entries.is_empty()
1032 }
1033 pub fn keys(&self) -> Vec<&K> {
1035 self.entries.iter().map(|(k, _)| k).collect()
1036 }
1037 pub fn values(&self) -> Vec<&V> {
1039 self.entries.iter().map(|(_, v)| v).collect()
1040 }
1041}
1042#[allow(dead_code)]
1044pub struct PathBuf {
1045 components: Vec<String>,
1046}
1047#[allow(dead_code)]
1048impl PathBuf {
1049 pub fn new() -> Self {
1051 Self {
1052 components: Vec::new(),
1053 }
1054 }
1055 pub fn push(&mut self, comp: impl Into<String>) {
1057 self.components.push(comp.into());
1058 }
1059 pub fn pop(&mut self) {
1061 self.components.pop();
1062 }
1063 pub fn as_str(&self) -> String {
1065 self.components.join("/")
1066 }
1067 pub fn depth(&self) -> usize {
1069 self.components.len()
1070 }
1071 pub fn clear(&mut self) {
1073 self.components.clear();
1074 }
1075}
1076#[allow(dead_code)]
1078pub struct FocusStack<T> {
1079 items: Vec<T>,
1080}
1081#[allow(dead_code)]
1082impl<T> FocusStack<T> {
1083 pub fn new() -> Self {
1085 Self { items: Vec::new() }
1086 }
1087 pub fn focus(&mut self, item: T) {
1089 self.items.push(item);
1090 }
1091 pub fn blur(&mut self) -> Option<T> {
1093 self.items.pop()
1094 }
1095 pub fn current(&self) -> Option<&T> {
1097 self.items.last()
1098 }
1099 pub fn depth(&self) -> usize {
1101 self.items.len()
1102 }
1103 pub fn is_empty(&self) -> bool {
1105 self.items.is_empty()
1106 }
1107}
1108#[allow(dead_code)]
1110pub struct MinHeap<T: Ord> {
1111 data: Vec<T>,
1112}
1113#[allow(dead_code)]
1114impl<T: Ord> MinHeap<T> {
1115 pub fn new() -> Self {
1117 Self { data: Vec::new() }
1118 }
1119 pub fn push(&mut self, val: T) {
1121 self.data.push(val);
1122 self.sift_up(self.data.len() - 1);
1123 }
1124 pub fn pop(&mut self) -> Option<T> {
1126 if self.data.is_empty() {
1127 return None;
1128 }
1129 let n = self.data.len();
1130 self.data.swap(0, n - 1);
1131 let min = self.data.pop();
1132 if !self.data.is_empty() {
1133 self.sift_down(0);
1134 }
1135 min
1136 }
1137 pub fn peek(&self) -> Option<&T> {
1139 self.data.first()
1140 }
1141 pub fn len(&self) -> usize {
1143 self.data.len()
1144 }
1145 pub fn is_empty(&self) -> bool {
1147 self.data.is_empty()
1148 }
1149 fn sift_up(&mut self, mut i: usize) {
1150 while i > 0 {
1151 let parent = (i - 1) / 2;
1152 if self.data[i] < self.data[parent] {
1153 self.data.swap(i, parent);
1154 i = parent;
1155 } else {
1156 break;
1157 }
1158 }
1159 }
1160 fn sift_down(&mut self, mut i: usize) {
1161 let n = self.data.len();
1162 loop {
1163 let left = 2 * i + 1;
1164 let right = 2 * i + 2;
1165 let mut smallest = i;
1166 if left < n && self.data[left] < self.data[smallest] {
1167 smallest = left;
1168 }
1169 if right < n && self.data[right] < self.data[smallest] {
1170 smallest = right;
1171 }
1172 if smallest == i {
1173 break;
1174 }
1175 self.data.swap(i, smallest);
1176 i = smallest;
1177 }
1178 }
1179}