1use std::fmt::{Debug, Display, Formatter, Result as FmtResult};
25
26pub struct KeyArray<K> {
27 keys: Vec<K>,
28 idx: usize,
29}
30
31impl<K> KeyArray<K>
32where
33 K: Clone + PartialEq + Debug + Display,
34{
35 pub fn new(keys: impl IntoIterator<Item = K>) -> Self {
37 let keys: Vec<K> = keys.into_iter().collect();
38 assert!(
39 !keys.is_empty(),
40 "KeyArray::new: must supply at least one key"
41 );
42 KeyArray { keys, idx: 0 }
43 }
44
45 pub fn new_with(keys: impl IntoIterator<Item = K>, start_idx: usize) -> Self {
47 let keys: Vec<K> = keys.into_iter().collect();
48 assert!(
49 !keys.is_empty(),
50 "KeyArray::new_with: must supply keys"
51 );
52 assert!(
53 start_idx < keys.len(),
54 "KeyArray::new_with: start_idx {} out of bounds",
55 start_idx
56 );
57 KeyArray {
58 keys,
59 idx: start_idx,
60 }
61 }
62
63 pub fn change(&mut self, i: usize) {
66 assert!(
67 i < self.keys.len(),
68 "KeyArray::change: index {} out of bounds",
69 i
70 );
71 self.idx = i;
72 }
73
74 pub fn current(&self) -> &K {
76 &self.keys[self.idx]
77 }
78
79 pub fn current_index(&self) -> usize {
81 self.idx
82 }
83
84 pub fn keys(&self) -> &[K] {
86 &self.keys
87 }
88
89 pub fn len(&self) -> usize {
91 self.keys.len()
92 }
93
94 pub fn is_empty(&self) -> bool {
96 self.len() == 0
97 }
98
99 pub fn push(&mut self, key: K) {
101 self.keys.push(key);
102 }
103
104 pub fn insert(&mut self, i: usize, key: K) {
106 assert!(
107 i <= self.keys.len(),
108 "KeyArray::insert: index {} out of bounds",
109 i
110 );
111 self.keys.insert(i, key);
112 if i <= self.idx {
114 self.idx += 1;
115 }
116 }
117
118 pub fn remove(&mut self, i: usize) -> K {
120 assert!(
121 i < self.keys.len(),
122 "KeyArray::remove: index {} out of bounds",
123 i
124 );
125 let removed = self.keys.remove(i);
126 if self.idx >= self.keys.len() {
128 self.idx = self.keys.len().saturating_sub(1);
130 }
131 removed
132 }
133}
134
135impl<K> Display for KeyArray<K>
136where
137 K: Clone + PartialEq + Debug + Display,
138{
139 fn fmt(&self, f: &mut Formatter) -> FmtResult {
140 write!(
141 f,
142 "keys={:?}, current_idx={}, current={}",
143 self.keys,
144 self.idx,
145 self.current()
146 )
147 }
148}
149
150#[cfg(test)]
151mod tests {
152 use super::*;
153
154 #[test]
155 fn basic_flow() {
156 let mut ka = KeyArray::new(["A", "B", "C"]);
157 assert_eq!(ka.current(), &"A");
158 assert_eq!(ka.current_index(), 0);
159
160 ka.change(2);
161 assert_eq!(ka.current(), &"C");
162
163 ka.push("D");
165 assert_eq!(ka.len(), 4);
166 assert_eq!(ka.keys(), &["A", "B", "C", "D"]);
167
168 ka.insert(0, "X");
170 assert_eq!(ka.keys()[0], "X");
171 assert_eq!(ka.current(), &"C");
173
174 let removed = ka.remove(0);
176 assert_eq!(removed, "X");
177 assert_eq!(ka.keys()[0], "A");
178 }
179
180 #[test]
181 #[should_panic(expected = "out of bounds")]
182 fn change_oob_panics() {
183 let mut ka = KeyArray::new(["Only"]);
184 ka.change(5);
185 }
186
187 #[test]
188 fn display_format() {
189 let ka = KeyArray::new(["Up", "Down"]);
190 let s = format!("{}", ka);
191 assert!(s.contains(r#"["Up", "Down"]"#) && s.contains("current_idx=0"));
192 }
193
194 #[test]
195 fn empty_and_len() {
196 let ka = KeyArray::new_with(["One"], 0);
197 assert!(!ka.is_empty());
198 assert_eq!(ka.len(), 1);
199
200 let mut empty = KeyArray::new(["X"]);
201 empty.remove(0);
202 assert!(empty.is_empty());
203 assert_eq!(empty.len(), 0);
204 }
205}