| use std::marker::PhantomData; |
| use std::ops::{Index, IndexMut}; |
| use std::{fmt, slice}; |
| |
| use crate::{Idx, IndexVec}; |
| |
| /// A view into contiguous `T`s, indexed by `I` rather than by `usize`. |
| /// |
| /// One common pattern you'll see is code that uses [`IndexVec::from_elem`] |
| /// to create the storage needed for a particular "universe" (aka the set of all |
| /// the possible keys that need an associated value) then passes that working |
| /// area as `&mut IndexSlice<I, T>` to clarify that nothing will be added nor |
| /// removed during processing (and, as a bonus, to chase fewer pointers). |
| #[derive(PartialEq, Eq, Hash)] |
| #[repr(transparent)] |
| pub struct IndexSlice<I: Idx, T> { |
| _marker: PhantomData<fn(&I)>, |
| pub raw: [T], |
| } |
| |
| impl<I: Idx, T> IndexSlice<I, T> { |
| #[inline] |
| pub const fn empty<'a>() -> &'a Self { |
| Self::from_raw(&[]) |
| } |
| |
| #[inline] |
| pub const fn from_raw(raw: &[T]) -> &Self { |
| let ptr: *const [T] = raw; |
| // SAFETY: `IndexSlice` is `repr(transparent)` over a normal slice |
| unsafe { &*(ptr as *const Self) } |
| } |
| |
| #[inline] |
| pub fn from_raw_mut(raw: &mut [T]) -> &mut Self { |
| let ptr: *mut [T] = raw; |
| // SAFETY: `IndexSlice` is `repr(transparent)` over a normal slice |
| unsafe { &mut *(ptr as *mut Self) } |
| } |
| |
| #[inline] |
| pub const fn len(&self) -> usize { |
| self.raw.len() |
| } |
| |
| #[inline] |
| pub const fn is_empty(&self) -> bool { |
| self.raw.is_empty() |
| } |
| |
| /// Gives the next index that will be assigned when `push` is called. |
| /// |
| /// Manual bounds checks can be done using `idx < slice.next_index()` |
| /// (as opposed to `idx.index() < slice.len()`). |
| #[inline] |
| pub fn next_index(&self) -> I { |
| I::new(self.len()) |
| } |
| |
| #[inline] |
| pub fn iter(&self) -> slice::Iter<'_, T> { |
| self.raw.iter() |
| } |
| |
| #[inline] |
| pub fn iter_enumerated( |
| &self, |
| ) -> impl DoubleEndedIterator<Item = (I, &T)> + ExactSizeIterator + '_ { |
| self.raw.iter().enumerate().map(|(n, t)| (I::new(n), t)) |
| } |
| |
| #[inline] |
| pub fn indices( |
| &self, |
| ) -> impl DoubleEndedIterator<Item = I> + ExactSizeIterator + Clone + 'static { |
| (0..self.len()).map(|n| I::new(n)) |
| } |
| |
| #[inline] |
| pub fn iter_mut(&mut self) -> slice::IterMut<'_, T> { |
| self.raw.iter_mut() |
| } |
| |
| #[inline] |
| pub fn iter_enumerated_mut( |
| &mut self, |
| ) -> impl DoubleEndedIterator<Item = (I, &mut T)> + ExactSizeIterator + '_ { |
| self.raw.iter_mut().enumerate().map(|(n, t)| (I::new(n), t)) |
| } |
| |
| #[inline] |
| pub fn last_index(&self) -> Option<I> { |
| self.len().checked_sub(1).map(I::new) |
| } |
| |
| #[inline] |
| pub fn swap(&mut self, a: I, b: I) { |
| self.raw.swap(a.index(), b.index()) |
| } |
| |
| #[inline] |
| pub fn get(&self, index: I) -> Option<&T> { |
| self.raw.get(index.index()) |
| } |
| |
| #[inline] |
| pub fn get_mut(&mut self, index: I) -> Option<&mut T> { |
| self.raw.get_mut(index.index()) |
| } |
| |
| /// Returns mutable references to two distinct elements, `a` and `b`. |
| /// |
| /// Panics if `a == b`. |
| #[inline] |
| pub fn pick2_mut(&mut self, a: I, b: I) -> (&mut T, &mut T) { |
| let (ai, bi) = (a.index(), b.index()); |
| assert!(ai != bi); |
| |
| if ai < bi { |
| let (c1, c2) = self.raw.split_at_mut(bi); |
| (&mut c1[ai], &mut c2[0]) |
| } else { |
| let (c2, c1) = self.pick2_mut(b, a); |
| (c1, c2) |
| } |
| } |
| |
| /// Returns mutable references to three distinct elements. |
| /// |
| /// Panics if the elements are not distinct. |
| #[inline] |
| pub fn pick3_mut(&mut self, a: I, b: I, c: I) -> (&mut T, &mut T, &mut T) { |
| let (ai, bi, ci) = (a.index(), b.index(), c.index()); |
| assert!(ai != bi && bi != ci && ci != ai); |
| let len = self.raw.len(); |
| assert!(ai < len && bi < len && ci < len); |
| let ptr = self.raw.as_mut_ptr(); |
| unsafe { (&mut *ptr.add(ai), &mut *ptr.add(bi), &mut *ptr.add(ci)) } |
| } |
| |
| #[inline] |
| pub fn binary_search(&self, value: &T) -> Result<I, I> |
| where |
| T: Ord, |
| { |
| match self.raw.binary_search(value) { |
| Ok(i) => Ok(Idx::new(i)), |
| Err(i) => Err(Idx::new(i)), |
| } |
| } |
| } |
| |
| impl<I: Idx, J: Idx> IndexSlice<I, J> { |
| /// Invert a bijective mapping, i.e. `invert(map)[y] = x` if `map[x] = y`, |
| /// assuming the values in `self` are a permutation of `0..self.len()`. |
| /// |
| /// This is used to go between `memory_index` (source field order to memory order) |
| /// and `inverse_memory_index` (memory order to source field order). |
| /// See also `FieldsShape::Arbitrary::memory_index` for more details. |
| // FIXME(eddyb) build a better abstraction for permutations, if possible. |
| pub fn invert_bijective_mapping(&self) -> IndexVec<J, I> { |
| debug_assert_eq!( |
| self.iter().map(|x| x.index() as u128).sum::<u128>(), |
| (0..self.len() as u128).sum::<u128>(), |
| "The values aren't 0..N in input {self:?}", |
| ); |
| |
| let mut inverse = IndexVec::from_elem_n(Idx::new(0), self.len()); |
| for (i1, &i2) in self.iter_enumerated() { |
| inverse[i2] = i1; |
| } |
| |
| debug_assert_eq!( |
| inverse.iter().map(|x| x.index() as u128).sum::<u128>(), |
| (0..inverse.len() as u128).sum::<u128>(), |
| "The values aren't 0..N in result {self:?}", |
| ); |
| |
| inverse |
| } |
| } |
| |
| impl<I: Idx, T: fmt::Debug> fmt::Debug for IndexSlice<I, T> { |
| fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { |
| fmt::Debug::fmt(&self.raw, fmt) |
| } |
| } |
| |
| impl<I: Idx, T> Index<I> for IndexSlice<I, T> { |
| type Output = T; |
| |
| #[inline] |
| fn index(&self, index: I) -> &T { |
| &self.raw[index.index()] |
| } |
| } |
| |
| impl<I: Idx, T> IndexMut<I> for IndexSlice<I, T> { |
| #[inline] |
| fn index_mut(&mut self, index: I) -> &mut T { |
| &mut self.raw[index.index()] |
| } |
| } |
| |
| impl<'a, I: Idx, T> IntoIterator for &'a IndexSlice<I, T> { |
| type Item = &'a T; |
| type IntoIter = slice::Iter<'a, T>; |
| |
| #[inline] |
| fn into_iter(self) -> slice::Iter<'a, T> { |
| self.raw.iter() |
| } |
| } |
| |
| impl<'a, I: Idx, T> IntoIterator for &'a mut IndexSlice<I, T> { |
| type Item = &'a mut T; |
| type IntoIter = slice::IterMut<'a, T>; |
| |
| #[inline] |
| fn into_iter(self) -> slice::IterMut<'a, T> { |
| self.raw.iter_mut() |
| } |
| } |
| |
| impl<I: Idx, T: Clone> ToOwned for IndexSlice<I, T> { |
| type Owned = IndexVec<I, T>; |
| |
| fn to_owned(&self) -> IndexVec<I, T> { |
| IndexVec::from_raw(self.raw.to_owned()) |
| } |
| |
| fn clone_into(&self, target: &mut IndexVec<I, T>) { |
| self.raw.clone_into(&mut target.raw) |
| } |
| } |
| |
| impl<I: Idx, T> Default for &IndexSlice<I, T> { |
| #[inline] |
| fn default() -> Self { |
| IndexSlice::from_raw(Default::default()) |
| } |
| } |
| |
| impl<I: Idx, T> Default for &mut IndexSlice<I, T> { |
| #[inline] |
| fn default() -> Self { |
| IndexSlice::from_raw_mut(Default::default()) |
| } |
| } |
| |
| // Whether `IndexSlice` is `Send` depends only on the data, |
| // not the phantom data. |
| unsafe impl<I: Idx, T> Send for IndexSlice<I, T> where T: Send {} |