Skip to main content

oxilean_kernel/abstract/
types.rs

1//! Auto-generated module
2//!
3//! 🤖 Generated with [SplitRS](https://github.com/cool-japan/splitrs)
4
5use std::collections::HashMap;
6
7/// A versioned record that stores a history of values.
8#[allow(dead_code)]
9pub struct VersionedRecord<T: Clone> {
10    /// Every earlier value, oldest first: version `n` is `earlier[n]`.
11    earlier: Vec<T>,
12    /// The latest value (version `earlier.len()`), declared last so it drops last.
13    current: T,
14}
15#[allow(dead_code)]
16impl<T: Clone> VersionedRecord<T> {
17    /// Creates a new record with an initial value.
18    pub fn new(initial: T) -> Self {
19        Self {
20            earlier: Vec::new(),
21            current: initial,
22        }
23    }
24    /// Updates the record with a new version.
25    pub fn update(&mut self, val: T) {
26        let previous = std::mem::replace(&mut self.current, val);
27        self.earlier.push(previous);
28    }
29    /// Returns the current (latest) value.
30    pub fn current(&self) -> &T {
31        &self.current
32    }
33    /// Returns the value at version `n` (0-indexed), or `None`.
34    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    /// Returns the version number of the current value.
42    pub fn version(&self) -> usize {
43        self.earlier.len()
44    }
45    /// Returns `true` if more than one version exists.
46    pub fn has_history(&self) -> bool {
47        !self.earlier.is_empty()
48    }
49}
50/// A flat list of substitution pairs `(from, to)`.
51#[allow(dead_code)]
52pub struct FlatSubstitution {
53    pairs: Vec<(String, String)>,
54}
55#[allow(dead_code)]
56impl FlatSubstitution {
57    /// Creates an empty substitution.
58    pub fn new() -> Self {
59        Self { pairs: Vec::new() }
60    }
61    /// Adds a pair.
62    pub fn add(&mut self, from: impl Into<String>, to: impl Into<String>) {
63        self.pairs.push((from.into(), to.into()));
64    }
65    /// Applies all substitutions to `s` (leftmost-first order).
66    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    /// Returns the number of pairs.
74    pub fn len(&self) -> usize {
75        self.pairs.len()
76    }
77    /// Returns `true` if empty.
78    pub fn is_empty(&self) -> bool {
79        self.pairs.is_empty()
80    }
81}
82/// Represents a rewrite rule `lhs → rhs`.
83#[allow(dead_code)]
84#[allow(missing_docs)]
85pub struct RewriteRule {
86    /// The name of the rule.
87    pub name: String,
88    /// A string representation of the LHS pattern.
89    pub lhs: String,
90    /// A string representation of the RHS.
91    pub rhs: String,
92    /// Whether this is a conditional rule (has side conditions).
93    pub conditional: bool,
94}
95#[allow(dead_code)]
96impl RewriteRule {
97    /// Creates an unconditional rewrite rule.
98    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    /// Creates a conditional rewrite rule.
111    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    /// Returns a textual representation.
124    pub fn display(&self) -> String {
125        format!("{}: {} → {}", self.name, self.lhs, self.rhs)
126    }
127}
128/// A token bucket rate limiter.
129#[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    /// Creates a new token bucket.
139    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    /// Attempts to consume `n` tokens.  Returns `true` on success.
148    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    /// Returns the number of currently available tokens.
167    pub fn available(&self) -> u64 {
168        self.tokens
169    }
170    /// Returns the bucket capacity.
171    pub fn capacity(&self) -> u64 {
172        self.capacity
173    }
174}
175/// A simple mutable key-value store for test fixtures.
176#[allow(dead_code)]
177pub struct Fixture {
178    data: std::collections::HashMap<String, String>,
179}
180#[allow(dead_code)]
181impl Fixture {
182    /// Creates an empty fixture.
183    pub fn new() -> Self {
184        Self {
185            data: std::collections::HashMap::new(),
186        }
187    }
188    /// Sets a key.
189    pub fn set(&mut self, key: impl Into<String>, val: impl Into<String>) {
190        self.data.insert(key.into(), val.into());
191    }
192    /// Gets a value.
193    pub fn get(&self, key: &str) -> Option<&str> {
194        self.data.get(key).map(|s| s.as_str())
195    }
196    /// Returns the number of entries.
197    pub fn len(&self) -> usize {
198        self.data.len()
199    }
200    /// Returns whether the collection is empty.
201    pub fn is_empty(&self) -> bool {
202        self.len() == 0
203    }
204}
205/// A non-empty list (at least one element guaranteed).
206#[allow(dead_code)]
207pub struct NonEmptyVec<T> {
208    head: T,
209    tail: Vec<T>,
210}
211#[allow(dead_code)]
212impl<T> NonEmptyVec<T> {
213    /// Creates a non-empty vec with a single element.
214    pub fn singleton(val: T) -> Self {
215        Self {
216            head: val,
217            tail: Vec::new(),
218        }
219    }
220    /// Pushes an element.
221    pub fn push(&mut self, val: T) {
222        self.tail.push(val);
223    }
224    /// Returns a reference to the first element.
225    pub fn first(&self) -> &T {
226        &self.head
227    }
228    /// Returns a reference to the last element.
229    pub fn last(&self) -> &T {
230        self.tail.last().unwrap_or(&self.head)
231    }
232    /// Returns the number of elements.
233    pub fn len(&self) -> usize {
234        1 + self.tail.len()
235    }
236    /// Returns whether the collection is empty.
237    pub fn is_empty(&self) -> bool {
238        self.len() == 0
239    }
240    /// Returns all elements as a Vec.
241    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/// A type-erased function pointer with arity tracking.
248#[allow(dead_code)]
249pub struct RawFnPtr {
250    /// The raw function pointer (stored as usize for type erasure).
251    ptr: usize,
252    arity: usize,
253    name: String,
254}
255#[allow(dead_code)]
256impl RawFnPtr {
257    /// Creates a new raw function pointer descriptor.
258    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    /// Returns the arity.
266    pub fn arity(&self) -> usize {
267        self.arity
268    }
269    /// Returns the name.
270    pub fn name(&self) -> &str {
271        &self.name
272    }
273    /// Returns the raw pointer value.
274    pub fn raw(&self) -> usize {
275        self.ptr
276    }
277}
278/// A pool of reusable string buffers.
279#[allow(dead_code)]
280pub struct StringPool {
281    free: Vec<String>,
282}
283#[allow(dead_code)]
284impl StringPool {
285    /// Creates a new empty string pool.
286    pub fn new() -> Self {
287        Self { free: Vec::new() }
288    }
289    /// Takes a string from the pool (may be empty).
290    pub fn take(&mut self) -> String {
291        self.free.pop().unwrap_or_default()
292    }
293    /// Returns a string to the pool.
294    pub fn give(&mut self, mut s: String) {
295        s.clear();
296        self.free.push(s);
297    }
298    /// Returns the number of free strings in the pool.
299    pub fn free_count(&self) -> usize {
300        self.free.len()
301    }
302}
303/// A label set for a graph node.
304#[allow(dead_code)]
305pub struct LabelSet {
306    labels: Vec<String>,
307}
308#[allow(dead_code)]
309impl LabelSet {
310    /// Creates a new empty label set.
311    pub fn new() -> Self {
312        Self { labels: Vec::new() }
313    }
314    /// Adds a label (deduplicates).
315    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    /// Returns `true` if `label` is present.
322    pub fn has(&self, label: &str) -> bool {
323        self.labels.iter().any(|l| l == label)
324    }
325    /// Returns the count of labels.
326    pub fn count(&self) -> usize {
327        self.labels.len()
328    }
329    /// Returns all labels.
330    pub fn all(&self) -> &[String] {
331        &self.labels
332    }
333}
334/// A sparse vector: stores only non-default elements.
335#[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    /// Creates a new sparse vector with logical length `len`.
344    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    /// Sets element at `idx`.
352    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    /// Gets element at `idx`.
360    pub fn get(&self, idx: usize) -> &T {
361        self.entries.get(&idx).unwrap_or(&self.default_)
362    }
363    /// Returns the logical length.
364    pub fn len(&self) -> usize {
365        self.logical_len
366    }
367    /// Returns whether the collection is empty.
368    pub fn is_empty(&self) -> bool {
369        self.len() == 0
370    }
371    /// Returns the number of non-default elements.
372    pub fn nnz(&self) -> usize {
373        self.entries.len()
374    }
375}
376/// A counter that can measure elapsed time between snapshots.
377#[allow(dead_code)]
378pub struct Stopwatch {
379    start: crate::wall_clock::Instant,
380    splits: Vec<f64>,
381}
382#[allow(dead_code)]
383impl Stopwatch {
384    /// Creates and starts a new stopwatch.
385    pub fn start() -> Self {
386        Self {
387            start: crate::wall_clock::Instant::now(),
388            splits: Vec::new(),
389        }
390    }
391    /// Records a split time (elapsed since start).
392    pub fn split(&mut self) {
393        self.splits.push(self.elapsed_ms());
394    }
395    /// Returns total elapsed milliseconds since start.
396    pub fn elapsed_ms(&self) -> f64 {
397        self.start.elapsed().as_secs_f64() * 1000.0
398    }
399    /// Returns all recorded split times.
400    pub fn splits(&self) -> &[f64] {
401        &self.splits
402    }
403    /// Returns the number of splits.
404    pub fn num_splits(&self) -> usize {
405        self.splits.len()
406    }
407}
408/// A tagged union for representing a simple two-case discriminated union.
409#[allow(dead_code)]
410pub enum Either2<A, B> {
411    /// The first alternative.
412    First(A),
413    /// The second alternative.
414    Second(B),
415}
416#[allow(dead_code)]
417impl<A, B> Either2<A, B> {
418    /// Returns `true` if this is the first alternative.
419    pub fn is_first(&self) -> bool {
420        matches!(self, Either2::First(_))
421    }
422    /// Returns `true` if this is the second alternative.
423    pub fn is_second(&self) -> bool {
424        matches!(self, Either2::Second(_))
425    }
426    /// Returns the first value if present.
427    pub fn first(self) -> Option<A> {
428        match self {
429            Either2::First(a) => Some(a),
430            _ => None,
431        }
432    }
433    /// Returns the second value if present.
434    pub fn second(self) -> Option<B> {
435        match self {
436            Either2::Second(b) => Some(b),
437            _ => None,
438        }
439    }
440    /// Maps over the first alternative.
441    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/// A fixed-size sliding window that computes a running sum.
449#[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    /// Creates a sliding sum with the given window size.
460    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    /// Adds a value to the window, removing the oldest if full.
470    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    /// Returns the current window sum.
481    pub fn sum(&self) -> f64 {
482        self.sum
483    }
484    /// Returns the window mean, or `None` if empty.
485    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    /// Returns the current window size (number of valid elements).
493    pub fn count(&self) -> usize {
494        self.count
495    }
496}
497/// A hierarchical configuration tree.
498#[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    /// Creates a leaf config node with a value.
507    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    /// Creates a section node with children.
515    pub fn section(key: impl Into<String>) -> Self {
516        Self {
517            key: key.into(),
518            value: None,
519            children: Vec::new(),
520        }
521    }
522    /// Adds a child node.
523    pub fn add_child(&mut self, child: ConfigNode) {
524        self.children.push(child);
525    }
526    /// Returns the key.
527    pub fn key(&self) -> &str {
528        &self.key
529    }
530    /// Returns the value, or `None` for section nodes.
531    pub fn value(&self) -> Option<&str> {
532        self.value.as_deref()
533    }
534    /// Returns the number of children.
535    pub fn num_children(&self) -> usize {
536        self.children.len()
537    }
538    /// Looks up a dot-separated path.
539    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/// A generic counter that tracks min/max/sum for statistical summaries.
565#[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    /// Creates an empty summary.
575    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    /// Records a sample.
584    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    /// Returns the mean, or `None` if no samples.
595    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    /// Returns the minimum, or `None` if no samples.
603    pub fn min(&self) -> Option<f64> {
604        if self.count == 0 {
605            None
606        } else {
607            Some(self.min)
608        }
609    }
610    /// Returns the maximum, or `None` if no samples.
611    pub fn max(&self) -> Option<f64> {
612        if self.count == 0 {
613            None
614        } else {
615            Some(self.max)
616        }
617    }
618    /// Returns the count of recorded samples.
619    pub fn count(&self) -> u64 {
620        self.count
621    }
622}
623/// A pair of `StatSummary` values tracking before/after a transformation.
624#[allow(dead_code)]
625pub struct TransformStat {
626    before: StatSummary,
627    after: StatSummary,
628}
629#[allow(dead_code)]
630impl TransformStat {
631    /// Creates a new transform stat recorder.
632    pub fn new() -> Self {
633        Self {
634            before: StatSummary::new(),
635            after: StatSummary::new(),
636        }
637    }
638    /// Records a before value.
639    pub fn record_before(&mut self, v: f64) {
640        self.before.record(v);
641    }
642    /// Records an after value.
643    pub fn record_after(&mut self, v: f64) {
644        self.after.record(v);
645    }
646    /// Returns the mean reduction ratio (after/before).
647    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/// A window iterator that yields overlapping windows of size `n`.
657#[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    /// Creates a new window iterator.
666    pub fn new(data: &'a [T], window: usize) -> Self {
667        Self {
668            data,
669            pos: 0,
670            window,
671        }
672    }
673}
674/// A set of rewrite rules.
675#[allow(dead_code)]
676pub struct RewriteRuleSet {
677    rules: Vec<RewriteRule>,
678}
679#[allow(dead_code)]
680impl RewriteRuleSet {
681    /// Creates an empty rule set.
682    pub fn new() -> Self {
683        Self { rules: Vec::new() }
684    }
685    /// Adds a rule.
686    pub fn add(&mut self, rule: RewriteRule) {
687        self.rules.push(rule);
688    }
689    /// Returns the number of rules.
690    pub fn len(&self) -> usize {
691        self.rules.len()
692    }
693    /// Returns `true` if the set is empty.
694    pub fn is_empty(&self) -> bool {
695        self.rules.is_empty()
696    }
697    /// Returns all conditional rules.
698    pub fn conditional_rules(&self) -> Vec<&RewriteRule> {
699        self.rules.iter().filter(|r| r.conditional).collect()
700    }
701    /// Returns all unconditional rules.
702    pub fn unconditional_rules(&self) -> Vec<&RewriteRule> {
703        self.rules.iter().filter(|r| !r.conditional).collect()
704    }
705    /// Looks up a rule by name.
706    pub fn get(&self, name: &str) -> Option<&RewriteRule> {
707        self.rules.iter().find(|r| r.name == name)
708    }
709}
710/// A dependency closure builder (transitive closure via BFS).
711#[allow(dead_code)]
712pub struct TransitiveClosure {
713    adj: Vec<Vec<usize>>,
714    n: usize,
715}
716#[allow(dead_code)]
717impl TransitiveClosure {
718    /// Creates a transitive closure builder for `n` nodes.
719    pub fn new(n: usize) -> Self {
720        Self {
721            adj: vec![Vec::new(); n],
722            n,
723        }
724    }
725    /// Adds a direct edge.
726    pub fn add_edge(&mut self, from: usize, to: usize) {
727        if from < self.n {
728            self.adj[from].push(to);
729        }
730    }
731    /// Computes all nodes reachable from `start` (including `start`).
732    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    /// Returns `true` if `from` can transitively reach `to`.
748    pub fn can_reach(&self, from: usize, to: usize) -> bool {
749        self.reachable_from(from).contains(&to)
750    }
751}
752/// A simple decision tree node for rule dispatching.
753#[allow(dead_code)]
754#[allow(missing_docs)]
755pub enum DecisionNode {
756    /// A leaf with an action string.
757    Leaf(String),
758    /// An interior node: check `key` equals `val` → `yes_branch`, else `no_branch`.
759    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    /// Evaluates the decision tree with the given context.
769    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    /// Returns the depth of the decision tree.
788    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/// A simple directed acyclic graph.
800#[allow(dead_code)]
801pub struct SimpleDag {
802    /// `edges[i]` is the list of direct successors of node `i`.
803    edges: Vec<Vec<usize>>,
804}
805#[allow(dead_code)]
806impl SimpleDag {
807    /// Creates a DAG with `n` nodes and no edges.
808    pub fn new(n: usize) -> Self {
809        Self {
810            edges: vec![Vec::new(); n],
811        }
812    }
813    /// Adds an edge from `from` to `to`.
814    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    /// Returns the successors of `node`.
820    pub fn successors(&self, node: usize) -> &[usize] {
821        self.edges.get(node).map(|v| v.as_slice()).unwrap_or(&[])
822    }
823    /// Returns `true` if `from` can reach `to` via DFS.
824    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    /// Returns the topological order of nodes, or `None` if a cycle is detected.
844    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    /// Returns the number of nodes.
875    pub fn num_nodes(&self) -> usize {
876        self.edges.len()
877    }
878}
879/// A write-once cell.
880#[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    /// Creates an empty write-once cell.
887    pub fn new() -> Self {
888        Self {
889            value: std::cell::Cell::new(None),
890        }
891    }
892    /// Writes a value.  Returns `false` if already written.
893    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    /// Returns the value if written.
901    pub fn read(&self) -> Option<T> {
902        self.value.get()
903    }
904    /// Returns `true` if the value has been written.
905    pub fn is_written(&self) -> bool {
906        self.value.get().is_some()
907    }
908}
909/// A simple stack-based calculator for arithmetic expressions.
910#[allow(dead_code)]
911pub struct StackCalc {
912    stack: Vec<i64>,
913}
914#[allow(dead_code)]
915impl StackCalc {
916    /// Creates a new empty calculator.
917    pub fn new() -> Self {
918        Self { stack: Vec::new() }
919    }
920    /// Pushes an integer literal.
921    pub fn push(&mut self, n: i64) {
922        self.stack.push(n);
923    }
924    /// Replaces the top two values, `b` on top of `a`, with `op(a, b)` and
925    /// returns it.  Returns `None`, leaving the stack unchanged, if it holds
926    /// fewer than two values.
927    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    /// Adds the top two values and returns the sum, which replaces them.
938    /// Returns `None`, leaving the stack unchanged, if it holds fewer than
939    /// two values.
940    pub fn add(&mut self) -> Option<i64> {
941        self.apply_binary(|a, b| a + b)
942    }
943    /// Subtracts top from second and returns the difference, which replaces
944    /// them.  Returns `None`, leaving the stack unchanged, if it holds fewer
945    /// than two values.
946    pub fn sub(&mut self) -> Option<i64> {
947        self.apply_binary(|a, b| a - b)
948    }
949    /// Multiplies the top two values and returns the product, which replaces
950    /// them.  Returns `None`, leaving the stack unchanged, if it holds fewer
951    /// than two values.
952    pub fn mul(&mut self) -> Option<i64> {
953        self.apply_binary(|a, b| a * b)
954    }
955    /// Peeks the top value.
956    pub fn peek(&self) -> Option<i64> {
957        self.stack.last().copied()
958    }
959    /// Returns the stack depth.
960    pub fn depth(&self) -> usize {
961        self.stack.len()
962    }
963}
964/// A trie-based prefix counter.
965#[allow(dead_code)]
966pub struct PrefixCounter {
967    children: std::collections::HashMap<char, PrefixCounter>,
968    count: usize,
969}
970#[allow(dead_code)]
971impl PrefixCounter {
972    /// Creates an empty prefix counter.
973    pub fn new() -> Self {
974        Self {
975            children: std::collections::HashMap::new(),
976            count: 0,
977        }
978    }
979    /// Records a string.
980    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    /// Returns how many strings have been recorded that start with `prefix`.
989    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/// A simple key-value store backed by a sorted Vec for small maps.
1001#[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    /// Creates a new empty small map.
1008    pub fn new() -> Self {
1009        Self {
1010            entries: Vec::new(),
1011        }
1012    }
1013    /// Inserts or replaces the value for `key`.
1014    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    /// Returns the value for `key`, or `None`.
1021    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    /// Returns the number of entries.
1028    pub fn len(&self) -> usize {
1029        self.entries.len()
1030    }
1031    /// Returns `true` if empty.
1032    pub fn is_empty(&self) -> bool {
1033        self.entries.is_empty()
1034    }
1035    /// Returns all keys.
1036    pub fn keys(&self) -> Vec<&K> {
1037        self.entries.iter().map(|(k, _)| k).collect()
1038    }
1039    /// Returns all values.
1040    pub fn values(&self) -> Vec<&V> {
1041        self.entries.iter().map(|(_, v)| v).collect()
1042    }
1043}
1044/// A reusable scratch buffer for path computations.
1045#[allow(dead_code)]
1046pub struct PathBuf {
1047    components: Vec<String>,
1048}
1049#[allow(dead_code)]
1050impl PathBuf {
1051    /// Creates a new empty path buffer.
1052    pub fn new() -> Self {
1053        Self {
1054            components: Vec::new(),
1055        }
1056    }
1057    /// Pushes a component.
1058    pub fn push(&mut self, comp: impl Into<String>) {
1059        self.components.push(comp.into());
1060    }
1061    /// Pops the last component.
1062    pub fn pop(&mut self) {
1063        self.components.pop();
1064    }
1065    /// Returns the current path as a `/`-separated string.
1066    pub fn as_str(&self) -> String {
1067        self.components.join("/")
1068    }
1069    /// Returns the depth of the path.
1070    pub fn depth(&self) -> usize {
1071        self.components.len()
1072    }
1073    /// Clears the path.
1074    pub fn clear(&mut self) {
1075        self.components.clear();
1076    }
1077}
1078/// A mutable reference stack for tracking the current "focus" in a tree traversal.
1079#[allow(dead_code)]
1080pub struct FocusStack<T> {
1081    items: Vec<T>,
1082}
1083#[allow(dead_code)]
1084impl<T> FocusStack<T> {
1085    /// Creates an empty focus stack.
1086    pub fn new() -> Self {
1087        Self { items: Vec::new() }
1088    }
1089    /// Focuses on `item`.
1090    pub fn focus(&mut self, item: T) {
1091        self.items.push(item);
1092    }
1093    /// Blurs (pops) the current focus.
1094    pub fn blur(&mut self) -> Option<T> {
1095        self.items.pop()
1096    }
1097    /// Returns the current focus, or `None`.
1098    pub fn current(&self) -> Option<&T> {
1099        self.items.last()
1100    }
1101    /// Returns the focus depth.
1102    pub fn depth(&self) -> usize {
1103        self.items.len()
1104    }
1105    /// Returns `true` if there is no current focus.
1106    pub fn is_empty(&self) -> bool {
1107        self.items.is_empty()
1108    }
1109}
1110/// A min-heap implemented as a binary heap.
1111#[allow(dead_code)]
1112pub struct MinHeap<T: Ord> {
1113    data: Vec<T>,
1114}
1115#[allow(dead_code)]
1116impl<T: Ord> MinHeap<T> {
1117    /// Creates a new empty min-heap.
1118    pub fn new() -> Self {
1119        Self { data: Vec::new() }
1120    }
1121    /// Inserts an element.
1122    pub fn push(&mut self, val: T) {
1123        self.data.push(val);
1124        self.sift_up(self.data.len() - 1);
1125    }
1126    /// Removes and returns the minimum element.
1127    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    /// Returns a reference to the minimum element.
1140    pub fn peek(&self) -> Option<&T> {
1141        self.data.first()
1142    }
1143    /// Returns the number of elements.
1144    pub fn len(&self) -> usize {
1145        self.data.len()
1146    }
1147    /// Returns `true` if empty.
1148    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}