safe_index 0.10.0

Type-safe indexes.
Documentation
//! Handles map code generation.

/// Map code generation.
#[macro_export]
#[doc(hidden)]
macro_rules! map_codegen {
    ($t:ident,
        $(#[$meta:meta])*
        $map:ident
        $($tail:tt)*
    ) => {
        $(#[$meta])*
        #[derive(Debug, Default, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
        pub struct $map<T> {
            vec: $crate::alloc::vec::Vec<T>
        }

        $crate::non_strict! {
            impl<T> core::convert::From<$crate::alloc::vec::Vec<T>> for $map<T> {
                fn from(vec: $crate::alloc::vec::Vec<T>) -> Self {
                    Self { vec }
                }
            }
        }

        impl<T> $map<T> {
            /// Creates an empty map.
            #[inline]
            pub const fn new() -> Self {
                $map { vec: $crate::alloc::vec::Vec::new() }
            }
            /// Creates an empty map with some capacity.
            #[inline]
            pub fn with_capacity(capacity: usize) -> Self {
                $map { vec: $crate::alloc::vec::Vec::with_capacity(capacity) }
            }

            /// Reserves some space for the map.
            #[inline]
            pub fn reserve(&mut self, capa: usize) {
                self.vec.reserve(capa)
            }

            /// Generates an index from a [`usize`] when it is a legal index.
            #[inline]
            pub fn index_from_usize(&self, n: usize) -> Option<$t> {
                if n < self.vec.len() {
                    Some($t { val: n })
                } else {
                    None
                }
            }

            /// Retrieves an entry in the map.
            #[inline]
            pub fn get(&self, idx: $t) -> Option<&T> {
                self.vec.get(idx.get())
            }
            /// Retrieves an entry in the map.
            #[inline]
            pub fn get_mut(&mut self, idx: $t) -> Option<&mut T> {
                self.vec.get_mut(idx.get())
            }

            /// Retrieves the last entry in the map.
            #[inline]
            pub fn last(&self) -> Option<($t, &T)> {
                self.last_index().map(|idx| (idx, &self[idx]))
            }
            /// Retrieves the last entry in the map.
            #[inline]
            pub fn last_mut(&mut self) -> Option<($t, &mut T)> {
                self.last_index().map(move |idx| (idx, &mut self[idx]))
            }

            /// Number of elements in the map.
            #[inline]
            pub fn len(& self) -> usize {
                self.vec.len()
            }
            /// Capacity of the map.
            #[inline]
            pub fn capacity(& self) -> usize {
                self.vec.capacity()
            }

            $crate::non_strict! {
                /// The next free index (wrapped `self.len()`).
                #[inline]
                pub fn next_index(& self) -> $t {
                    $t { val: self.len() }
                }
            }
            /// Index of the last element in the map.
            #[inline]
            pub fn last_index(& self) -> Option<$t> {
                let len = self.len();
                if len > 0 { Some($t { val: len - 1 }) } else { None }
            }

            /// Pushes an element, yields its index.
            ///
            /// If element construction requires the element's index, see [`Self::push_idx`].
            #[inline]
            pub fn push(&mut self, elem: T) -> $t {
                let idx = $t { val: self.len() };
                self.vec.push(elem);
                idx
            }
            /// Pushes an element generated by a function taking the element's index as input.
            ///
            /// This is useful if you want to store the `T`-element's index inside the element,
            /// meaning you need the index to actually create the element.
            #[inline]
            pub fn push_idx(&mut self, new_elem: impl FnOnce($t) -> T) -> $t {
                let idx = $t { val: self.len() };
                self.vec.push(new_elem(idx));
                idx
            }
            /// Same as [`push_idx`], but the builder returns a result.
            #[inline]
            pub fn try_push_idx<E>(&mut self, new_elem: impl FnOnce($t) -> Result<T, E>) -> Result<$t, E> {
                let idx = $t { val: self.len() };
                self.vec.push(new_elem(idx)?);
                Ok(idx)
            }

            $crate::non_strict! {
                /// Pops an element.
                ///
                /// This function is unsafe for the logics of safe indices. This function voids indices
                /// previously created (indices for the last element on entry) and should be used with
                /// great care.
                #[inline]
                pub fn pop(&mut self) -> Option<T> {
                    self.vec.pop()
                }
            }
            $crate::non_strict! {
                /// Clears a map.
                #[inline]
                pub fn clear(&mut self) {
                    self.vec.clear()
                }
            }

            /// Range of the map.
            #[inline]
            pub fn range(&self) -> core::ops::RangeInclusive<$t> {
                $t { val: 0 } ..= $t { val: self.len() }
            }
            /// Iterator over all the indices.
            #[inline]
            pub fn indices(&self) -> impl core::iter::Iterator<Item = $t> {
                (0..self.len()).into_iter().map(|i| $t { val: i })
            }

            /// Ref-iterator over the elements.
            #[inline]
            pub fn iter(& self) -> core::slice::Iter<T> {
                self.vec.iter()
            }
            /// Ref-iterator over the index/element pairs.
            #[inline]
            pub fn index_iter<'a>(&'a self) ->
                impl core::iter::Iterator<Item = ($t, &'a T)>
                + core::iter::DoubleEndedIterator
                + core::iter::ExactSizeIterator
            where T: 'a {
                self.vec.iter().enumerate().map(|(idx, elm)| (
                    $t { val: idx }, elm
                ))
            }
            /// Ref-mut-iterator over the index/element pairs.
            #[inline]
            pub fn index_iter_mut<'a>(&'a mut self) ->
                impl core::iter::Iterator<Item = ($t, &'a mut T)>
                + core::iter::DoubleEndedIterator
                + core::iter::ExactSizeIterator
            where T: 'a {
                self.vec.iter_mut().enumerate().map(|(idx, elm)| (
                    $t { val: idx }, elm
                ))
            }
            /// Own-iterator over the index/element pairs.
            #[inline]
            pub fn into_index_iter(self) ->
                impl core::iter::Iterator<Item = ($t, T)>
                + core::iter::DoubleEndedIterator
                + core::iter::ExactSizeIterator
            {
                self.vec.into_iter().enumerate().map(|(idx, elm)| (
                    $t { val: idx }, elm
                ))
            }
            /// Ref-mut-iterator over the elements.
            #[inline]
            pub fn iter_mut(&mut self) -> core::slice::IterMut<T> {
                self.vec.iter_mut()
            }

            /// Shrinks the capacity as much as possible.
            #[inline]
            pub fn shrink_to_fit(&mut self) {
                self.vec.shrink_to_fit()
            }
            /// Swaps two elements.
            #[inline]
            pub fn swap(&mut self, a: $t, b: $t) {
                self.vec.swap(* a, *b)
            }

            $crate::non_strict! {
                /// Swap remove from `Vec`.
                ///
                /// This function is unsafe for the logics of safe indices. This function voids indices
                /// previously created (indices for the last element on entry) and should be used with
                /// great care.
                #[inline]
                pub fn swap_remove(&mut self, idx: $t) -> T {
                    self.vec.swap_remove(* idx)
                }
            }

            /// Splits the map into the elements before and after some index.
            ///
            /// More precisely, returns a tuple of
            ///
            /// - an iterator over the elements *before* `idx`,
            /// - the element at position `idx`, and
            /// - an iterator over the elements *after* `idx`.
            #[inline]
            pub fn split(&self, idx: $t) -> (
                impl core::iter::Iterator<Item = ($t, &T)>,
                &T,
                impl core::iter::Iterator<Item = ($t, &T)>,
            ) {
                let before = self.vec[0..idx.val].iter().enumerate().map(
                    |(i, elm)| ($t { val: i }, elm)
                );
                let after = if idx.val < self.vec.len() {
                    self.vec[idx.val + 1 ..].iter()
                } else {
                    self.vec[0..0].iter()
                }.enumerate().map(
                    move |(i, elm)| ($t { val: 1 + i + idx.val  }, elm)
                );
                (before, &self.vec[idx.val], after)
            }
        }

        impl<T: Clone> $map<T> {
            /// Creates an empty vector with some capacity.
            #[inline]
            pub fn of_elems(elem: T, size: usize) -> Self {
                $map { vec: $crate::alloc::vec![ elem ; size ] }
            }
        }

        impl<T> core::iter::IntoIterator for $map<T> {
            type Item = T ;
            type IntoIter = $crate::alloc::vec::IntoIter<T> ;
            fn into_iter(self) -> $crate::alloc::vec::IntoIter<T> {
                self.vec.into_iter()
            }
        }
        impl<'a, T> core::iter::IntoIterator for &'a $map<T> {
            type Item = &'a T ;
            type IntoIter = core::slice::Iter<'a, T> ;
            fn into_iter(self) -> core::slice::Iter<'a, T> {
                self.iter()
            }
        }
        impl<'a, T> core::iter::IntoIterator for &'a mut $map<T> {
            type Item = &'a mut T ;
            type IntoIter = core::slice::IterMut<'a, T> ;
            fn into_iter(self) -> core::slice::IterMut<'a, T> {
                self.iter_mut()
            }
        }
        impl<T> core::iter::FromIterator<T> for $map<T> {
            fn from_iter<
                I: core::iter::IntoIterator<Item = T>
            >(iter: I) -> Self {
                $map { vec: iter.into_iter().collect() }
            }
        }
        impl<T> core::ops::Index<$t> for $map<T> {
            type Output = T ;
            fn index(& self, index: $t) -> & T {
                & self.vec[ index.get() ]
            }
        }
        impl<T> core::ops::Index<core::ops::RangeFrom<$t>> for $map<T> {
            type Output = [T];
            fn index(& self, core::ops::RangeFrom { start }: core::ops::RangeFrom<$t>) -> &[T] {
                & self.vec[ start.get() .. ]
            }
        }
        impl<T> core::ops::Index<core::ops::Range<$t>> for $map<T> {
            type Output = [T];
            fn index(& self, core::ops::Range { start, end }: core::ops::Range<$t>) -> &[T] {
                & self.vec[ start.get() .. end.get() ]
            }
        }
        impl<T> core::ops::Index<core::ops::RangeInclusive<$t>> for $map<T> {
            type Output = [T];
            fn index(& self, range: core::ops::RangeInclusive<$t>) -> &[T] {
                & self.vec[ range.start().get() ..= range.end().get() ]
            }
        }
        impl<T> core::ops::Index<core::ops::RangeFull> for $map<T> {
            type Output = [T];
            fn index(& self, _: core::ops::RangeFull) -> &[T] {
                & self.vec[..]
            }
        }
        impl<T> core::ops::Index<core::ops::RangeTo<$t>> for $map<T> {
            type Output = [T];
            fn index(& self, core::ops::RangeTo { end }: core::ops::RangeTo<$t>) -> &[T] {
                & self.vec[..end.get()]
            }
        }
        impl<T> core::ops::Index<core::ops::RangeToInclusive<$t>> for $map<T> {
            type Output = [T];
            fn index(
                & self,
                core::ops::RangeToInclusive { end }: core::ops::RangeToInclusive<$t>
            ) -> &[T] {
                & self.vec[..=end.get()]
            }
        }
        impl<T> core::ops::IndexMut<$t> for $map<T> {
            fn index_mut(&mut self, index: $t) -> &mut T {
                &mut self.vec[ index.get() ]
            }
        }

        $crate::non_strict! {
            impl<T> core::ops::Index<
                core::ops::Range<usize>
            > for $map<T> {
                type Output = [T] ;
                fn index(& self, index: core::ops::Range<usize>) -> & [T] {
                    self.vec.index(index)
                }
            }
            impl<T> core::ops::Index<
                core::ops::RangeInclusive<usize>
            > for $map<T> {
                type Output = [T] ;
                fn index(& self, index: core::ops::RangeInclusive<usize>) -> & [T] {
                self.vec.index(index)
                }
            }
            impl<T> core::ops::Index<
                core::ops::RangeFrom<usize>
            > for $map<T> {
                type Output = [T] ;
                fn index(& self, index: core::ops::RangeFrom<usize>) -> & [T] {
                    self.vec.index(index)
                }
            }
            impl<T> core::ops::Index<
                core::ops::RangeTo<usize>
            > for $map<T> {
                type Output = [T] ;
                fn index(& self, index: core::ops::RangeTo<usize>) -> & [T] {
                    self.vec.index(index)
                }
            }
            impl<T> core::ops::Index<
                core::ops::RangeToInclusive<usize>
            > for $map<T> {
                type Output = [T] ;
                fn index(& self, index: core::ops::RangeToInclusive<usize>) -> & [T] {
                    self.vec.index(index)
                }
            }
            impl<T> core::ops::Deref for $map<T> {
                type Target = $crate::alloc::vec::Vec<T> ;
                fn deref(& self) -> & $crate::alloc::vec::Vec<T> {
                    & self.vec
                }
            }
        }

        $crate::handle!{ $t $($tail)* }
    };
}