bumpish 0.4.0

A set of collections using bump allocations
Documentation
//! Some helper functions for bump-stack.

use core::mem;
use core::ptr::NonNull;

macro_rules! impl_iter {
    ($map_fn:expr, $iter_name:ident < $( $life:lifetime, )? $( $arg_ty:ident,)* { $( const $n_ty:ident : usize )? }> => $item_ty:ty ) => {
        impl<$($life,)? $($arg_ty),* $(, const $n_ty: usize )?> core::iter::Iterator for $iter_name<$($life,)? $($arg_ty),* $(, $n_ty)?> {
            type Item = $item_ty;

            #[inline]
            fn next(&mut self) -> Option<Self::Item> {
                self.raw_iter.next().map($map_fn)
            }

            #[inline]
            fn size_hint(&self) -> (usize, Option<usize>) {
                self.raw_iter.size_hint()
            }

            #[inline]
            fn count(self) -> usize {
                self.raw_iter.count()
            }

            #[inline]
            fn nth(&mut self, n: usize) -> Option<Self::Item> {
                self.raw_iter.nth(n).map($map_fn)
            }

            #[inline]
            fn last(self) -> Option<Self::Item>
            where
                Self: Sized,
            {
                self.raw_iter.last().map($map_fn)
            }
        }
    };
}

pub(crate) use impl_iter;

macro_rules! impl_deiter {
    ($map_fn:expr, $iter_name:ident < $( $life:lifetime, )? $( $arg_ty:ident,)* { $( const $n_ty:ident : usize )? }> ) => {
        impl<$($life,)? $($arg_ty),* $(, const $n_ty: usize)?> core::iter::DoubleEndedIterator for $iter_name<$($life,)? $($arg_ty),* $(, $n_ty)?> {
            #[inline]
            fn next_back(&mut self) -> Option<Self::Item> {
                self.raw_iter.next_back().map($map_fn)
            }

            #[inline]
            fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
                self.raw_iter.nth_back(n).map($map_fn)
            }
        }
    };
}

pub(crate) use impl_deiter;

/// Typical overhead per allocation imposed by allocators.
pub(crate) const ALLOC_OVERHEAD: usize = 16;

/// Just helpling trait for getting properties of a type.
pub(crate) trait TypeProps<T> {
    const SIZE: usize = mem::size_of::<T>();
    const ALIGN: usize = mem::align_of::<T>();
    const IS_ZST: bool = Self::SIZE == 0;
}

impl<T> TypeProps<T> for T {}

/// Replacement for standard `max` method until its constancy is stabilized.
pub(crate) const fn max(a: usize, b: usize) -> usize {
    if a > b { a } else { b }
}

/// Checks if `value` is aligned to `alignment`.
pub(crate) fn ptr_is_aligned_to<T>(ptr: *mut T, alignment: usize) -> bool {
    let value = ptr as usize;
    value.is_multiple_of(alignment)
}

/// Returns a properly aligned pointer to a ZST instance.
pub(crate) const fn zst_ptr<T>() -> NonNull<T> {
    assert!(T::IS_ZST);
    let non_zero = core::num::NonZero::new(T::ALIGN).unwrap();
    NonNull::without_provenance(non_zero)
}

#[cfg(test)]
mod utest {
    use super::*;
    use pretty_assertions::assert_eq;

    #[test]
    fn max_min() {
        assert_eq!(max(1, 2), 2);
        assert_eq!(max(2, 1), 2);
    }
}