bumpish 0.4.1

A set of collections using bump allocations
Documentation
use super::*;
use pretty_assertions::assert_eq;

#[test]
fn bump_with_capacity() {
    unsafe {
        let bump = RawBump::<i32, 0>::with_capacity(0);
        assert_eq!(bump.capacity(), 0);

        let mut bump = RawBump::<i32, 0>::with_capacity(3);
        assert!(bump.capacity() >= 3);
        let inlined_chunk = bump.inlined.get_mut().get();
        let next_chunk = inlined_chunk.next();
        assert_eq!(0, inlined_chunk.capacity());
        assert!(next_chunk.capacity() >= 3 * i32::SIZE);
        assert_eq!(bump.capacity() * i32::SIZE, next_chunk.capacity());

        assert!(!inlined_chunk.prev().is_dead());
        assert!(!inlined_chunk.next().is_dead());

        assert!(next_chunk.prev().is_dead());
        assert!(next_chunk.next().is_dead());

        let mut bump = RawBump::<i32, 5>::with_capacity(5);
        assert_eq!(bump.capacity(), 5);
        let chunk = bump.inlined.get_mut().get();
        assert_eq!(chunk.capacity(), 5 * i32::SIZE);
    }
}

#[test]
fn bump_push_pop_zst() {
    let mut bump = RawBump::<(), 0>::new();
    unsafe {
        bump.push_ptr(());
        assert!(bump.inlined.get_mut().current_chunk().is_dead());
        assert!(bump.inlined.get_mut().next_chunk().is_dead());
        assert_eq!(bump.pop(), Some(()));

        bump.pop();
        assert!(bump.inlined.get_mut().current_chunk().is_dead());
        assert!(bump.inlined.get_mut().next_chunk().is_dead());
    }
    assert_eq!(bump.pop(), None);
}

#[test]
fn bump_push_pop_0() {
    let mut bump = RawBump::<usize, 0>::new();
    let cap_0 = bump.capacity();
    assert_eq!(bump.capacity(), 0);
    assert_eq!(bump.pop(), None);
    unsafe {
        assert!(bump.inlined.get_mut().current_chunk().is_dead());
        assert!(bump.inlined.get_mut().next_chunk().is_dead());
    }

    bump.push_ptr(cap_0);
    let cap_01 = bump.capacity();
    let cap_1 = cap_01 - cap_0;
    assert_eq!(bump.capacity(), cap_01);
    assert_eq!(bump.pop(), Some(cap_0));
    assert!(bump.capacity() > cap_0);
    unsafe {
        let current_chunk = bump.inlined.get_mut().current_chunk();
        let first_chunk = bump.inlined.get_mut().next_chunk();
        assert!(!current_chunk.is_dead());
        assert!(!first_chunk.is_dead());
        assert!(current_chunk.is(first_chunk));
        assert!(current_chunk.next().is_dead());
        assert!(current_chunk.prev().is_dead());
        assert!(first_chunk.next().is_dead());
        assert!(first_chunk.prev().is_dead());
    }

    for i in cap_0..cap_01 {
        bump.push_ptr(i);
    }

    bump.push_ptr(cap_01);
    assert!(bump.capacity() > cap_01);
    assert_eq!(bump.pop(), Some(cap_01));
    assert!(bump.capacity() > cap_01);
    unsafe {
        let current_chunk = bump.inlined.get_mut().current_chunk();
        let first_chunk = bump.inlined.get_mut().next_chunk();
        assert!(!current_chunk.is_dead());
        assert!(!first_chunk.is_dead());
        assert!(!current_chunk.is(first_chunk));
        assert!(current_chunk.next().is_dead());
        assert!(!current_chunk.prev().is_dead());
        assert!(!first_chunk.next().is_dead());
        assert!(first_chunk.prev().is_dead());
    }

    assert_eq!(bump.pop(), Some(cap_01 - 1));
    assert!(bump.capacity() > cap_01);
    unsafe {
        let current_chunk = bump.inlined.get_mut().current_chunk();
        let first_chunk = bump.inlined.get_mut().next_chunk();
        assert!(!current_chunk.is_dead());
        assert!(!first_chunk.is_dead());
        assert!(current_chunk.is(first_chunk));
        assert!(!current_chunk.next().is_dead());
        assert!(current_chunk.prev().is_dead());
        assert!(!first_chunk.next().is_dead());
        assert!(first_chunk.prev().is_dead());
    }
    bump.push_ptr(cap_01 - 1);

    let cap_012 = bump.capacity();
    let cap_02 = cap_012 - cap_1;
    for i in cap_01..cap_012 {
        bump.push_ptr(i);
    }
    for i in (cap_01..cap_012).rev() {
        assert_eq!(bump.pop(), Some(i));
    }
    unsafe {
        let current_chunk = bump.inlined.get_mut().current_chunk();
        let first_chunk = bump.inlined.get_mut().next_chunk();
        assert!(!current_chunk.is_dead());
        assert!(!first_chunk.is_dead());
        assert!(!current_chunk.is(first_chunk));
        assert!(current_chunk.next().is_dead());
        assert!(!current_chunk.prev().is_dead());
        assert!(!first_chunk.next().is_dead());
        assert!(first_chunk.prev().is_dead());
    }

    assert_eq!(bump.pop(), Some(cap_01 - 1));
    unsafe {
        let current_chunk = bump.inlined.get_mut().current_chunk();
        let first_chunk = bump.inlined.get_mut().next_chunk();
        assert!(!current_chunk.is_dead());
        assert!(!first_chunk.is_dead());
        assert!(current_chunk.is(first_chunk));
        assert!(!current_chunk.next().is_dead());
        assert!(current_chunk.prev().is_dead());
        assert!(!first_chunk.next().is_dead());
        assert!(first_chunk.prev().is_dead());
    }

    for i in (cap_0..cap_01 - 1).rev() {
        assert_eq!(bump.pop(), Some(i));
    }
    assert_eq!(bump.capacity(), cap_012);
    unsafe {
        let current_chunk = bump.inlined.get_mut().current_chunk();
        let first_chunk = bump.inlined.get_mut().next_chunk();
        assert!(!current_chunk.is_dead());
        assert!(!first_chunk.is_dead());
        assert!(current_chunk.is(first_chunk));
        assert!(!current_chunk.next().is_dead());
        assert!(current_chunk.prev().is_dead());
        assert!(!first_chunk.next().is_dead());
        assert!(first_chunk.prev().is_dead());
    }

    assert_eq!(bump.pop(), None);
    assert_eq!(bump.capacity(), cap_02);
}

#[test]
fn bump_push_pop_n() {
    let mut bump = RawBump::<usize, 5>::new();
    assert_eq!(bump.capacity(), 5);
    assert_eq!(bump.pop(), None);

    let cap_0 = bump.capacity();
    for i in 0..cap_0 {
        bump.push_ptr(i);
    }

    assert_eq!(bump.capacity(), cap_0);
    unsafe {
        assert!(bump.inlined.get_mut().current_chunk().is_dead());
        assert!(bump.inlined.get_mut().next_chunk().is_dead());
    }

    bump.push_ptr(cap_0);
    let cap_01 = bump.capacity();
    let cap_1 = cap_01 - cap_0;
    assert_eq!(bump.capacity(), cap_01);
    assert_eq!(bump.pop(), Some(cap_0));
    assert!(bump.capacity() > cap_0);
    unsafe {
        let current_chunk = bump.inlined.get_mut().current_chunk();
        let first_chunk = bump.inlined.get_mut().next_chunk();
        assert!(!current_chunk.is_dead());
        assert!(!first_chunk.is_dead());
        assert!(current_chunk.is(first_chunk));
        assert!(current_chunk.next().is_dead());
        assert!(current_chunk.prev().is_dead());
        assert!(first_chunk.next().is_dead());
        assert!(first_chunk.prev().is_dead());
    }

    for i in cap_0..cap_01 {
        bump.push_ptr(i);
    }

    bump.push_ptr(cap_01);
    assert!(bump.capacity() > cap_01);
    assert_eq!(bump.pop(), Some(cap_01));
    assert!(bump.capacity() > cap_01);
    unsafe {
        let current_chunk = bump.inlined.get_mut().current_chunk();
        let first_chunk = bump.inlined.get_mut().next_chunk();
        assert!(!current_chunk.is_dead());
        assert!(!first_chunk.is_dead());
        assert!(!current_chunk.is(first_chunk));
        assert!(current_chunk.next().is_dead());
        assert!(!current_chunk.prev().is_dead());
        assert!(!first_chunk.next().is_dead());
        assert!(first_chunk.prev().is_dead());
    }

    assert_eq!(bump.pop(), Some(cap_01 - 1));
    assert!(bump.capacity() > cap_01);
    unsafe {
        let current_chunk = bump.inlined.get_mut().current_chunk();
        let first_chunk = bump.inlined.get_mut().next_chunk();
        assert!(!current_chunk.is_dead());
        assert!(!first_chunk.is_dead());
        assert!(current_chunk.is(first_chunk));
        assert!(!current_chunk.next().is_dead());
        assert!(current_chunk.prev().is_dead());
        assert!(!first_chunk.next().is_dead());
        assert!(first_chunk.prev().is_dead());
    }
    bump.push_ptr(cap_01 - 1);

    let cap_012 = bump.capacity();
    let cap_02 = cap_012 - cap_1;
    for i in cap_01..cap_012 {
        bump.push_ptr(i);
    }
    for i in (cap_01..cap_012).rev() {
        assert_eq!(bump.pop(), Some(i));
    }
    unsafe {
        let current_chunk = bump.inlined.get_mut().current_chunk();
        let first_chunk = bump.inlined.get_mut().next_chunk();
        assert!(!current_chunk.is_dead());
        assert!(!first_chunk.is_dead());
        assert!(!current_chunk.is(first_chunk));
        assert!(current_chunk.next().is_dead());
        assert!(!current_chunk.prev().is_dead());
        assert!(!first_chunk.next().is_dead());
        assert!(first_chunk.prev().is_dead());
    }

    assert_eq!(bump.pop(), Some(cap_01 - 1));
    unsafe {
        let current_chunk = bump.inlined.get_mut().current_chunk();
        let first_chunk = bump.inlined.get_mut().next_chunk();
        assert!(!current_chunk.is_dead());
        assert!(!first_chunk.is_dead());
        assert!(current_chunk.is(first_chunk));
        assert!(!current_chunk.next().is_dead());
        assert!(current_chunk.prev().is_dead());
        assert!(!first_chunk.next().is_dead());
        assert!(first_chunk.prev().is_dead());
    }

    for i in (cap_0..cap_01 - 1).rev() {
        assert_eq!(bump.pop(), Some(i));
    }
    assert_eq!(bump.capacity(), cap_012);
    unsafe {
        let current_chunk = bump.inlined.get_mut().current_chunk();
        let first_chunk = bump.inlined.get_mut().next_chunk();
        assert!(!current_chunk.is_dead());
        assert!(!first_chunk.is_dead());
        assert!(current_chunk.is(first_chunk));
        assert!(!current_chunk.next().is_dead());
        assert!(current_chunk.prev().is_dead());
        assert!(!first_chunk.next().is_dead());
        assert!(first_chunk.prev().is_dead());
    }

    assert_eq!(bump.pop(), Some(cap_0 - 1));
    assert_eq!(bump.capacity(), cap_02);

    for i in (0..cap_0 - 1).rev() {
        assert_eq!(bump.pop(), Some(i));
    }
    assert_eq!(bump.pop(), None);
    assert_eq!(bump.capacity(), cap_02);
}

#[test]
fn bump_index() {
    let bump = RawBump::<_, 0>::new();
    bump.push_ptr(1);
    bump.push_ptr(2);
    bump.push_ptr(3);
    bump.push_ptr(4);
    bump.push_ptr(5);
    unsafe {
        assert_eq!(bump.index_unchecked(0).read(), 1);
        assert_eq!(bump.index_unchecked(1).read(), 2);
        assert_eq!(bump.index_unchecked(2).read(), 3);
        assert_eq!(bump.index_unchecked(3).read(), 4);
        assert_eq!(bump.index_unchecked(4).read(), 5);
    }

    let bump = RawBump::<_, 2>::new();

    bump.push_ptr(1);
    bump.push_ptr(2);
    bump.push_ptr(3);
    bump.push_ptr(4);
    bump.push_ptr(5);
    unsafe {
        assert_eq!(bump.index_unchecked(0).read(), 1);
        assert_eq!(bump.index_unchecked(1).read(), 2);
        assert_eq!(bump.index_unchecked(2).read(), 3);
        assert_eq!(bump.index_unchecked(3).read(), 4);
        assert_eq!(bump.index_unchecked(4).read(), 5);
    }

    let bump = RawBump::<_, 0>::new();
    bump.push_ptr(());
    bump.push_ptr(());
    bump.push_ptr(());
    bump.push_ptr(());
    bump.push_ptr(());
    unsafe {
        assert_eq!(bump.index_unchecked(0).read(), ());
        assert_eq!(bump.index_unchecked(1).read(), ());
        assert_eq!(bump.index_unchecked(2).read(), ());
        assert_eq!(bump.index_unchecked(3).read(), ());
        assert_eq!(bump.index_unchecked(4).read(), ());
    }
}