fixed_index_vec/
lib.rs

1#![deny(missing_docs)]
2#![doc = include_str!("../README.md")]
3use std::collections::{BTreeMap, HashMap};
4use std::fmt::Display;
5
6/// A fixed-size indexed vector that maps indices to values.
7///
8/// It provides a fixed-size vector-like data structure that can store values based on its
9/// associated index.
10/// Each value is associated with a unique index in the map.
11/// The values can be
12/// accessed, inserted, and removed using the index as the identifier.
13///
14/// # Examples
15///
16/// ```
17/// use fixed_index_vec::FixedIndexVec;
18///
19/// let mut vec = FixedIndexVec::new();
20///
21/// vec.insert("value1".to_string());
22/// vec.insert("value2".to_string());
23///
24/// assert_eq!(vec.get(0), Some(&"value1".to_string()));
25/// assert_eq!(vec.get(1), Some(&"value2".to_string()));
26///
27/// vec.remove(1);
28///
29/// assert_eq!(vec.get(1), None);
30/// ```
31///
32/// # Notes
33///
34/// - The `FixedIndexVec` is backed by a `BTreeMap`, so it is not as fast as a `Vec`.
35/// - Index notations are supported (eg. `vec[0]`), however, accessing an index that does not
36///  exist will panic.
37#[derive(Clone, Debug, Default, Hash, PartialEq, Eq, PartialOrd, Ord)]
38#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
39pub struct FixedIndexVec<T> {
40    map: BTreeMap<usize, T>,
41    next_index: usize,
42}
43
44impl<T: Display> Display for FixedIndexVec<T> {
45    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
46        let mut s = String::new();
47        for (i, v) in self.iter() {
48            s.push_str(&format!("{}: {}\n", i, v));
49        }
50        write!(f, "{}", s)
51    }
52}
53
54impl<T> FixedIndexVec<T> {
55    /// Creates an empty `FixedIndexVec`.
56    ///
57    /// The internal storage will not allocate until elements are pushed onto it.
58    ///
59    /// # Examples
60    ///
61    /// ```
62    /// use fixed_index_vec::FixedIndexVec;
63    /// let mut vec: FixedIndexVec<i32> = FixedIndexVec::new();
64    /// ```
65    pub fn new() -> FixedIndexVec<T> {
66        FixedIndexVec {
67            map: BTreeMap::new(),
68            next_index: 0,
69        }
70    }
71
72    /// Inserts an element at the end of the `FixedIndexVec`.
73    ///
74    /// # Panics
75    ///
76    /// Panics if the `FixedIndexVec` is at capacity.
77    ///
78    /// # Examples
79    ///
80    /// ```
81    /// use fixed_index_vec::FixedIndexVec;
82    ///
83    /// let mut vec = FixedIndexVec::new();
84    /// vec.push(1);
85    /// vec.push(2);
86    /// assert_eq!(vec[0], 1);
87    /// assert_eq!(vec[1], 2);
88    /// ```
89    pub fn push(&mut self, value: T) {
90        self.map.insert(self.next_index, value);
91        self.next_index += 1;
92    }
93
94    /// Alias for `push`.
95    /// Inserts an element at the end of the `FixedIndexVec`.
96    ///
97    /// # Panics
98    ///
99    /// Panics if the `FixedIndexVec` is at capacity.
100    ///
101    /// # Examples
102    ///
103    /// ```
104    /// use fixed_index_vec::FixedIndexVec;
105    ///
106    /// let mut vec = FixedIndexVec::new();
107    /// vec.insert(1);
108    /// vec.insert(2);
109    /// assert_eq!(vec[0], 1);
110    /// assert_eq!(vec[1], 2);
111    /// ```
112    pub fn insert(&mut self, value: T) {
113        self.push(value);
114    }
115
116    /// Removes the element at the given index, if it exists, returning it or `None` if it does not exist.
117    ///
118    /// # Examples
119    ///
120    /// ```
121    /// use fixed_index_vec::FixedIndexVec;
122    ///
123    /// let mut vec = FixedIndexVec::new();
124    /// vec.push(1);
125    /// vec.push(2);
126    /// assert_eq!(vec.remove(0), Some(1));
127    /// assert_eq!(vec.remove(0), None);
128    /// ```
129    ///
130    /// # Notes
131    ///
132    /// Unlike `Vec::remove`, this does not shift elements after the removed element.
133    /// If index >= length, this returns `None`, the same as if the element did not exist.
134    pub fn remove(&mut self, index: usize) -> Option<T> {
135        self.map.remove(&index)
136    }
137
138    /// Returns a reference to the element at the given index,
139    /// if it exists, or `None` if it does not exist.
140    ///
141    /// # Examples
142    ///
143    /// ```
144    /// use fixed_index_vec::FixedIndexVec;
145    ///
146    /// let mut vec = FixedIndexVec::new();
147    /// vec.push(1);
148    /// vec.push(2);
149    /// assert_eq!(vec.get(0), Some(&1));
150    /// assert_eq!(vec.get(2), None);
151    /// ```
152    pub fn get(&self, index: usize) -> Option<&T> {
153        self.map.get(&index)
154    }
155
156    /// An iterator visiting all elements in ascending order of their indices.
157    /// The index is returned along with the value.
158    /// The iterator skips indices that do not have a corresponding value.
159    ///
160    /// # Examples
161    ///
162    /// ```
163    /// use fixed_index_vec::FixedIndexVec;
164    ///
165    /// let mut vec: FixedIndexVec<i32> = vec![1, 2, 3].into();
166    /// vec.remove(1);
167    /// let mut iter = vec.iter();
168    /// assert_eq!(iter.next(), Some((0, &1)));
169    /// assert_eq!(iter.next(), Some((2, &3)));
170    /// assert_eq!(iter.next(), None);
171    /// ```
172    pub fn iter(&self) -> impl Iterator<Item = (usize, &T)> {
173        self.map.iter().map(|(i, v)| (*i, v))
174    }
175
176    /// Returns the number of elements in the `FixedIndexVec`.
177    /// This is not the same as the value of the largest index, unless no elements have been removed.
178    ///
179    /// # Examples
180    ///
181    /// ```
182    /// use fixed_index_vec::FixedIndexVec;
183    ///
184    /// let mut vec: FixedIndexVec<i32> = vec![1, 2, 3].into();
185    /// vec.remove(1);
186    /// assert_eq!(vec.len(), 2);
187    /// ```
188    pub fn len(&self) -> usize {
189        self.map.len()
190    }
191
192    /// Returns `true` if the `FixedIndexVec` contains no elements.
193    ///
194    /// # Examples
195    ///
196    /// ```
197    /// use fixed_index_vec::FixedIndexVec;
198    ///
199    /// let mut vec: FixedIndexVec<i32> = vec![1, 2, 3].into();
200    /// vec.remove(1);
201    /// assert_eq!(vec.is_empty(), false);
202    /// ```
203    /// ```
204    /// use fixed_index_vec::FixedIndexVec;
205    /// let vec: FixedIndexVec<i32> = FixedIndexVec::new();
206    /// assert_eq!(vec.is_empty(), true);
207    /// ```
208    pub fn is_empty(&self) -> bool {
209        self.map.is_empty()
210    }
211
212    /// Clears the `FixedIndexVec`, removing all values.
213    /// Keeps the allocated memory for reuse.
214    /// This is equivalent to calling `remove` on every index.
215    /// The next index will *not* be reset to 0.
216    ///
217    /// # Examples
218    /// ```
219    /// use fixed_index_vec::FixedIndexVec;
220    ///
221    /// let mut vec: FixedIndexVec<i32> = vec![1, 2, 3].into();
222    /// vec.clear();
223    /// assert_eq!(vec.len(), 0);
224    /// assert_eq!(vec.next_index(), 3);
225    /// ```
226    pub fn clear(&mut self) {
227        self.map.clear();
228    }
229
230    /// Clears the `FixedIndexVec`, removing all values and resetting the next index to 0.
231    /// Keeps the allocated memory for reuse.
232    ///
233    /// # Examples
234    ///
235    /// ```
236    /// use fixed_index_vec::FixedIndexVec;
237    ///
238    /// let mut vec: FixedIndexVec<i32> = vec![1, 2, 3].into();
239    /// vec.reset();
240    /// assert_eq!(vec.len(), 0);
241    /// assert_eq!(vec.next_index(), 0);
242    /// ```
243    pub fn reset(&mut self) {
244        self.map.clear();
245        self.next_index = 0;
246    }
247
248    /// Returns the next index that will be used when inserting an element.
249    ///
250    /// # Examples
251    ///
252    /// ```
253    /// use fixed_index_vec::FixedIndexVec;
254    ///
255    /// let mut vec: FixedIndexVec<i32> = vec![1, 2, 3].into();
256    /// vec.remove(1);
257    /// assert_eq!(vec.next_index(), 3);
258    /// ```
259    pub fn next_index(&self) -> usize {
260        self.next_index
261    }
262
263    /// Returns the index and a reference to the element at the smallest populated index, or `None`
264    /// if the `FixedIndexVec` is empty.
265    ///
266    /// # Examples
267    ///
268    /// ```
269    /// use fixed_index_vec::FixedIndexVec;
270    ///
271    /// let mut vec: FixedIndexVec<i32> = vec![1, 2, 3].into();
272    /// vec.remove(0);
273    /// assert_eq!(vec.first(), Some((1, &2)));
274    /// ```
275    /// ```
276    /// use fixed_index_vec::FixedIndexVec;
277    ///
278    /// let vec: FixedIndexVec<i32> = FixedIndexVec::new();
279    /// assert_eq!(vec.first(), None);
280    pub fn first(&self) -> Option<(usize, &T)> {
281        self.iter().next()
282    }
283
284    /// Returns the index and a reference to the element at the largest populated index, or `None`
285    /// if the `FixedIndexVec` is empty.
286    ///
287    /// # Examples
288    ///
289    /// ```
290    /// use fixed_index_vec::FixedIndexVec;
291    ///
292    /// let mut vec: FixedIndexVec<i32> = vec![1, 2, 3].into();
293    /// vec.remove(2);
294    /// assert_eq!(vec.last(), Some((1, &2)));
295    /// ```
296    /// ```
297    /// use fixed_index_vec::FixedIndexVec;
298    ///
299    /// let vec: FixedIndexVec<i32> = FixedIndexVec::new();
300    /// assert_eq!(vec.last(), None);
301    /// ```
302    pub fn last(&self) -> Option<(usize, &T)> {
303        self.iter().last()
304    }
305}
306
307impl<T> std::ops::Index<usize> for FixedIndexVec<T> {
308    type Output = T;
309
310    fn index(&self, index: usize) -> &T {
311        self.get(index).unwrap()
312    }
313}
314
315impl<T> FromIterator<T> for FixedIndexVec<T> {
316    fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> FixedIndexVec<T> {
317        let mut map = BTreeMap::new();
318        for (i, v) in iter.into_iter().enumerate() {
319            map.insert(i, v);
320        }
321        FixedIndexVec {
322            next_index: map.len(),
323            map,
324        }
325    }
326}
327
328impl<T> Extend<T> for FixedIndexVec<T> {
329    fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
330        for v in iter.into_iter() {
331            self.push(v);
332        }
333    }
334}
335
336impl<T> From<Vec<T>> for FixedIndexVec<T> {
337    fn from(vec: Vec<T>) -> FixedIndexVec<T> {
338        vec.into_iter().collect()
339    }
340}
341
342impl<T, A> From<HashMap<A, T>> for FixedIndexVec<T> {
343    fn from(map: HashMap<A, T>) -> FixedIndexVec<T> {
344        map.into_values().collect()
345    }
346}
347
348impl<T, A> From<BTreeMap<A, T>> for FixedIndexVec<T> {
349    fn from(map: BTreeMap<A, T>) -> FixedIndexVec<T> {
350        map.into_values().collect()
351    }
352}
353
354#[cfg(test)]
355mod tests {
356    use super::FixedIndexVec;
357
358    #[test]
359    fn test_send() {
360        fn assert_send<T: Send>() {}
361        assert_send::<FixedIndexVec<i32>>();
362        assert_send::<FixedIndexVec<f32>>();
363        assert_send::<FixedIndexVec<String>>();
364    }
365    #[test]
366    fn test_sync() {
367        fn assert_sync<T: Sync>() {}
368        assert_sync::<FixedIndexVec<i32>>();
369        assert_sync::<FixedIndexVec<f32>>();
370        assert_sync::<FixedIndexVec<String>>();
371    }
372}