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    /// Inserts the given value at the back of the `Vec`, returning its index.
26    pub fn push(&mut self, value: Value) -> Index
27    where
28        Index: From<usize>,
29    {
30        let index = self.vec.len().into();
31        self.vec.push(value);
32        index
33    }
34
35    /// Removes the value at the back of the `Vec` and returns it with its index.
36    pub fn pop(&mut self) -> Option<(Index, Value)>
37    where
38        Index: From<usize>,
39    {
40        if let Some(value) = self.vec.pop() {
41            Some((self.vec.len().into(), value))
42        } else {
43            None
44        }
45    }
46}