/ src / typed_vec.rs
typed_vec.rs
  1  /// Implement methods for vectors indexed with typed indices.
  2  ///
  3  /// We use a lot of indices into arrays: we have arrays indexed by input
  4  /// segments, arrays indexed by output segments, arrays indexed by output
  5  /// endpoints, and more. To help keep these straight, we wrap indices
  6  /// in new types, like `SegIdx`, `OutputSegIdx`, etc., and we wrap `Vec`
  7  /// in new types, like `SegVec`, `OutputSegVec`, etc. Then you can only
  8  /// use the right index type with the right vector type.
  9  ///
 10  /// This macro implements a bunch of useful methods on the new-type
 11  /// wrappers. It assumes that the index new-type is just a wrapper
 12  /// around `usize`.
 13  macro_rules! impl_typed_vec {
 14      ($vec_name:ident, $idx_name:ident, $dbg_prefix:expr) => {
 15          impl std::fmt::Debug for $idx_name {
 16              fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 17                  write!(f, "{}_{}", $dbg_prefix, self.0)
 18              }
 19          }
 20  
 21          #[allow(dead_code)]
 22          impl<T> $vec_name<T> {
 23              /// Wraps a plain vector.
 24              pub fn from_vec(vec: Vec<T>) -> Self {
 25                  Self { inner: vec }
 26              }
 27  
 28              /// Creates a new vector with capacity for at least `cap` output segments before reallocating.
 29              pub fn with_capacity(cap: usize) -> Self {
 30                  Self {
 31                      inner: Vec::with_capacity(cap),
 32                  }
 33              }
 34  
 35              /// Returns an iterator over all indices into this vector.
 36              pub fn indices(&self) -> impl Iterator<Item = $idx_name> {
 37                  (0..self.inner.len()).map($idx_name)
 38              }
 39  
 40              /// The length of this vector.
 41              pub fn len(&self) -> usize {
 42                  self.inner.len()
 43              }
 44  
 45              /// Are we empty?
 46              pub fn is_empty(&self) -> bool {
 47                  self.inner.is_empty()
 48              }
 49  
 50              /// Adds a new element, returning its index.
 51              pub fn push(&mut self, elt: T) -> $idx_name {
 52                  self.inner.push(elt);
 53                  $idx_name(self.len() - 1)
 54              }
 55  
 56              /// Returns an iterator over indices and elements.
 57              pub fn iter(&self) -> impl Iterator<Item = ($idx_name, &T)> + '_ {
 58                  self.inner
 59                      .iter()
 60                      .enumerate()
 61                      .map(|(idx, t)| ($idx_name(idx), t))
 62              }
 63  
 64              /// Returns an iterator over indices and mutable elements.
 65              pub fn iter_mut(&mut self) -> impl Iterator<Item = ($idx_name, &mut T)> + '_ {
 66                  self.inner
 67                      .iter_mut()
 68                      .enumerate()
 69                      .map(|(idx, t)| ($idx_name(idx), t))
 70              }
 71          }
 72  
 73          #[allow(dead_code)]
 74          impl<T: Default> $vec_name<T> {
 75              /// Creates a new vector with `size` elements, each initialized with the default value.
 76              pub fn with_size(size: usize) -> Self {
 77                  Self {
 78                      inner: std::iter::from_fn(|| Some(T::default()))
 79                          .take(size)
 80                          .collect(),
 81                  }
 82              }
 83          }
 84  
 85          impl<T> Default for $vec_name<T> {
 86              fn default() -> Self {
 87                  Self { inner: Vec::new() }
 88              }
 89          }
 90  
 91          impl<T> std::ops::Index<$idx_name> for $vec_name<T> {
 92              type Output = T;
 93  
 94              fn index(&self, index: $idx_name) -> &Self::Output {
 95                  &self.inner[index.0]
 96              }
 97          }
 98  
 99          impl<T> std::ops::IndexMut<$idx_name> for $vec_name<T> {
100              fn index_mut(&mut self, index: $idx_name) -> &mut T {
101                  &mut self.inner[index.0]
102              }
103          }
104  
105          impl<T: std::fmt::Debug> std::fmt::Debug for $vec_name<T> {
106              fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
107                  struct Entry<'a, T> {
108                      idx: $idx_name,
109                      inner: &'a T,
110                  }
111  
112                  impl<T: std::fmt::Debug> std::fmt::Debug for Entry<'_, T> {
113                      fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
114                          write!(f, "{idx:?}: {inner:?}", idx = self.idx, inner = self.inner,)
115                      }
116                  }
117  
118                  let mut list = f.debug_list();
119                  for idx in self.indices() {
120                      list.entry(&Entry {
121                          idx,
122                          inner: &self[idx],
123                      });
124                  }
125                  list.finish()
126              }
127          }
128      };
129  }