o3 0.3.0

shared-nothing primitives
Documentation
use o3::collections::{CellSlab, Slab, SlabKeyParts};

#[test]
fn generational_reuse_and_capacity() {
    let mut slab: Slab<&str> = Slab::with_capacity(3);
    let first = slab.insert("a").unwrap();
    let recycled = slab.insert("b").unwrap();
    let last = slab.insert("c").unwrap();
    assert!(slab.is_full());
    assert!(slab.insert("overflow").is_err());

    assert_eq!(slab.remove(recycled), Some("b"));
    let replacement = slab.insert("B").unwrap();
    assert_eq!(replacement.index(), recycled.index());
    assert_ne!(replacement.generation(), recycled.generation());
    assert_eq!(slab.get(recycled), None);
    assert_eq!(slab.remove(recycled), None);
    assert_eq!(slab.get(replacement), Some(&"B"));

    *slab.get_mut(last).unwrap() = "C";
    assert_eq!(slab.get(first), Some(&"a"));
    assert_eq!(slab.get(last), Some(&"C"));
}

#[test]
fn entry_and_explicit_index_paths_preserve_the_free_list() {
    let mut slab = Slab::<u32>::with_capacity(200);
    let entry = slab.vacant_entry().unwrap();
    let first = entry.insert(1);
    let (second, value) = slab.insert_entry(2).unwrap();
    *value = 3;
    assert_eq!(slab.get(first), Some(&1));
    assert_eq!(slab.get(second), Some(&3));

    let high = slab.insert_at_with(130, |key| key.index()).unwrap();
    let middle = slab.insert_at_with(70, |key| key.index()).unwrap();
    assert!(slab.insert_at_with(70, |_| 0).is_none());
    let next = slab.insert(4).unwrap();
    assert_eq!(next.index(), 2);

    let (value, indexed) = slab.get_index(130).unwrap();
    assert_eq!((*value, indexed), (130, high));
    let (value, indexed) = slab.get_index_mut(70).unwrap();
    *value += 1;
    assert_eq!(indexed, middle);
    assert_eq!(slab.get(middle), Some(&71));

    assert_eq!(slab.remove(high), Some(130));
    let replacement = slab.insert_at_with(130, |_| 7).unwrap();
    assert_ne!(high, replacement);
    assert_eq!(slab.get(replacement), Some(&7));
}

#[test]
fn sparse_iteration_clear_and_index_removal_follow_live_entries() {
    let mut slab: Slab<u32> = Slab::with_capacity(128);
    assert_eq!(slab.key(127), None);
    let high = slab.insert_at_with(127, |_| 7).unwrap();
    let low = slab.insert_at_with(1, |_| 3).unwrap();
    assert_eq!(slab.values().copied().collect::<Vec<_>>(), [7, 3]);
    assert_eq!(slab.remove(high), Some(7));
    assert_eq!(slab.values().copied().collect::<Vec<_>>(), [3]);

    let (value, generation) = slab
        .remove_index_with(low.index(), |value, key| {
            *value += 1;
            Some(key.generation())
        })
        .unwrap();
    assert_eq!(value, 4);
    assert_eq!(generation, low.generation());
    assert_eq!(slab.remove_index(low.index()), None);

    let live = slab.insert(9).unwrap();
    slab.clear();
    assert!(slab.is_empty());
    assert_eq!(slab.key(live.index()), None);
}

#[test]
fn growth_preserves_live_retired_and_dense_entries() {
    let mut slab = Slab::<u8, (), 1>::with_capacity(2);
    let retired = slab.insert(1).unwrap();
    let live = slab.insert(2).unwrap();
    assert_eq!(slab.remove(retired), Some(1));
    slab.grow_to(4);
    assert_eq!(slab.capacity(), 4);
    assert_eq!(slab.get(live), Some(&2));
    assert_eq!(slab.get(retired), None);
    let first = slab.insert(3).unwrap();
    let second = slab.insert(4).unwrap();
    assert_ne!(first.index(), retired.index());
    assert_ne!(second.index(), retired.index());
    assert!(slab.insert(5).is_err());

    let mut slab: CellSlab<i32> = CellSlab::with_capacity(1);
    let first = slab.insert(7).unwrap();
    slab.grow_to(3);
    let second = slab.insert(8).unwrap();
    let third = slab.insert(9).unwrap();
    assert_eq!(slab.update(first, |value| *value), Some(7));
    assert_eq!(slab.update(second, |value| *value), Some(8));
    assert_eq!(slab.update(third, |value| *value), Some(9));
    assert_eq!(slab.keys().count(), 3);
}

#[test]
fn external_parts_resolve_only_the_current_generation() {
    const MAX: u32 = 7;
    struct Tag;

    assert!(SlabKeyParts::<MAX>::new(0, 0).is_none());
    assert!(SlabKeyParts::<MAX>::new(0, MAX + 1).is_none());
    assert!(SlabKeyParts::<MAX>::new(u32::MAX, MAX).is_some());

    let mut slab = Slab::<u32, Tag, MAX>::with_capacity(1);
    let key = slab.insert(7).unwrap();
    let parts = SlabKeyParts::<MAX>::new(key.index(), key.generation().get()).unwrap();
    assert_eq!(slab.get_parts(parts), Some(&7));
    assert_eq!(slab.resolve(parts), Some(key));
    assert_eq!(slab.remove_parts(parts), Some(7));
    assert_eq!(slab.get_parts(parts), None);

    let slab = CellSlab::<u32, Tag, MAX>::with_capacity(1);
    let stale = slab.insert(7).unwrap().parts();
    assert_eq!(slab.remove_parts(stale), Some(7));
    let current = slab.insert(11).unwrap().parts();
    assert_eq!(slab.update_parts(stale, |value| *value += 1), None);
    assert_eq!(slab.update_parts(current, |value| *value += 1), Some(()));
    assert_eq!(slab.remove_parts(current), Some(12));
}