limited-table 0.1.0

A preallocated table with the limited size
Documentation
extern crate slab;

use slab::Slab;

pub type Key = usize;

pub struct LimitedTable<Item> {
    slab: Slab<Item>,
    begin: Key,
    limit: usize,
}

impl<Item> LimitedTable<Item> {
    pub fn new(begin: Key, limit: usize) -> Self {
        Self {
            slab: Slab::with_capacity(limit),
            begin,
            limit,
        }
    }

    pub fn limit(&self) -> usize {
        self.limit
    }

    pub fn len(&self) -> usize {
        self.slab.len()
    }

    pub fn is_empty(&self) -> bool {
        self.len() == 0
    }

    pub fn capacity(&self) -> usize {
        let capacity = self.slab.capacity();
        debug_assert_eq!(self.limit(), capacity);
        capacity
    }

    pub fn is_full(&self) -> bool {
        self.limit() == self.len()
    }

    pub fn insert(&mut self, item: Item) -> Option<Key> {
        if self.is_full() {
            return None;
        }
        Some(self.begin + self.slab.insert(item))
    }

    pub fn remove(&mut self, key: Key) -> Option<Item> {
        if key < self.begin {
            return None;
        }
        let key = key - self.begin;
        if !self.slab.contains(key) {
            return None;
        }
        Some(self.slab.remove(key))
    }

    pub fn contains(&self, key: Key) -> bool {
        self.slab.contains(key - self.begin)
    }

    pub fn get(&self, key: Key) -> Option<&Item> {
        self.slab.get(key - self.begin)
    }

    pub fn clear(&mut self) {
        self.slab.clear()
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    struct TestItem;

    #[test]
    fn limit() {
        let begin = 11;
        let limit = 54;
        let table: LimitedTable<TestItem> = LimitedTable::new(begin, limit);
        assert_eq!(limit, table.limit());
    }

    #[test]
    fn empty_table_len_is_zero() {
        let begin = 11;
        let limit = 54;
        let table: LimitedTable<TestItem> = LimitedTable::new(begin, limit);
        assert_eq!(0, table.len());
    }

    #[test]
    fn len_of_inserted_table() {
        let begin: Key = 11;
        let limit: usize = 54;
        let mut table: LimitedTable<TestItem> = LimitedTable::new(begin, limit);
        assert_eq!(0, table.len());
        let t1 = table.insert(TestItem);
        assert!(t1.is_some());
        assert_eq!(1, table.len());
        let t2 = table.insert(TestItem);
        assert!(t2.is_some());
        assert_eq!(2, table.len());
        let t3 = table.insert(TestItem);
        assert!(t3.is_some());
        assert_eq!(3, table.len());
        let t4 = table.insert(TestItem);
        assert!(t4.is_some());
        assert_eq!(4, table.len());
    }

    #[test]
    fn get_returns_none_when_the_item_is_removed() {
        let begin: Key = 11;
        let limit: usize = 54;
        let mut table: LimitedTable<TestItem> = LimitedTable::new(begin, limit);
        let t1 = table.insert(TestItem);
        assert!(t1.is_some());
        let t2 = table.insert(TestItem);
        assert!(t2.is_some());
        let t3 = table.insert(TestItem);
        assert!(t3.is_some());
        let t4 = table.insert(TestItem);
        assert!(t4.is_some());
        assert!(table.get(t4.unwrap()).is_some());
        let _ = table.remove(t4.unwrap());
        assert!(table.get(t4.unwrap()).is_none());
    }

    #[test]
    fn insert_returns_none_when_the_table_is_full() {
        let begin: Key = 11;
        let limit: usize = 20;
        let mut table: LimitedTable<TestItem> = LimitedTable::new(begin, limit);
        for _ in begin..(begin + limit) {
            let t = table.insert(TestItem);
            assert!(table.get(t.unwrap()).is_some());
        }
        let t = table.insert(TestItem);
        assert!(t.is_none());
    }

    #[test]
    fn contains_returns_true_when_item_is_inserted() {
        let begin: Key = 11;
        let limit: usize = 54;
        let mut table: LimitedTable<TestItem> = LimitedTable::new(begin, limit);
        let t1 = table.insert(TestItem);
        assert_ne!(None, t1);
        assert!(table.contains(t1.unwrap()));
    }
}