//! Stack-allocated ring buffer backing the sliding sub-word windows.

/// Fixed-capacity ring buffer backed by a stack array.
/// N must be a power of two; operations are branchless via `% N`.
pub(crate) struct Ring<T: Copy + Default, const N: usize> {
    buf: [T; N],
    head: usize,
    len: usize,
}

impl<T: Copy + Default, const N: usize> Ring<T, N> {
    #[inline]
    pub(crate) fn new() -> Self {
        Self {
            buf: [T::default(); N],
            head: 0,
            len: 0,
        }
    }

    #[inline]
    pub(crate) fn clear(&mut self) {
        self.len = 0;
        self.head = 0;
    }

    #[inline]
    pub(crate) fn push_back(&mut self, val: T) {
        self.buf[(self.head + self.len) % N] = val;
        self.len += 1;
    }

    #[inline]
    pub(crate) fn pop_front(&mut self) -> T {
        let val = self.buf[self.head];
        self.head = (self.head + 1) % N;
        self.len -= 1;
        val
    }
}
