o3 0.16.2

shared-nothing primitives
Documentation
use std::{cell::Cell, mem};

use o3::collections::batch;

#[test]
fn fill_requires_an_empty_batch() {
    let mut values = batch::inline::Inline::<u32, 2>::new();
    let mut fill = values.fill().expect("a new batch is empty");
    fill.vacant_entry().unwrap().insert(1);
    fill.vacant_entry().unwrap().insert(2);
    assert!(fill.vacant_entry().is_none());
    drop(fill);

    assert!(values.fill().is_none());
    assert_eq!(values.pop_front(), Some(1));
    assert!(values.fill().is_none());
    assert_eq!(values.pop_front(), Some(2));

    let mut fill = values.fill().expect("a drained batch can be refilled");
    fill.vacant_entry().unwrap().insert(3);
    assert_eq!(values.pop_front(), Some(3));
}

#[test]
fn reserved_pop_can_restore_the_original_front() {
    let mut values = batch::inline::Inline::<u32, 2>::new();
    let mut fill = values.fill().unwrap();
    fill.vacant_entry().unwrap().insert(1);
    fill.vacant_entry().unwrap().insert(2);
    drop(fill);

    let (value, vacant) = values.pop_front_reserved().unwrap();
    vacant.restore(value);
    assert_eq!(values.pop_front(), Some(1));
    assert_eq!(values.pop_front(), Some(2));
}

#[test]
fn dropping_a_reserved_vacancy_commits_the_pop() {
    let mut values = batch::inline::Inline::<u32, 2>::new();
    let mut fill = values.fill().unwrap();
    fill.vacant_entry().unwrap().insert(1);
    fill.vacant_entry().unwrap().insert(2);
    drop(fill);

    let (value, vacant) = values.pop_front_reserved().unwrap();
    assert_eq!(value, 1);
    std::hint::black_box(vacant);
    assert_eq!(values.pop_front(), Some(2));
}

#[test]
fn live_values_drop_exactly_once() {
    struct Count<'a>(&'a Cell<usize>);

    impl Drop for Count<'_> {
        fn drop(&mut self) {
            self.0.set(self.0.get() + 1);
        }
    }

    let drops = Cell::new(0);
    let mut values = batch::inline::Inline::<Count<'_>, 3>::new();
    let mut fill = values.fill().unwrap();
    fill.vacant_entry().unwrap().insert(Count(&drops));
    fill.vacant_entry().unwrap().insert(Count(&drops));
    fill.vacant_entry().unwrap().insert(Count(&drops));
    drop(fill);

    drop(values.pop_front());
    drop(values);
    assert_eq!(drops.get(), 3);
}

#[test]
fn inline_layout_is_payload_plus_two_indices() {
    assert_eq!(
        mem::size_of::<batch::inline::Inline<u64, 3>>(),
        3 * mem::size_of::<u64>() + 2 * mem::size_of::<usize>()
    );
    assert_eq!(
        mem::size_of::<batch::inline::Fill<'static, u64, 3>>(),
        mem::size_of::<usize>()
    );
    assert_eq!(
        mem::size_of::<batch::inline::Vacant<'static, u64, 3>>(),
        mem::size_of::<usize>()
    );
    assert_eq!(
        mem::size_of::<batch::inline::FrontVacant<'static, u64, 3>>(),
        mem::size_of::<usize>()
    );
}