1use std::collections::HashMap;
6
7#[allow(dead_code)]
9pub struct VersionedRecord<T: Clone> {
10 earlier: Vec<T>,
12 current: T,
14}
15#[allow(dead_code)]
16impl<T: Clone> VersionedRecord<T> {
17 pub fn new(initial: T) -> Self {
19 Self {
20 earlier: Vec::new(),
21 current: initial,
22 }
23 }
24 pub fn update(&mut self, val: T) {
26 let previous = std::mem::replace(&mut self.current, val);
27 self.earlier.push(previous);
28 }
29 pub fn current(&self) -> &T {
31 &self.current
32 }
33 pub fn at_version(&self, n: usize) -> Option<&T> {
35 match self.earlier.get(n) {
36 Some(value) => Some(value),
37 None if n == self.earlier.len() => Some(&self.current),
38 None => None,
39 }
40 }
41 pub fn version(&self) -> usize {
43 self.earlier.len()
44 }
45 pub fn has_history(&self) -> bool {
47 !self.earlier.is_empty()
48 }
49}
50#[allow(dead_code)]
52pub struct FlatSubstitution {
53 pairs: Vec<(String, String)>,
54}
55#[allow(dead_code)]
56impl FlatSubstitution {
57 pub fn new() -> Self {
59 Self { pairs: Vec::new() }
60 }
61 pub fn add(&mut self, from: impl Into<String>, to: impl Into<String>) {
63 self.pairs.push((from.into(), to.into()));
64 }
65 pub fn apply(&self, s: &str) -> String {
67 let mut result = s.to_string();
68 for (from, to) in &self.pairs {
69 result = result.replace(from.as_str(), to.as_str());
70 }
71 result
72 }
73 pub fn len(&self) -> usize {
75 self.pairs.len()
76 }
77 pub fn is_empty(&self) -> bool {
79 self.pairs.is_empty()
80 }
81}
82#[allow(dead_code)]
84#[allow(missing_docs)]
85pub struct RewriteRule {
86 pub name: String,
88 pub lhs: String,
90 pub rhs: String,
92 pub conditional: bool,
94}
95#[allow(dead_code)]
96impl RewriteRule {
97 pub fn unconditional(
99 name: impl Into<String>,
100 lhs: impl Into<String>,
101 rhs: impl Into<String>,
102 ) -> Self {
103 Self {
104 name: name.into(),
105 lhs: lhs.into(),
106 rhs: rhs.into(),
107 conditional: false,
108 }
109 }
110 pub fn conditional(
112 name: impl Into<String>,
113 lhs: impl Into<String>,
114 rhs: impl Into<String>,
115 ) -> Self {
116 Self {
117 name: name.into(),
118 lhs: lhs.into(),
119 rhs: rhs.into(),
120 conditional: true,
121 }
122 }
123 pub fn display(&self) -> String {
125 format!("{}: {} → {}", self.name, self.lhs, self.rhs)
126 }
127}
128#[allow(dead_code)]
130pub struct TokenBucket {
131 capacity: u64,
132 tokens: u64,
133 refill_per_ms: u64,
134 last_refill: crate::wall_clock::Instant,
135}
136#[allow(dead_code)]
137impl TokenBucket {
138 pub fn new(capacity: u64, refill_per_ms: u64) -> Self {
140 Self {
141 capacity,
142 tokens: capacity,
143 refill_per_ms,
144 last_refill: crate::wall_clock::Instant::now(),
145 }
146 }
147 pub fn try_consume(&mut self, n: u64) -> bool {
149 self.refill();
150 if self.tokens >= n {
151 self.tokens -= n;
152 true
153 } else {
154 false
155 }
156 }
157 fn refill(&mut self) {
158 let now = crate::wall_clock::Instant::now();
159 let elapsed_ms = now.duration_since(self.last_refill).as_millis() as u64;
160 if elapsed_ms > 0 {
161 let new_tokens = elapsed_ms * self.refill_per_ms;
162 self.tokens = (self.tokens + new_tokens).min(self.capacity);
163 self.last_refill = now;
164 }
165 }
166 pub fn available(&self) -> u64 {
168 self.tokens
169 }
170 pub fn capacity(&self) -> u64 {
172 self.capacity
173 }
174}
175#[allow(dead_code)]
177pub struct Fixture {
178 data: std::collections::HashMap<String, String>,
179}
180#[allow(dead_code)]
181impl Fixture {
182 pub fn new() -> Self {
184 Self {
185 data: std::collections::HashMap::new(),
186 }
187 }
188 pub fn set(&mut self, key: impl Into<String>, val: impl Into<String>) {
190 self.data.insert(key.into(), val.into());
191 }
192 pub fn get(&self, key: &str) -> Option<&str> {
194 self.data.get(key).map(|s| s.as_str())
195 }
196 pub fn len(&self) -> usize {
198 self.data.len()
199 }
200 pub fn is_empty(&self) -> bool {
202 self.len() == 0
203 }
204}
205#[allow(dead_code)]
207pub struct NonEmptyVec<T> {
208 head: T,
209 tail: Vec<T>,
210}
211#[allow(dead_code)]
212impl<T> NonEmptyVec<T> {
213 pub fn singleton(val: T) -> Self {
215 Self {
216 head: val,
217 tail: Vec::new(),
218 }
219 }
220 pub fn push(&mut self, val: T) {
222 self.tail.push(val);
223 }
224 pub fn first(&self) -> &T {
226 &self.head
227 }
228 pub fn last(&self) -> &T {
230 self.tail.last().unwrap_or(&self.head)
231 }
232 pub fn len(&self) -> usize {
234 1 + self.tail.len()
235 }
236 pub fn is_empty(&self) -> bool {
238 self.len() == 0
239 }
240 pub fn to_vec(&self) -> Vec<&T> {
242 let mut v = vec![&self.head];
243 v.extend(self.tail.iter());
244 v
245 }
246}
247#[allow(dead_code)]
249pub struct RawFnPtr {
250 ptr: usize,
252 arity: usize,
253 name: String,
254}
255#[allow(dead_code)]
256impl RawFnPtr {
257 pub fn new(ptr: usize, arity: usize, name: impl Into<String>) -> Self {
259 Self {
260 ptr,
261 arity,
262 name: name.into(),
263 }
264 }
265 pub fn arity(&self) -> usize {
267 self.arity
268 }
269 pub fn name(&self) -> &str {
271 &self.name
272 }
273 pub fn raw(&self) -> usize {
275 self.ptr
276 }
277}
278#[allow(dead_code)]
280pub struct StringPool {
281 free: Vec<String>,
282}
283#[allow(dead_code)]
284impl StringPool {
285 pub fn new() -> Self {
287 Self { free: Vec::new() }
288 }
289 pub fn take(&mut self) -> String {
291 self.free.pop().unwrap_or_default()
292 }
293 pub fn give(&mut self, mut s: String) {
295 s.clear();
296 self.free.push(s);
297 }
298 pub fn free_count(&self) -> usize {
300 self.free.len()
301 }
302}
303#[allow(dead_code)]
305pub struct LabelSet {
306 labels: Vec<String>,
307}
308#[allow(dead_code)]
309impl LabelSet {
310 pub fn new() -> Self {
312 Self { labels: Vec::new() }
313 }
314 pub fn add(&mut self, label: impl Into<String>) {
316 let s = label.into();
317 if !self.labels.contains(&s) {
318 self.labels.push(s);
319 }
320 }
321 pub fn has(&self, label: &str) -> bool {
323 self.labels.iter().any(|l| l == label)
324 }
325 pub fn count(&self) -> usize {
327 self.labels.len()
328 }
329 pub fn all(&self) -> &[String] {
331 &self.labels
332 }
333}
334#[allow(dead_code)]
336pub struct SparseVec<T: Default + Clone + PartialEq> {
337 entries: std::collections::HashMap<usize, T>,
338 default_: T,
339 logical_len: usize,
340}
341#[allow(dead_code)]
342impl<T: Default + Clone + PartialEq> SparseVec<T> {
343 pub fn new(len: usize) -> Self {
345 Self {
346 entries: std::collections::HashMap::new(),
347 default_: T::default(),
348 logical_len: len,
349 }
350 }
351 pub fn set(&mut self, idx: usize, val: T) {
353 if val == self.default_ {
354 self.entries.remove(&idx);
355 } else {
356 self.entries.insert(idx, val);
357 }
358 }
359 pub fn get(&self, idx: usize) -> &T {
361 self.entries.get(&idx).unwrap_or(&self.default_)
362 }
363 pub fn len(&self) -> usize {
365 self.logical_len
366 }
367 pub fn is_empty(&self) -> bool {
369 self.len() == 0
370 }
371 pub fn nnz(&self) -> usize {
373 self.entries.len()
374 }
375}
376#[allow(dead_code)]
378pub struct Stopwatch {
379 start: crate::wall_clock::Instant,
380 splits: Vec<f64>,
381}
382#[allow(dead_code)]
383impl Stopwatch {
384 pub fn start() -> Self {
386 Self {
387 start: crate::wall_clock::Instant::now(),
388 splits: Vec::new(),
389 }
390 }
391 pub fn split(&mut self) {
393 self.splits.push(self.elapsed_ms());
394 }
395 pub fn elapsed_ms(&self) -> f64 {
397 self.start.elapsed().as_secs_f64() * 1000.0
398 }
399 pub fn splits(&self) -> &[f64] {
401 &self.splits
402 }
403 pub fn num_splits(&self) -> usize {
405 self.splits.len()
406 }
407}
408#[allow(dead_code)]
410pub enum Either2<A, B> {
411 First(A),
413 Second(B),
415}
416#[allow(dead_code)]
417impl<A, B> Either2<A, B> {
418 pub fn is_first(&self) -> bool {
420 matches!(self, Either2::First(_))
421 }
422 pub fn is_second(&self) -> bool {
424 matches!(self, Either2::Second(_))
425 }
426 pub fn first(self) -> Option<A> {
428 match self {
429 Either2::First(a) => Some(a),
430 _ => None,
431 }
432 }
433 pub fn second(self) -> Option<B> {
435 match self {
436 Either2::Second(b) => Some(b),
437 _ => None,
438 }
439 }
440 pub fn map_first<C, F: FnOnce(A) -> C>(self, f: F) -> Either2<C, B> {
442 match self {
443 Either2::First(a) => Either2::First(f(a)),
444 Either2::Second(b) => Either2::Second(b),
445 }
446 }
447}
448#[allow(dead_code)]
450pub struct SlidingSum {
451 window: Vec<f64>,
452 capacity: usize,
453 pos: usize,
454 sum: f64,
455 count: usize,
456}
457#[allow(dead_code)]
458impl SlidingSum {
459 pub fn new(capacity: usize) -> Self {
461 Self {
462 window: vec![0.0; capacity],
463 capacity,
464 pos: 0,
465 sum: 0.0,
466 count: 0,
467 }
468 }
469 pub fn push(&mut self, val: f64) {
471 let oldest = self.window[self.pos];
472 self.sum -= oldest;
473 self.sum += val;
474 self.window[self.pos] = val;
475 self.pos = (self.pos + 1) % self.capacity;
476 if self.count < self.capacity {
477 self.count += 1;
478 }
479 }
480 pub fn sum(&self) -> f64 {
482 self.sum
483 }
484 pub fn mean(&self) -> Option<f64> {
486 if self.count == 0 {
487 None
488 } else {
489 Some(self.sum / self.count as f64)
490 }
491 }
492 pub fn count(&self) -> usize {
494 self.count
495 }
496}
497#[allow(dead_code)]
499pub struct ConfigNode {
500 key: String,
501 value: Option<String>,
502 children: Vec<ConfigNode>,
503}
504#[allow(dead_code)]
505impl ConfigNode {
506 pub fn leaf(key: impl Into<String>, value: impl Into<String>) -> Self {
508 Self {
509 key: key.into(),
510 value: Some(value.into()),
511 children: Vec::new(),
512 }
513 }
514 pub fn section(key: impl Into<String>) -> Self {
516 Self {
517 key: key.into(),
518 value: None,
519 children: Vec::new(),
520 }
521 }
522 pub fn add_child(&mut self, child: ConfigNode) {
524 self.children.push(child);
525 }
526 pub fn key(&self) -> &str {
528 &self.key
529 }
530 pub fn value(&self) -> Option<&str> {
532 self.value.as_deref()
533 }
534 pub fn num_children(&self) -> usize {
536 self.children.len()
537 }
538 pub fn lookup(&self, path: &str) -> Option<&str> {
540 let mut parts = path.splitn(2, '.');
541 let head = parts.next()?;
542 let tail = parts.next();
543 if head != self.key {
544 return None;
545 }
546 match tail {
547 None => self.value.as_deref(),
548 Some(rest) => self.children.iter().find_map(|c| c.lookup_relative(rest)),
549 }
550 }
551 fn lookup_relative(&self, path: &str) -> Option<&str> {
552 let mut parts = path.splitn(2, '.');
553 let head = parts.next()?;
554 let tail = parts.next();
555 if head != self.key {
556 return None;
557 }
558 match tail {
559 None => self.value.as_deref(),
560 Some(rest) => self.children.iter().find_map(|c| c.lookup_relative(rest)),
561 }
562 }
563}
564#[allow(dead_code)]
566pub struct StatSummary {
567 count: u64,
568 sum: f64,
569 min: f64,
570 max: f64,
571}
572#[allow(dead_code)]
573impl StatSummary {
574 pub fn new() -> Self {
576 Self {
577 count: 0,
578 sum: 0.0,
579 min: f64::INFINITY,
580 max: f64::NEG_INFINITY,
581 }
582 }
583 pub fn record(&mut self, val: f64) {
585 self.count += 1;
586 self.sum += val;
587 if val < self.min {
588 self.min = val;
589 }
590 if val > self.max {
591 self.max = val;
592 }
593 }
594 pub fn mean(&self) -> Option<f64> {
596 if self.count == 0 {
597 None
598 } else {
599 Some(self.sum / self.count as f64)
600 }
601 }
602 pub fn min(&self) -> Option<f64> {
604 if self.count == 0 {
605 None
606 } else {
607 Some(self.min)
608 }
609 }
610 pub fn max(&self) -> Option<f64> {
612 if self.count == 0 {
613 None
614 } else {
615 Some(self.max)
616 }
617 }
618 pub fn count(&self) -> u64 {
620 self.count
621 }
622}
623#[allow(dead_code)]
625pub struct TransformStat {
626 before: StatSummary,
627 after: StatSummary,
628}
629#[allow(dead_code)]
630impl TransformStat {
631 pub fn new() -> Self {
633 Self {
634 before: StatSummary::new(),
635 after: StatSummary::new(),
636 }
637 }
638 pub fn record_before(&mut self, v: f64) {
640 self.before.record(v);
641 }
642 pub fn record_after(&mut self, v: f64) {
644 self.after.record(v);
645 }
646 pub fn mean_ratio(&self) -> Option<f64> {
648 let b = self.before.mean()?;
649 let a = self.after.mean()?;
650 if b.abs() < f64::EPSILON {
651 return None;
652 }
653 Some(a / b)
654 }
655}
656#[allow(dead_code)]
658pub struct WindowIterator<'a, T> {
659 pub(super) data: &'a [T],
660 pub(super) pos: usize,
661 pub(super) window: usize,
662}
663#[allow(dead_code)]
664impl<'a, T> WindowIterator<'a, T> {
665 pub fn new(data: &'a [T], window: usize) -> Self {
667 Self {
668 data,
669 pos: 0,
670 window,
671 }
672 }
673}
674#[allow(dead_code)]
676pub struct RewriteRuleSet {
677 rules: Vec<RewriteRule>,
678}
679#[allow(dead_code)]
680impl RewriteRuleSet {
681 pub fn new() -> Self {
683 Self { rules: Vec::new() }
684 }
685 pub fn add(&mut self, rule: RewriteRule) {
687 self.rules.push(rule);
688 }
689 pub fn len(&self) -> usize {
691 self.rules.len()
692 }
693 pub fn is_empty(&self) -> bool {
695 self.rules.is_empty()
696 }
697 pub fn conditional_rules(&self) -> Vec<&RewriteRule> {
699 self.rules.iter().filter(|r| r.conditional).collect()
700 }
701 pub fn unconditional_rules(&self) -> Vec<&RewriteRule> {
703 self.rules.iter().filter(|r| !r.conditional).collect()
704 }
705 pub fn get(&self, name: &str) -> Option<&RewriteRule> {
707 self.rules.iter().find(|r| r.name == name)
708 }
709}
710#[allow(dead_code)]
712pub struct TransitiveClosure {
713 adj: Vec<Vec<usize>>,
714 n: usize,
715}
716#[allow(dead_code)]
717impl TransitiveClosure {
718 pub fn new(n: usize) -> Self {
720 Self {
721 adj: vec![Vec::new(); n],
722 n,
723 }
724 }
725 pub fn add_edge(&mut self, from: usize, to: usize) {
727 if from < self.n {
728 self.adj[from].push(to);
729 }
730 }
731 pub fn reachable_from(&self, start: usize) -> Vec<usize> {
733 let mut visited = vec![false; self.n];
734 let mut queue = std::collections::VecDeque::new();
735 queue.push_back(start);
736 while let Some(node) = queue.pop_front() {
737 if node >= self.n || visited[node] {
738 continue;
739 }
740 visited[node] = true;
741 for &next in &self.adj[node] {
742 queue.push_back(next);
743 }
744 }
745 (0..self.n).filter(|&i| visited[i]).collect()
746 }
747 pub fn can_reach(&self, from: usize, to: usize) -> bool {
749 self.reachable_from(from).contains(&to)
750 }
751}
752#[allow(dead_code)]
754#[allow(missing_docs)]
755pub enum DecisionNode {
756 Leaf(String),
758 Branch {
760 key: String,
761 val: String,
762 yes_branch: Box<DecisionNode>,
763 no_branch: Box<DecisionNode>,
764 },
765}
766#[allow(dead_code)]
767impl DecisionNode {
768 pub fn evaluate(&self, ctx: &std::collections::HashMap<String, String>) -> &str {
770 match self {
771 DecisionNode::Leaf(action) => action.as_str(),
772 DecisionNode::Branch {
773 key,
774 val,
775 yes_branch,
776 no_branch,
777 } => {
778 let actual = ctx.get(key).map(|s| s.as_str()).unwrap_or("");
779 if actual == val.as_str() {
780 yes_branch.evaluate(ctx)
781 } else {
782 no_branch.evaluate(ctx)
783 }
784 }
785 }
786 }
787 pub fn depth(&self) -> usize {
789 match self {
790 DecisionNode::Leaf(_) => 0,
791 DecisionNode::Branch {
792 yes_branch,
793 no_branch,
794 ..
795 } => 1 + yes_branch.depth().max(no_branch.depth()),
796 }
797 }
798}
799#[allow(dead_code)]
801pub struct SimpleDag {
802 edges: Vec<Vec<usize>>,
804}
805#[allow(dead_code)]
806impl SimpleDag {
807 pub fn new(n: usize) -> Self {
809 Self {
810 edges: vec![Vec::new(); n],
811 }
812 }
813 pub fn add_edge(&mut self, from: usize, to: usize) {
815 if from < self.edges.len() {
816 self.edges[from].push(to);
817 }
818 }
819 pub fn successors(&self, node: usize) -> &[usize] {
821 self.edges.get(node).map(|v| v.as_slice()).unwrap_or(&[])
822 }
823 pub fn can_reach(&self, from: usize, to: usize) -> bool {
825 let mut visited = vec![false; self.edges.len()];
826 self.dfs(from, to, &mut visited)
827 }
828 fn dfs(&self, cur: usize, target: usize, visited: &mut Vec<bool>) -> bool {
829 if cur == target {
830 return true;
831 }
832 if cur >= visited.len() || visited[cur] {
833 return false;
834 }
835 visited[cur] = true;
836 for &next in self.successors(cur) {
837 if self.dfs(next, target, visited) {
838 return true;
839 }
840 }
841 false
842 }
843 pub fn topological_sort(&self) -> Option<Vec<usize>> {
845 let n = self.edges.len();
846 let mut in_degree = vec![0usize; n];
847 for succs in &self.edges {
848 for &s in succs {
849 if s < n {
850 in_degree[s] += 1;
851 }
852 }
853 }
854 let mut queue: std::collections::VecDeque<usize> =
855 (0..n).filter(|&i| in_degree[i] == 0).collect();
856 let mut order = Vec::new();
857 while let Some(node) = queue.pop_front() {
858 order.push(node);
859 for &s in self.successors(node) {
860 if s < n {
861 in_degree[s] -= 1;
862 if in_degree[s] == 0 {
863 queue.push_back(s);
864 }
865 }
866 }
867 }
868 if order.len() == n {
869 Some(order)
870 } else {
871 None
872 }
873 }
874 pub fn num_nodes(&self) -> usize {
876 self.edges.len()
877 }
878}
879#[allow(dead_code)]
881pub struct WriteOnce<T> {
882 value: std::cell::Cell<Option<T>>,
883}
884#[allow(dead_code)]
885impl<T: Copy> WriteOnce<T> {
886 pub fn new() -> Self {
888 Self {
889 value: std::cell::Cell::new(None),
890 }
891 }
892 pub fn write(&self, val: T) -> bool {
894 if self.value.get().is_some() {
895 return false;
896 }
897 self.value.set(Some(val));
898 true
899 }
900 pub fn read(&self) -> Option<T> {
902 self.value.get()
903 }
904 pub fn is_written(&self) -> bool {
906 self.value.get().is_some()
907 }
908}
909#[allow(dead_code)]
911pub struct StackCalc {
912 stack: Vec<i64>,
913}
914#[allow(dead_code)]
915impl StackCalc {
916 pub fn new() -> Self {
918 Self { stack: Vec::new() }
919 }
920 pub fn push(&mut self, n: i64) {
922 self.stack.push(n);
923 }
924 fn apply_binary(&mut self, op: impl FnOnce(i64, i64) -> i64) -> Option<i64> {
928 let (rest_len, a, b) = match self.stack[..] {
929 [ref rest @ .., a, b] => (rest.len(), a, b),
930 _ => return None,
931 };
932 let value = op(a, b);
933 self.stack.truncate(rest_len);
934 self.stack.push(value);
935 Some(value)
936 }
937 pub fn add(&mut self) -> Option<i64> {
941 self.apply_binary(|a, b| a + b)
942 }
943 pub fn sub(&mut self) -> Option<i64> {
947 self.apply_binary(|a, b| a - b)
948 }
949 pub fn mul(&mut self) -> Option<i64> {
953 self.apply_binary(|a, b| a * b)
954 }
955 pub fn peek(&self) -> Option<i64> {
957 self.stack.last().copied()
958 }
959 pub fn depth(&self) -> usize {
961 self.stack.len()
962 }
963}
964#[allow(dead_code)]
966pub struct PrefixCounter {
967 children: std::collections::HashMap<char, PrefixCounter>,
968 count: usize,
969}
970#[allow(dead_code)]
971impl PrefixCounter {
972 pub fn new() -> Self {
974 Self {
975 children: std::collections::HashMap::new(),
976 count: 0,
977 }
978 }
979 pub fn record(&mut self, s: &str) {
981 self.count += 1;
982 let mut node = self;
983 for c in s.chars() {
984 node = node.children.entry(c).or_default();
985 node.count += 1;
986 }
987 }
988 pub fn count_with_prefix(&self, prefix: &str) -> usize {
990 let mut node = self;
991 for c in prefix.chars() {
992 match node.children.get(&c) {
993 Some(n) => node = n,
994 None => return 0,
995 }
996 }
997 node.count
998 }
999}
1000#[allow(dead_code)]
1002pub struct SmallMap<K: Ord + Clone, V: Clone> {
1003 entries: Vec<(K, V)>,
1004}
1005#[allow(dead_code)]
1006impl<K: Ord + Clone, V: Clone> SmallMap<K, V> {
1007 pub fn new() -> Self {
1009 Self {
1010 entries: Vec::new(),
1011 }
1012 }
1013 pub fn insert(&mut self, key: K, val: V) {
1015 match self.entries.binary_search_by_key(&&key, |(k, _)| k) {
1016 Ok(i) => self.entries[i].1 = val,
1017 Err(i) => self.entries.insert(i, (key, val)),
1018 }
1019 }
1020 pub fn get(&self, key: &K) -> Option<&V> {
1022 self.entries
1023 .binary_search_by_key(&key, |(k, _)| k)
1024 .ok()
1025 .map(|i| &self.entries[i].1)
1026 }
1027 pub fn len(&self) -> usize {
1029 self.entries.len()
1030 }
1031 pub fn is_empty(&self) -> bool {
1033 self.entries.is_empty()
1034 }
1035 pub fn keys(&self) -> Vec<&K> {
1037 self.entries.iter().map(|(k, _)| k).collect()
1038 }
1039 pub fn values(&self) -> Vec<&V> {
1041 self.entries.iter().map(|(_, v)| v).collect()
1042 }
1043}
1044#[allow(dead_code)]
1046pub struct PathBuf {
1047 components: Vec<String>,
1048}
1049#[allow(dead_code)]
1050impl PathBuf {
1051 pub fn new() -> Self {
1053 Self {
1054 components: Vec::new(),
1055 }
1056 }
1057 pub fn push(&mut self, comp: impl Into<String>) {
1059 self.components.push(comp.into());
1060 }
1061 pub fn pop(&mut self) {
1063 self.components.pop();
1064 }
1065 pub fn as_str(&self) -> String {
1067 self.components.join("/")
1068 }
1069 pub fn depth(&self) -> usize {
1071 self.components.len()
1072 }
1073 pub fn clear(&mut self) {
1075 self.components.clear();
1076 }
1077}
1078#[allow(dead_code)]
1080pub struct FocusStack<T> {
1081 items: Vec<T>,
1082}
1083#[allow(dead_code)]
1084impl<T> FocusStack<T> {
1085 pub fn new() -> Self {
1087 Self { items: Vec::new() }
1088 }
1089 pub fn focus(&mut self, item: T) {
1091 self.items.push(item);
1092 }
1093 pub fn blur(&mut self) -> Option<T> {
1095 self.items.pop()
1096 }
1097 pub fn current(&self) -> Option<&T> {
1099 self.items.last()
1100 }
1101 pub fn depth(&self) -> usize {
1103 self.items.len()
1104 }
1105 pub fn is_empty(&self) -> bool {
1107 self.items.is_empty()
1108 }
1109}
1110#[allow(dead_code)]
1112pub struct MinHeap<T: Ord> {
1113 data: Vec<T>,
1114}
1115#[allow(dead_code)]
1116impl<T: Ord> MinHeap<T> {
1117 pub fn new() -> Self {
1119 Self { data: Vec::new() }
1120 }
1121 pub fn push(&mut self, val: T) {
1123 self.data.push(val);
1124 self.sift_up(self.data.len() - 1);
1125 }
1126 pub fn pop(&mut self) -> Option<T> {
1128 if self.data.is_empty() {
1129 return None;
1130 }
1131 let n = self.data.len();
1132 self.data.swap(0, n - 1);
1133 let min = self.data.pop();
1134 if !self.data.is_empty() {
1135 self.sift_down(0);
1136 }
1137 min
1138 }
1139 pub fn peek(&self) -> Option<&T> {
1141 self.data.first()
1142 }
1143 pub fn len(&self) -> usize {
1145 self.data.len()
1146 }
1147 pub fn is_empty(&self) -> bool {
1149 self.data.is_empty()
1150 }
1151 fn sift_up(&mut self, mut i: usize) {
1152 while i > 0 {
1153 let parent = (i - 1) / 2;
1154 if self.data[i] < self.data[parent] {
1155 self.data.swap(i, parent);
1156 i = parent;
1157 } else {
1158 break;
1159 }
1160 }
1161 }
1162 fn sift_down(&mut self, mut i: usize) {
1163 let n = self.data.len();
1164 loop {
1165 let left = 2 * i + 1;
1166 let right = 2 * i + 2;
1167 let mut smallest = i;
1168 if left < n && self.data[left] < self.data[smallest] {
1169 smallest = left;
1170 }
1171 if right < n && self.data[right] < self.data[smallest] {
1172 smallest = right;
1173 }
1174 if smallest == i {
1175 break;
1176 }
1177 self.data.swap(i, smallest);
1178 i = smallest;
1179 }
1180 }
1181}