1pub type Idx = usize;
8
9pub struct List<T> {
20 inner: Vec<Option<T>>,
21}
22
23impl<T> Default for List<T> {
24 fn default() -> Self {
25 Self { inner: Vec::default() }
26 }
27}
28
29impl<T> List<T> {
30 pub fn insert(&mut self, value: T) -> Idx {
33 let index = if let Some(index) = self.inner.iter_mut().position(|v| v.is_none()) {
34 self.inner[index] = Some(value);
35 index
36 } else {
37 self.inner.push(Some(value));
38 self.inner.len() - 1
39 };
40
41 Self::to_call_index(index)
42 }
43
44 pub fn get(&self, index: Idx) -> Option<&T> {
46 match Self::to_internal_index(index) {
47 Some(index) => self.inner.get(index).map(|v| v.as_ref()).unwrap_or(None),
48 None => None,
49 }
50 }
51
52 pub fn get_mut(&mut self, index: Idx) -> Option<&mut T> {
55 match Self::to_internal_index(index) {
56 Some(index) => self.inner.get_mut(index).map(|v| v.as_mut()).unwrap_or(None),
57 None => None,
58 }
59 }
60
61 pub fn remove(&mut self, index: Idx) -> Option<T> {
63 match Self::to_internal_index(index) {
64 Some(index) => self.inner.get_mut(index).map(|v| v.take()).unwrap_or(None),
65 None => None,
66 }
67 }
68
69 pub fn calls(&self) -> impl Iterator<Item = (Idx, &T)> + Clone {
71 self.inner
72 .iter()
73 .enumerate()
74 .flat_map(|(i, entry)| entry.as_ref().map(|v| (Self::to_call_index(i), v)))
75 }
76
77 fn to_internal_index(index: Idx) -> Option<usize> {
84 (index != 0).then(|| index - 1)
85 }
86
87 fn to_call_index(internal: usize) -> Idx {
91 internal + 1
92 }
93}
94
95#[cfg(test)]
96mod tests {
97 use super::*;
98
99 #[fuchsia::test]
100 fn call_list_insert() {
101 let mut list = List::default();
102 let i1 = list.insert(1);
103 assert_eq!(i1, 1, "The first value must be assigned the number 1");
104 let i2 = list.insert(2);
105 assert_eq!(i2, 2, "The second value is assigned the next available number");
106 }
107
108 #[fuchsia::test]
109 fn call_list_get() {
110 let mut list = List::default();
111 let i1 = list.insert(1);
112 let i2 = list.insert(2);
113 assert_eq!(list.get(0), None);
114 assert_eq!(list.get(i1), Some(&1));
115 assert_eq!(list.get(i2), Some(&2));
116 assert_eq!(list.get(3), None);
117 }
118
119 #[fuchsia::test]
120 fn call_list_get_mut() {
121 let mut list = List::default();
122 let i1 = list.insert(1);
123 let i2 = list.insert(2);
124 assert_eq!(list.get_mut(i1), Some(&mut 1));
125 assert_eq!(list.get_mut(i2), Some(&mut 2));
126 assert_eq!(list.get_mut(3), None);
127 }
128
129 #[fuchsia::test]
130 fn call_list_remove() {
131 let mut list = List::default();
132 let i1 = list.insert(1);
133 let i2 = list.insert(2);
134 let removed = list.remove(i1);
135 assert!(removed.is_some());
136 assert_eq!(list.get(i1), None, "The value at i1 is removed");
137 assert_eq!(list.get(i2), Some(&2), "The value at i2 is untouched");
138 let invalid_idx = 0;
139 assert!(list.remove(invalid_idx).is_none());
140 }
141
142 #[fuchsia::test]
143 fn call_list_remove_and_insert_behaves() {
144 let mut list = List::default();
145 let i1 = list.insert(1);
146 let i2 = list.insert(2);
147 let i3 = list.insert(3);
148 let i4 = list.insert(4);
149 assert!(list.remove(i2).is_some());
150 assert!(list.remove(i1).is_some());
151 assert!(list.remove(i3).is_some());
152 let i5 = list.insert(5);
153 assert_eq!(i5, i1, "i5 is the lowest possible index (i1) even though i1 was not the first or last index removed");
154 assert_eq!(list.get(i5), Some(&5), "The value at i5 is correct");
155 let i6 = list.insert(6);
156 let i7 = list.insert(7);
157 assert_eq!(i6, i2, "i6 takes the next available index (i2)");
158 assert_eq!(i7, i3, "i7 takes the next available index (i3)");
159 let i8_ = list.insert(8);
160 assert_ne!(i8_, i4, "i4 is reserved, so i8_ must take a new index");
161 assert_eq!(
162 i8_, 5,
163 "i8_ takes an index of 5 since it is the last of the 5 values to be inserted"
164 );
165 }
166
167 #[fuchsia::test]
168 fn call_list_iter_returns_all_valid_values() {
169 let mut list = List::default();
170 let i1 = list.insert(1);
171 let i2 = list.insert(2);
172 let i3 = list.insert(3);
173 let i4 = list.insert(4);
174 assert!(list.remove(i2).is_some());
175 let actual: Vec<_> = list.calls().collect();
176 let expected = vec![(i1, &1), (i3, &3), (i4, &4)];
177 assert_eq!(actual, expected);
178 }
179}