fast-cache 0.1.0

Embedded-first thread-per-core in-memory cache with optional Redis-compatible server
Documentation
use super::*;

impl SmallListDeque {
    pub(super) fn new() -> Self {
        Self {
            entries: std::array::from_fn(|_| None),
            head: 0,
            len: 0,
        }
    }

    pub(super) fn from_vec(values: Vec<Bytes>) -> Self {
        debug_assert!(values.len() <= SMALL_LIST_INLINE);
        let mut list = Self::new();
        for value in values {
            list.push_back(value)
                .expect("small list capacity checked before construction");
        }
        list
    }

    #[inline(always)]
    pub(super) fn len(&self) -> usize {
        self.len
    }

    #[inline(always)]
    pub(super) fn is_full(&self) -> bool {
        self.len == SMALL_LIST_INLINE
    }

    #[inline(always)]
    pub(super) fn physical_index(&self, logical_index: usize) -> usize {
        (self.head + logical_index) % SMALL_LIST_INLINE
    }

    #[inline(always)]
    pub(super) fn get(&self, index: usize) -> Option<&Bytes> {
        (index < self.len)
            .then(|| self.physical_index(index))
            .and_then(|index| self.entries[index].as_ref())
    }

    #[inline(always)]
    pub(super) fn set(&mut self, index: usize, value: Bytes) {
        let physical_index = self.physical_index(index);
        self.entries[physical_index] = Some(value);
    }

    #[inline(always)]
    pub(super) fn push_front(&mut self, value: Bytes) -> Result<(), Bytes> {
        if self.is_full() {
            return Err(value);
        }
        self.head = if self.len == 0 {
            0
        } else {
            (self.head + SMALL_LIST_INLINE - 1) % SMALL_LIST_INLINE
        };
        self.entries[self.head] = Some(value);
        self.len += 1;
        Ok(())
    }

    #[inline(always)]
    pub(super) fn push_back(&mut self, value: Bytes) -> Result<(), Bytes> {
        if self.is_full() {
            return Err(value);
        }
        let index = self.physical_index(self.len);
        self.entries[index] = Some(value);
        self.len += 1;
        Ok(())
    }

    #[inline(always)]
    pub(super) fn pop_front(&mut self) -> Option<Bytes> {
        if self.len == 0 {
            return None;
        }
        let value = self.entries[self.head].take();
        self.head = (self.head + 1) % SMALL_LIST_INLINE;
        self.len -= 1;
        if self.len == 0 {
            self.head = 0;
        }
        value
    }

    #[inline(always)]
    pub(super) fn pop_back(&mut self) -> Option<Bytes> {
        if self.len == 0 {
            return None;
        }
        let index = self.physical_index(self.len - 1);
        let value = self.entries[index].take();
        self.len -= 1;
        if self.len == 0 {
            self.head = 0;
        }
        value
    }

    pub(super) fn insert(&mut self, index: usize, value: Bytes) -> Result<(), Bytes> {
        if self.is_full() {
            return Err(value);
        }
        let mut values = self.take_all();
        values.insert(index, value);
        *self = Self::from_vec(values);
        Ok(())
    }

    pub(super) fn remove(&mut self, index: usize) -> Option<Bytes> {
        if index >= self.len {
            return None;
        }
        let mut values = self.take_all();
        let value = values.remove(index);
        *self = Self::from_vec(values);
        Some(value)
    }

    pub(super) fn take_all(&mut self) -> Vec<Bytes> {
        let len = self.len;
        let mut values = Vec::with_capacity(len);
        for index in 0..len {
            let physical_index = self.physical_index(index);
            values.push(
                self.entries[physical_index]
                    .take()
                    .expect("small list slot missing value"),
            );
        }
        self.head = 0;
        self.len = 0;
        values
    }

    pub(super) fn into_segmented(mut self, additional: usize) -> SegmentedList {
        let mut list = SegmentedList::with_capacity(self.len + additional);
        for value in self.take_all() {
            list.push_back(value);
        }
        list
    }

    pub(super) fn iter(&self) -> SmallListIter<'_> {
        SmallListIter {
            list: self,
            index: 0,
        }
    }
}

impl<'a> Iterator for SmallListIter<'a> {
    type Item = &'a Bytes;

    fn next(&mut self) -> Option<Self::Item> {
        let value = self.list.get(self.index)?;
        self.index += 1;
        Some(value)
    }
}

pub(super) fn push_values_small(list: &mut SmallListDeque, values: &[&[u8]], front: bool) {
    if front {
        for value in values {
            list.push_front(value.to_vec())
                .expect("small list capacity checked before push");
        }
    } else {
        for value in values {
            list.push_back(value.to_vec())
                .expect("small list capacity checked before push");
        }
    }
}