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: std::fmt::Debug> std::fmt::Debug for List<T> {
30 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
31 write!(f, "{:?}", self.inner)
32 }
33}
34
35impl<T> List<T> {
36 pub fn insert(&mut self, value: T) -> Idx {
39 let index = if let Some(index) = self.inner.iter_mut().position(|v| v.is_none()) {
40 self.inner[index] = Some(value);
41 index
42 } else {
43 self.inner.push(Some(value));
44 self.inner.len() - 1
45 };
46
47 Self::to_call_index(index)
48 }
49
50 pub fn get(&self, index: Idx) -> Option<&T> {
52 let index = Self::to_internal_index(index)?;
53 self.inner.get(index).map(|v| v.as_ref()).unwrap_or_default()
54 }
55
56 pub fn get_mut(&mut self, index: Idx) -> Option<&mut T> {
59 let index = Self::to_internal_index(index)?;
60 self.inner.get_mut(index).map(|v| v.as_mut()).unwrap_or_default()
61 }
62
63 pub fn remove(&mut self, index: Idx) -> Option<T> {
65 let index = Self::to_internal_index(index)?;
66 self.inner.get_mut(index).map(|v| v.take()).unwrap_or_default()
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 pub fn calls_mut(&mut self) -> impl Iterator<Item = (Idx, &mut T)> {
79 self.inner
80 .iter_mut()
81 .enumerate()
82 .flat_map(|(i, entry)| entry.as_mut().map(|v| (Self::to_call_index(i), v)))
83 }
84
85 fn to_internal_index(index: Idx) -> Option<usize> {
92 (index != 0).then(|| index - 1)
93 }
94
95 fn to_call_index(internal: usize) -> Idx {
99 internal + 1
100 }
101
102 pub fn len(&self) -> usize {
104 self.inner.iter().map(Option::as_ref).filter(Option::is_some).count()
105 }
106}
107
108#[cfg(test)]
109mod tests {
110 use super::*;
111
112 #[fuchsia::test]
113 fn call_list_insert() {
114 let mut list = List::default();
115 let i1 = list.insert(1);
116 assert_eq!(i1, 1, "The first value must be assigned the number 1");
117 let i2 = list.insert(2);
118 assert_eq!(i2, 2, "The second value is assigned the next available number");
119 }
120
121 #[fuchsia::test]
122 fn call_list_get() {
123 let mut list = List::default();
124 let i1 = list.insert(1);
125 let i2 = list.insert(2);
126 assert_eq!(list.get(0), None);
127 assert_eq!(list.get(i1), Some(&1));
128 assert_eq!(list.get(i2), Some(&2));
129 assert_eq!(list.get(3), None);
130 }
131
132 #[fuchsia::test]
133 fn call_list_get_mut() {
134 let mut list = List::default();
135 let i1 = list.insert(1);
136 let i2 = list.insert(2);
137 assert_eq!(list.get_mut(i1), Some(&mut 1));
138 assert_eq!(list.get_mut(i2), Some(&mut 2));
139 assert_eq!(list.get_mut(3), None);
140 }
141
142 #[fuchsia::test]
143 fn call_list_remove() {
144 let mut list = List::default();
145 let i1 = list.insert(1);
146 let i2 = list.insert(2);
147 let removed = list.remove(i1);
148 assert!(removed.is_some());
149 assert_eq!(list.get(i1), None, "The value at i1 is removed");
150 assert_eq!(list.get(i2), Some(&2), "The value at i2 is untouched");
151 let invalid_idx = 0;
152 assert!(list.remove(invalid_idx).is_none());
153 }
154
155 #[fuchsia::test]
156 fn call_list_remove_and_insert_behaves() {
157 let mut list = List::default();
158 let i1 = list.insert(1);
159 let i2 = list.insert(2);
160 let i3 = list.insert(3);
161 let i4 = list.insert(4);
162 assert!(list.remove(i2).is_some());
163 assert!(list.remove(i1).is_some());
164 assert!(list.remove(i3).is_some());
165 let i5 = list.insert(5);
166 assert_eq!(
167 i5, i1,
168 "i5 is the lowest possible index (i1) even though i1 was not the first or last index removed"
169 );
170 assert_eq!(list.get(i5), Some(&5), "The value at i5 is correct");
171 let i6 = list.insert(6);
172 let i7 = list.insert(7);
173 assert_eq!(i6, i2, "i6 takes the next available index (i2)");
174 assert_eq!(i7, i3, "i7 takes the next available index (i3)");
175 let i8_ = list.insert(8);
176 assert_ne!(i8_, i4, "i4 is reserved, so i8_ must take a new index");
177 assert_eq!(
178 i8_, 5,
179 "i8_ takes an index of 5 since it is the last of the 5 values to be inserted"
180 );
181 }
182
183 #[fuchsia::test]
184 fn call_list_iter_returns_all_valid_values() {
185 let mut list = List::default();
186 let i1 = list.insert(1);
187 let i2 = list.insert(2);
188 let i3 = list.insert(3);
189 let i4 = list.insert(4);
190 assert!(list.remove(i2).is_some());
191 let actual: Vec<_> = list.calls().collect();
192 let expected = vec![(i1, &1), (i3, &3), (i4, &4)];
193 assert_eq!(actual, expected);
194 }
195}