kermit_algos/
singleton.rs1use kermit_iters::{JoinIterable, LinearIterator, TrieIterable, TrieIterator, TrieIteratorWrapper};
6
7#[derive(Debug, Clone, Copy, PartialEq, Eq)]
8enum State {
9 Root,
10 AtValue,
11 Exhausted,
12}
13
14#[derive(Debug, Clone)]
20pub struct SingletonTrieIter {
21 value: usize,
22 state: State,
23}
24
25impl SingletonTrieIter {
26 pub fn new(value: usize) -> Self {
28 Self {
29 value,
30 state: State::Root,
31 }
32 }
33}
34
35impl LinearIterator for SingletonTrieIter {
36 fn key(&self) -> Option<usize> {
37 match self.state {
38 | State::AtValue => Some(self.value),
39 | State::Root | State::Exhausted => None,
40 }
41 }
42
43 fn next(&mut self) -> Option<usize> {
44 if self.state == State::AtValue {
45 self.state = State::Exhausted;
46 }
47 None
48 }
49
50 fn seek(&mut self, seek_key: usize) -> bool {
51 if self.state != State::AtValue {
52 return false;
53 }
54 if seek_key > self.value {
55 self.state = State::Exhausted;
56 false
57 } else {
58 true
59 }
60 }
61
62 fn at_end(&self) -> bool { self.state == State::Exhausted }
63}
64
65impl TrieIterator for SingletonTrieIter {
66 fn open(&mut self) -> bool {
67 match self.state {
68 | State::Root => {
69 self.state = State::AtValue;
70 true
71 },
72 | State::AtValue | State::Exhausted => false,
73 }
74 }
75
76 fn up(&mut self) -> bool {
77 match self.state {
78 | State::AtValue | State::Exhausted => {
79 self.state = State::Root;
80 true
81 },
82 | State::Root => false,
83 }
84 }
85}
86
87impl IntoIterator for SingletonTrieIter {
88 type IntoIter = TrieIteratorWrapper<Self>;
89 type Item = Vec<usize>;
90
91 fn into_iter(self) -> Self::IntoIter { TrieIteratorWrapper::new(self) }
92}
93
94impl JoinIterable for SingletonTrieIter {}
95
96impl TrieIterable for SingletonTrieIter {
97 fn trie_iter(&self) -> impl TrieIterator + IntoIterator<Item = Vec<usize>> { self.clone() }
98}
99
100#[cfg(test)]
101mod tests {
102 use super::*;
103
104 #[test]
105 fn new_at_root_not_at_end() {
106 let it = SingletonTrieIter::new(42);
107 assert_eq!(it.state, State::Root);
108 assert!(!it.at_end());
109 assert_eq!(it.key(), None);
110 }
111
112 #[test]
113 fn open_descends_to_value() {
114 let mut it = SingletonTrieIter::new(42);
115 assert!(it.open());
116 assert_eq!(it.state, State::AtValue);
117 assert_eq!(it.key(), Some(42));
118 assert!(!it.at_end());
119 }
120
121 #[test]
122 fn next_exhausts_the_level() {
123 let mut it = SingletonTrieIter::new(42);
124 it.open();
125 assert_eq!(it.next(), None);
126 assert_eq!(it.state, State::Exhausted);
127 assert!(it.at_end());
128 assert_eq!(it.key(), None);
129 }
130
131 #[test]
132 fn seek_below_value_stays_at_value() {
133 let mut it = SingletonTrieIter::new(42);
134 it.open();
135 assert!(it.seek(10));
136 assert_eq!(it.key(), Some(42));
137 }
138
139 #[test]
140 fn seek_at_value_stays_at_value() {
141 let mut it = SingletonTrieIter::new(42);
142 it.open();
143 assert!(it.seek(42));
144 assert_eq!(it.key(), Some(42));
145 }
146
147 #[test]
148 fn seek_above_value_exhausts() {
149 let mut it = SingletonTrieIter::new(42);
150 it.open();
151 assert!(!it.seek(43));
152 assert!(it.at_end());
153 }
154
155 #[test]
156 fn up_from_value_returns_to_root() {
157 let mut it = SingletonTrieIter::new(42);
158 it.open();
159 assert!(it.up());
160 assert_eq!(it.state, State::Root);
161 }
162
163 #[test]
164 fn open_then_up_then_reopen_is_idempotent() {
165 let mut it = SingletonTrieIter::new(42);
166 assert!(it.open());
167 assert_eq!(it.key(), Some(42));
168 assert!(it.up());
169 assert!(it.open());
170 assert_eq!(it.key(), Some(42));
171 }
172
173 #[test]
174 fn wrapper_yields_single_tuple() {
175 let tuples: Vec<Vec<usize>> = SingletonTrieIter::new(7).into_iter().collect();
176 assert_eq!(tuples, vec![vec![7]]);
177 }
178}