1use std::collections::HashMap;
6
7#[allow(dead_code)]
9pub struct LabelSet {
10 labels: Vec<String>,
11}
12#[allow(dead_code)]
13impl LabelSet {
14 pub fn new() -> Self {
16 Self { labels: Vec::new() }
17 }
18 pub fn add(&mut self, label: impl Into<String>) {
20 let s = label.into();
21 if !self.labels.contains(&s) {
22 self.labels.push(s);
23 }
24 }
25 pub fn has(&self, label: &str) -> bool {
27 self.labels.iter().any(|l| l == label)
28 }
29 pub fn count(&self) -> usize {
31 self.labels.len()
32 }
33 pub fn all(&self) -> &[String] {
35 &self.labels
36 }
37}
38#[allow(dead_code)]
40pub struct PathBuf {
41 components: Vec<String>,
42}
43#[allow(dead_code)]
44impl PathBuf {
45 pub fn new() -> Self {
47 Self {
48 components: Vec::new(),
49 }
50 }
51 pub fn push(&mut self, comp: impl Into<String>) {
53 self.components.push(comp.into());
54 }
55 pub fn pop(&mut self) {
57 self.components.pop();
58 }
59 pub fn as_str(&self) -> String {
61 self.components.join("/")
62 }
63 pub fn depth(&self) -> usize {
65 self.components.len()
66 }
67 pub fn clear(&mut self) {
69 self.components.clear();
70 }
71}
72#[allow(dead_code)]
74pub struct RewriteRuleSet {
75 rules: Vec<RewriteRule>,
76}
77#[allow(dead_code)]
78impl RewriteRuleSet {
79 pub fn new() -> Self {
81 Self { rules: Vec::new() }
82 }
83 pub fn add(&mut self, rule: RewriteRule) {
85 self.rules.push(rule);
86 }
87 pub fn len(&self) -> usize {
89 self.rules.len()
90 }
91 pub fn is_empty(&self) -> bool {
93 self.rules.is_empty()
94 }
95 pub fn conditional_rules(&self) -> Vec<&RewriteRule> {
97 self.rules.iter().filter(|r| r.conditional).collect()
98 }
99 pub fn unconditional_rules(&self) -> Vec<&RewriteRule> {
101 self.rules.iter().filter(|r| !r.conditional).collect()
102 }
103 pub fn get(&self, name: &str) -> Option<&RewriteRule> {
105 self.rules.iter().find(|r| r.name == name)
106 }
107}
108#[allow(dead_code)]
110pub struct SimpleDag {
111 edges: Vec<Vec<usize>>,
113}
114#[allow(dead_code)]
115impl SimpleDag {
116 pub fn new(n: usize) -> Self {
118 Self {
119 edges: vec![Vec::new(); n],
120 }
121 }
122 pub fn add_edge(&mut self, from: usize, to: usize) {
124 if from < self.edges.len() {
125 self.edges[from].push(to);
126 }
127 }
128 pub fn successors(&self, node: usize) -> &[usize] {
130 self.edges.get(node).map(|v| v.as_slice()).unwrap_or(&[])
131 }
132 pub fn can_reach(&self, from: usize, to: usize) -> bool {
134 let mut visited = vec![false; self.edges.len()];
135 self.dfs(from, to, &mut visited)
136 }
137 fn dfs(&self, cur: usize, target: usize, visited: &mut Vec<bool>) -> bool {
138 if cur == target {
139 return true;
140 }
141 if cur >= visited.len() || visited[cur] {
142 return false;
143 }
144 visited[cur] = true;
145 for &next in self.successors(cur) {
146 if self.dfs(next, target, visited) {
147 return true;
148 }
149 }
150 false
151 }
152 pub fn topological_sort(&self) -> Option<Vec<usize>> {
154 let n = self.edges.len();
155 let mut in_degree = vec![0usize; n];
156 for succs in &self.edges {
157 for &s in succs {
158 if s < n {
159 in_degree[s] += 1;
160 }
161 }
162 }
163 let mut queue: std::collections::VecDeque<usize> =
164 (0..n).filter(|&i| in_degree[i] == 0).collect();
165 let mut order = Vec::new();
166 while let Some(node) = queue.pop_front() {
167 order.push(node);
168 for &s in self.successors(node) {
169 if s < n {
170 in_degree[s] -= 1;
171 if in_degree[s] == 0 {
172 queue.push_back(s);
173 }
174 }
175 }
176 }
177 if order.len() == n {
178 Some(order)
179 } else {
180 None
181 }
182 }
183 pub fn num_nodes(&self) -> usize {
185 self.edges.len()
186 }
187}
188#[allow(dead_code)]
190#[allow(missing_docs)]
191pub enum DecisionNode {
192 Leaf(String),
194 Branch {
196 key: String,
197 val: String,
198 yes_branch: Box<DecisionNode>,
199 no_branch: Box<DecisionNode>,
200 },
201}
202#[allow(dead_code)]
203impl DecisionNode {
204 pub fn evaluate(&self, ctx: &std::collections::HashMap<String, String>) -> &str {
206 match self {
207 DecisionNode::Leaf(action) => action.as_str(),
208 DecisionNode::Branch {
209 key,
210 val,
211 yes_branch,
212 no_branch,
213 } => {
214 let actual = ctx.get(key).map(|s| s.as_str()).unwrap_or("");
215 if actual == val.as_str() {
216 yes_branch.evaluate(ctx)
217 } else {
218 no_branch.evaluate(ctx)
219 }
220 }
221 }
222 }
223 pub fn depth(&self) -> usize {
225 match self {
226 DecisionNode::Leaf(_) => 0,
227 DecisionNode::Branch {
228 yes_branch,
229 no_branch,
230 ..
231 } => 1 + yes_branch.depth().max(no_branch.depth()),
232 }
233 }
234}
235#[allow(dead_code)]
237pub struct Stopwatch {
238 start: crate::wall_clock::Instant,
239 splits: Vec<f64>,
240}
241#[allow(dead_code)]
242impl Stopwatch {
243 pub fn start() -> Self {
245 Self {
246 start: crate::wall_clock::Instant::now(),
247 splits: Vec::new(),
248 }
249 }
250 pub fn split(&mut self) {
252 self.splits.push(self.elapsed_ms());
253 }
254 pub fn elapsed_ms(&self) -> f64 {
256 self.start.elapsed().as_secs_f64() * 1000.0
257 }
258 pub fn splits(&self) -> &[f64] {
260 &self.splits
261 }
262 pub fn num_splits(&self) -> usize {
264 self.splits.len()
265 }
266}
267#[allow(dead_code)]
269pub struct WriteOnce<T> {
270 value: std::cell::Cell<Option<T>>,
271}
272#[allow(dead_code)]
273impl<T: Copy> WriteOnce<T> {
274 pub fn new() -> Self {
276 Self {
277 value: std::cell::Cell::new(None),
278 }
279 }
280 pub fn write(&self, val: T) -> bool {
282 if self.value.get().is_some() {
283 return false;
284 }
285 self.value.set(Some(val));
286 true
287 }
288 pub fn read(&self) -> Option<T> {
290 self.value.get()
291 }
292 pub fn is_written(&self) -> bool {
294 self.value.get().is_some()
295 }
296}
297#[allow(dead_code)]
299#[allow(missing_docs)]
300pub struct RewriteRule {
301 pub name: String,
303 pub lhs: String,
305 pub rhs: String,
307 pub conditional: bool,
309}
310#[allow(dead_code)]
311impl RewriteRule {
312 pub fn unconditional(
314 name: impl Into<String>,
315 lhs: impl Into<String>,
316 rhs: impl Into<String>,
317 ) -> Self {
318 Self {
319 name: name.into(),
320 lhs: lhs.into(),
321 rhs: rhs.into(),
322 conditional: false,
323 }
324 }
325 pub fn conditional(
327 name: impl Into<String>,
328 lhs: impl Into<String>,
329 rhs: impl Into<String>,
330 ) -> Self {
331 Self {
332 name: name.into(),
333 lhs: lhs.into(),
334 rhs: rhs.into(),
335 conditional: true,
336 }
337 }
338 pub fn display(&self) -> String {
340 format!("{}: {} → {}", self.name, self.lhs, self.rhs)
341 }
342}
343#[allow(dead_code)]
345pub struct FlatSubstitution {
346 pairs: Vec<(String, String)>,
347}
348#[allow(dead_code)]
349impl FlatSubstitution {
350 pub fn new() -> Self {
352 Self { pairs: Vec::new() }
353 }
354 pub fn add(&mut self, from: impl Into<String>, to: impl Into<String>) {
356 self.pairs.push((from.into(), to.into()));
357 }
358 pub fn apply(&self, s: &str) -> String {
360 let mut result = s.to_string();
361 for (from, to) in &self.pairs {
362 result = result.replace(from.as_str(), to.as_str());
363 }
364 result
365 }
366 pub fn len(&self) -> usize {
368 self.pairs.len()
369 }
370 pub fn is_empty(&self) -> bool {
372 self.pairs.is_empty()
373 }
374}
375#[allow(dead_code)]
377pub struct FocusStack<T> {
378 items: Vec<T>,
379}
380#[allow(dead_code)]
381impl<T> FocusStack<T> {
382 pub fn new() -> Self {
384 Self { items: Vec::new() }
385 }
386 pub fn focus(&mut self, item: T) {
388 self.items.push(item);
389 }
390 pub fn blur(&mut self) -> Option<T> {
392 self.items.pop()
393 }
394 pub fn current(&self) -> Option<&T> {
396 self.items.last()
397 }
398 pub fn depth(&self) -> usize {
400 self.items.len()
401 }
402 pub fn is_empty(&self) -> bool {
404 self.items.is_empty()
405 }
406}
407#[allow(dead_code)]
409pub struct SlidingSum {
410 window: Vec<f64>,
411 capacity: usize,
412 pos: usize,
413 sum: f64,
414 count: usize,
415}
416#[allow(dead_code)]
417impl SlidingSum {
418 pub fn new(capacity: usize) -> Self {
420 Self {
421 window: vec![0.0; capacity],
422 capacity,
423 pos: 0,
424 sum: 0.0,
425 count: 0,
426 }
427 }
428 pub fn push(&mut self, val: f64) {
430 let oldest = self.window[self.pos];
431 self.sum -= oldest;
432 self.sum += val;
433 self.window[self.pos] = val;
434 self.pos = (self.pos + 1) % self.capacity;
435 if self.count < self.capacity {
436 self.count += 1;
437 }
438 }
439 pub fn sum(&self) -> f64 {
441 self.sum
442 }
443 pub fn mean(&self) -> Option<f64> {
445 if self.count == 0 {
446 None
447 } else {
448 Some(self.sum / self.count as f64)
449 }
450 }
451 pub fn count(&self) -> usize {
453 self.count
454 }
455}
456#[allow(dead_code)]
458pub struct TokenBucket {
459 capacity: u64,
460 tokens: u64,
461 refill_per_ms: u64,
462 last_refill: crate::wall_clock::Instant,
463}
464#[allow(dead_code)]
465impl TokenBucket {
466 pub fn new(capacity: u64, refill_per_ms: u64) -> Self {
468 Self {
469 capacity,
470 tokens: capacity,
471 refill_per_ms,
472 last_refill: crate::wall_clock::Instant::now(),
473 }
474 }
475 pub fn try_consume(&mut self, n: u64) -> bool {
477 self.refill();
478 if self.tokens >= n {
479 self.tokens -= n;
480 true
481 } else {
482 false
483 }
484 }
485 fn refill(&mut self) {
486 let now = crate::wall_clock::Instant::now();
487 let elapsed_ms = now.duration_since(self.last_refill).as_millis() as u64;
488 if elapsed_ms > 0 {
489 let new_tokens = elapsed_ms * self.refill_per_ms;
490 self.tokens = (self.tokens + new_tokens).min(self.capacity);
491 self.last_refill = now;
492 }
493 }
494 pub fn available(&self) -> u64 {
496 self.tokens
497 }
498 pub fn capacity(&self) -> u64 {
500 self.capacity
501 }
502}
503#[allow(dead_code)]
505pub struct SparseVec<T: Default + Clone + PartialEq> {
506 entries: std::collections::HashMap<usize, T>,
507 default_: T,
508 logical_len: usize,
509}
510#[allow(dead_code)]
511impl<T: Default + Clone + PartialEq> SparseVec<T> {
512 pub fn new(len: usize) -> Self {
514 Self {
515 entries: std::collections::HashMap::new(),
516 default_: T::default(),
517 logical_len: len,
518 }
519 }
520 pub fn set(&mut self, idx: usize, val: T) {
522 if val == self.default_ {
523 self.entries.remove(&idx);
524 } else {
525 self.entries.insert(idx, val);
526 }
527 }
528 pub fn get(&self, idx: usize) -> &T {
530 self.entries.get(&idx).unwrap_or(&self.default_)
531 }
532 pub fn len(&self) -> usize {
534 self.logical_len
535 }
536 pub fn is_empty(&self) -> bool {
538 self.len() == 0
539 }
540 pub fn nnz(&self) -> usize {
542 self.entries.len()
543 }
544}
545#[allow(dead_code)]
547pub struct StackCalc {
548 stack: Vec<i64>,
549}
550#[allow(dead_code)]
551impl StackCalc {
552 pub fn new() -> Self {
554 Self { stack: Vec::new() }
555 }
556 pub fn push(&mut self, n: i64) {
558 self.stack.push(n);
559 }
560 fn apply_binary(&mut self, op: impl FnOnce(i64, i64) -> i64) -> Option<i64> {
564 let (rest_len, a, b) = match self.stack[..] {
565 [ref rest @ .., a, b] => (rest.len(), a, b),
566 _ => return None,
567 };
568 let value = op(a, b);
569 self.stack.truncate(rest_len);
570 self.stack.push(value);
571 Some(value)
572 }
573 pub fn add(&mut self) -> Option<i64> {
577 self.apply_binary(|a, b| a + b)
578 }
579 pub fn sub(&mut self) -> Option<i64> {
583 self.apply_binary(|a, b| a - b)
584 }
585 pub fn mul(&mut self) -> Option<i64> {
589 self.apply_binary(|a, b| a * b)
590 }
591 pub fn peek(&self) -> Option<i64> {
593 self.stack.last().copied()
594 }
595 pub fn depth(&self) -> usize {
597 self.stack.len()
598 }
599}
600#[allow(dead_code)]
602pub struct SmallMap<K: Ord + Clone, V: Clone> {
603 entries: Vec<(K, V)>,
604}
605#[allow(dead_code)]
606impl<K: Ord + Clone, V: Clone> SmallMap<K, V> {
607 pub fn new() -> Self {
609 Self {
610 entries: Vec::new(),
611 }
612 }
613 pub fn insert(&mut self, key: K, val: V) {
615 match self.entries.binary_search_by_key(&&key, |(k, _)| k) {
616 Ok(i) => self.entries[i].1 = val,
617 Err(i) => self.entries.insert(i, (key, val)),
618 }
619 }
620 pub fn get(&self, key: &K) -> Option<&V> {
622 self.entries
623 .binary_search_by_key(&key, |(k, _)| k)
624 .ok()
625 .map(|i| &self.entries[i].1)
626 }
627 pub fn len(&self) -> usize {
629 self.entries.len()
630 }
631 pub fn is_empty(&self) -> bool {
633 self.entries.is_empty()
634 }
635 pub fn keys(&self) -> Vec<&K> {
637 self.entries.iter().map(|(k, _)| k).collect()
638 }
639 pub fn values(&self) -> Vec<&V> {
641 self.entries.iter().map(|(_, v)| v).collect()
642 }
643}
644#[allow(dead_code)]
646pub struct StatSummary {
647 count: u64,
648 sum: f64,
649 min: f64,
650 max: f64,
651}
652#[allow(dead_code)]
653impl StatSummary {
654 pub fn new() -> Self {
656 Self {
657 count: 0,
658 sum: 0.0,
659 min: f64::INFINITY,
660 max: f64::NEG_INFINITY,
661 }
662 }
663 pub fn record(&mut self, val: f64) {
665 self.count += 1;
666 self.sum += val;
667 if val < self.min {
668 self.min = val;
669 }
670 if val > self.max {
671 self.max = val;
672 }
673 }
674 pub fn mean(&self) -> Option<f64> {
676 if self.count == 0 {
677 None
678 } else {
679 Some(self.sum / self.count as f64)
680 }
681 }
682 pub fn min(&self) -> Option<f64> {
684 if self.count == 0 {
685 None
686 } else {
687 Some(self.min)
688 }
689 }
690 pub fn max(&self) -> Option<f64> {
692 if self.count == 0 {
693 None
694 } else {
695 Some(self.max)
696 }
697 }
698 pub fn count(&self) -> u64 {
700 self.count
701 }
702}
703#[allow(dead_code)]
705pub struct StringPool {
706 free: Vec<String>,
707}
708#[allow(dead_code)]
709impl StringPool {
710 pub fn new() -> Self {
712 Self { free: Vec::new() }
713 }
714 pub fn take(&mut self) -> String {
716 self.free.pop().unwrap_or_default()
717 }
718 pub fn give(&mut self, mut s: String) {
720 s.clear();
721 self.free.push(s);
722 }
723 pub fn free_count(&self) -> usize {
725 self.free.len()
726 }
727}
728#[allow(dead_code)]
730pub enum Either2<A, B> {
731 First(A),
733 Second(B),
735}
736#[allow(dead_code)]
737impl<A, B> Either2<A, B> {
738 pub fn is_first(&self) -> bool {
740 matches!(self, Either2::First(_))
741 }
742 pub fn is_second(&self) -> bool {
744 matches!(self, Either2::Second(_))
745 }
746 pub fn first(self) -> Option<A> {
748 match self {
749 Either2::First(a) => Some(a),
750 _ => None,
751 }
752 }
753 pub fn second(self) -> Option<B> {
755 match self {
756 Either2::Second(b) => Some(b),
757 _ => None,
758 }
759 }
760 pub fn map_first<C, F: FnOnce(A) -> C>(self, f: F) -> Either2<C, B> {
762 match self {
763 Either2::First(a) => Either2::First(f(a)),
764 Either2::Second(b) => Either2::Second(b),
765 }
766 }
767}
768#[allow(dead_code)]
770pub struct PrefixCounter {
771 children: std::collections::HashMap<char, PrefixCounter>,
772 count: usize,
773}
774#[allow(dead_code)]
775impl PrefixCounter {
776 pub fn new() -> Self {
778 Self {
779 children: std::collections::HashMap::new(),
780 count: 0,
781 }
782 }
783 pub fn record(&mut self, s: &str) {
785 self.count += 1;
786 let mut node = self;
787 for c in s.chars() {
788 node = node.children.entry(c).or_default();
789 node.count += 1;
790 }
791 }
792 pub fn count_with_prefix(&self, prefix: &str) -> usize {
794 let mut node = self;
795 for c in prefix.chars() {
796 match node.children.get(&c) {
797 Some(n) => node = n,
798 None => return 0,
799 }
800 }
801 node.count
802 }
803}
804#[allow(dead_code)]
806pub struct Fixture {
807 data: std::collections::HashMap<String, String>,
808}
809#[allow(dead_code)]
810impl Fixture {
811 pub fn new() -> Self {
813 Self {
814 data: std::collections::HashMap::new(),
815 }
816 }
817 pub fn set(&mut self, key: impl Into<String>, val: impl Into<String>) {
819 self.data.insert(key.into(), val.into());
820 }
821 pub fn get(&self, key: &str) -> Option<&str> {
823 self.data.get(key).map(|s| s.as_str())
824 }
825 pub fn len(&self) -> usize {
827 self.data.len()
828 }
829 pub fn is_empty(&self) -> bool {
831 self.len() == 0
832 }
833}
834#[allow(dead_code)]
836pub struct WindowIterator<'a, T> {
837 pub(super) data: &'a [T],
838 pub(super) pos: usize,
839 pub(super) window: usize,
840}
841#[allow(dead_code)]
842impl<'a, T> WindowIterator<'a, T> {
843 pub fn new(data: &'a [T], window: usize) -> Self {
845 Self {
846 data,
847 pos: 0,
848 window,
849 }
850 }
851}
852#[allow(dead_code)]
854pub struct NonEmptyVec<T> {
855 head: T,
856 tail: Vec<T>,
857}
858#[allow(dead_code)]
859impl<T> NonEmptyVec<T> {
860 pub fn singleton(val: T) -> Self {
862 Self {
863 head: val,
864 tail: Vec::new(),
865 }
866 }
867 pub fn push(&mut self, val: T) {
869 self.tail.push(val);
870 }
871 pub fn first(&self) -> &T {
873 &self.head
874 }
875 pub fn last(&self) -> &T {
877 self.tail.last().unwrap_or(&self.head)
878 }
879 pub fn len(&self) -> usize {
881 1 + self.tail.len()
882 }
883 pub fn is_empty(&self) -> bool {
885 self.len() == 0
886 }
887 pub fn to_vec(&self) -> Vec<&T> {
889 let mut v = vec![&self.head];
890 v.extend(self.tail.iter());
891 v
892 }
893}
894#[allow(dead_code)]
896pub struct RawFnPtr {
897 ptr: usize,
899 arity: usize,
900 name: String,
901}
902#[allow(dead_code)]
903impl RawFnPtr {
904 pub fn new(ptr: usize, arity: usize, name: impl Into<String>) -> Self {
906 Self {
907 ptr,
908 arity,
909 name: name.into(),
910 }
911 }
912 pub fn arity(&self) -> usize {
914 self.arity
915 }
916 pub fn name(&self) -> &str {
918 &self.name
919 }
920 pub fn raw(&self) -> usize {
922 self.ptr
923 }
924}
925#[allow(dead_code)]
927pub struct TransitiveClosure {
928 adj: Vec<Vec<usize>>,
929 n: usize,
930}
931#[allow(dead_code)]
932impl TransitiveClosure {
933 pub fn new(n: usize) -> Self {
935 Self {
936 adj: vec![Vec::new(); n],
937 n,
938 }
939 }
940 pub fn add_edge(&mut self, from: usize, to: usize) {
942 if from < self.n {
943 self.adj[from].push(to);
944 }
945 }
946 pub fn reachable_from(&self, start: usize) -> Vec<usize> {
948 let mut visited = vec![false; self.n];
949 let mut queue = std::collections::VecDeque::new();
950 queue.push_back(start);
951 while let Some(node) = queue.pop_front() {
952 if node >= self.n || visited[node] {
953 continue;
954 }
955 visited[node] = true;
956 for &next in &self.adj[node] {
957 queue.push_back(next);
958 }
959 }
960 (0..self.n).filter(|&i| visited[i]).collect()
961 }
962 pub fn can_reach(&self, from: usize, to: usize) -> bool {
964 self.reachable_from(from).contains(&to)
965 }
966}
967#[allow(dead_code)]
969pub struct TransformStat {
970 before: StatSummary,
971 after: StatSummary,
972}
973#[allow(dead_code)]
974impl TransformStat {
975 pub fn new() -> Self {
977 Self {
978 before: StatSummary::new(),
979 after: StatSummary::new(),
980 }
981 }
982 pub fn record_before(&mut self, v: f64) {
984 self.before.record(v);
985 }
986 pub fn record_after(&mut self, v: f64) {
988 self.after.record(v);
989 }
990 pub fn mean_ratio(&self) -> Option<f64> {
992 let b = self.before.mean()?;
993 let a = self.after.mean()?;
994 if b.abs() < f64::EPSILON {
995 return None;
996 }
997 Some(a / b)
998 }
999}
1000#[allow(dead_code)]
1002pub struct ConfigNode {
1003 key: String,
1004 value: Option<String>,
1005 children: Vec<ConfigNode>,
1006}
1007#[allow(dead_code)]
1008impl ConfigNode {
1009 pub fn leaf(key: impl Into<String>, value: impl Into<String>) -> Self {
1011 Self {
1012 key: key.into(),
1013 value: Some(value.into()),
1014 children: Vec::new(),
1015 }
1016 }
1017 pub fn section(key: impl Into<String>) -> Self {
1019 Self {
1020 key: key.into(),
1021 value: None,
1022 children: Vec::new(),
1023 }
1024 }
1025 pub fn add_child(&mut self, child: ConfigNode) {
1027 self.children.push(child);
1028 }
1029 pub fn key(&self) -> &str {
1031 &self.key
1032 }
1033 pub fn value(&self) -> Option<&str> {
1035 self.value.as_deref()
1036 }
1037 pub fn num_children(&self) -> usize {
1039 self.children.len()
1040 }
1041 pub fn lookup(&self, path: &str) -> Option<&str> {
1043 let mut parts = path.splitn(2, '.');
1044 let head = parts.next()?;
1045 let tail = parts.next();
1046 if head != self.key {
1047 return None;
1048 }
1049 match tail {
1050 None => self.value.as_deref(),
1051 Some(rest) => self.children.iter().find_map(|c| c.lookup_relative(rest)),
1052 }
1053 }
1054 fn lookup_relative(&self, path: &str) -> Option<&str> {
1055 let mut parts = path.splitn(2, '.');
1056 let head = parts.next()?;
1057 let tail = parts.next();
1058 if head != self.key {
1059 return None;
1060 }
1061 match tail {
1062 None => self.value.as_deref(),
1063 Some(rest) => self.children.iter().find_map(|c| c.lookup_relative(rest)),
1064 }
1065 }
1066}
1067#[allow(dead_code)]
1069pub struct VersionedRecord<T: Clone> {
1070 earlier: Vec<T>,
1072 current: T,
1074}
1075#[allow(dead_code)]
1076impl<T: Clone> VersionedRecord<T> {
1077 pub fn new(initial: T) -> Self {
1079 Self {
1080 earlier: Vec::new(),
1081 current: initial,
1082 }
1083 }
1084 pub fn update(&mut self, val: T) {
1086 let previous = std::mem::replace(&mut self.current, val);
1087 self.earlier.push(previous);
1088 }
1089 pub fn current(&self) -> &T {
1091 &self.current
1092 }
1093 pub fn at_version(&self, n: usize) -> Option<&T> {
1095 match self.earlier.get(n) {
1096 Some(value) => Some(value),
1097 None if n == self.earlier.len() => Some(&self.current),
1098 None => None,
1099 }
1100 }
1101 pub fn version(&self) -> usize {
1103 self.earlier.len()
1104 }
1105 pub fn has_history(&self) -> bool {
1107 !self.earlier.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}