tagged_vec/
lib.rs

1//! An alternative to the standard libraries' [`Vec`] which is indexed with a custom type instead of [`usize`].
2//!
3//! This is useful to catch errors like using the wrong variable to index the vector.
4
5#![warn(missing_docs)]
6
7use std::marker::PhantomData;
8
9mod trait_impls;
10
11/// A [`Vec`] wrapper that allows indexing only via the given `Index` type.
12///
13/// For actual operation, `Index` must implement [`From<usize>`] and [`Into<usize>`].
14pub struct TaggedVec<Index, Value> {
15    index_type: PhantomData<Index>,
16    vec: Vec<Value>,
17}
18
19impl<Index, Value> TaggedVec<Index, Value> {
20    /// Creates a new empty `TaggedVec`.
21    pub fn new() -> Self {
22        Self::default()
23    }
24
25    /// Returns the number of elements in the `TaggedVec`.
26    pub fn len(&self) -> usize {
27        self.vec.len()
28    }
29
30    /// Returns `true` if the `TaggedVec` contains no elements.
31    pub fn is_empty(&self) -> bool {
32        self.vec.is_empty()
33    }
34
35    /// Inserts the given value at the back of the `TaggedVec`, returning its index.
36    pub fn push(&mut self, value: Value) -> Index
37    where
38        Index: From<usize>,
39    {
40        let index = self.vec.len().into();
41        self.vec.push(value);
42        index
43    }
44
45    /// Removes the value at the back of the `TaggedVec` and returns it with its index.
46    pub fn pop(&mut self) -> Option<(Index, Value)>
47    where
48        Index: From<usize>,
49    {
50        if let Some(value) = self.vec.pop() {
51            Some((self.vec.len().into(), value))
52        } else {
53            None
54        }
55    }
56
57    /// Returns an iterator over references to the entries of the `TaggedVec`.
58    pub fn iter(&self) -> impl Iterator<Item = (Index, &Value)>
59    where
60        Index: From<usize>,
61    {
62        self.vec
63            .iter()
64            .enumerate()
65            .map(|(index, value)| (index.into(), value))
66    }
67
68    /// Returns an iterator over mutable references to the entries of the `TaggedVec`.
69    pub fn iter_mut(&mut self) -> impl Iterator<Item = (Index, &mut Value)>
70    where
71        Index: From<usize>,
72    {
73        self.vec
74            .iter_mut()
75            .enumerate()
76            .map(|(index, value)| (index.into(), value))
77    }
78
79    /// Returns an iterator over references to the values of the `TaggedVec`.
80    pub fn iter_values(&self) -> std::slice::Iter<'_, Value> {
81        self.vec.iter()
82    }
83
84    /// Returns an iterator over mutable references to the values of the `TaggedVec`.
85    pub fn iter_values_mut(&mut self) -> std::slice::IterMut<'_, Value> {
86        self.vec.iter_mut()
87    }
88
89    /// Returns an iterator over the indices of the `TaggedVec`.
90    pub fn iter_indices(&self) -> impl Iterator<Item = Index>
91    where
92        Index: From<usize>,
93    {
94        (0..self.vec.len()).map(Into::into)
95    }
96}