// Licensed under the Apache-2.0 license
// SPDX-License-Identifier: Apache-2.0

#![cfg_attr(not(test), no_std)]

/// A simple single-threaded ring buffer of type `T` with a backing array of size `N`.
///
/// The effective capacity of this queue is `N - 1`.
///
/// If producer == consumer, the queue is empty.
/// If (producer + 1) % N == consumer, the queue is full.
///
/// Invariants:
///     The producer and consumer indicies are maintained to be less than `N`.
pub struct RingBuffer<T: Copy + Default, const N: usize> {
    producer: usize,
    consumer: usize,
    data: [T; N],
}

/// Creates a default empty `RingBuffer`.
///
/// # Panics
///
/// Panics at compile time if `N <= 1`.
impl<T: Copy + Default, const N: usize> Default for RingBuffer<T, N> {
    fn default() -> Self {
        // The queue requires at least 2 slots to store 1 item (N-1 capacity).
        // Using a const block to ensure this is checked at compile time.
        const { assert!(N > 1, "RingBuffer size N must be greater than 1") };
        Self {
            producer: 0,
            consumer: 0,
            data: [T::default(); N],
        }
    }
}

impl<T: Copy + Default, const N: usize> RingBuffer<T, N> {
    /// Pushes an item into the buffer.
    ///
    /// Returns `Ok(())` if the item was successfully added, or `Err(item)` if the buffer is full.
    pub fn push(&mut self, item: T) -> Result<(), T> {
        let next = (self.producer + 1) % N;
        if next != self.consumer {
            // nosemgrep
            unsafe {
                // SAFETY: the producer is always less than N.
                core::hint::assert_unchecked(self.producer < N);
            }
            self.data[self.producer] = item;
            self.producer = next;
            Ok(())
        } else {
            Err(item)
        }
    }

    /// Removes and returns the first item from the buffer.
    ///
    /// Returns `Some(item)` if the buffer is not empty, or `None` if it is.
    pub fn pop(&mut self) -> Option<T> {
        if self.consumer != self.producer {
            // nosemgrep
            unsafe {
                // SAFETY: the consumer is always less than N.
                core::hint::assert_unchecked(self.consumer < N)
            };
            let item = self.data[self.consumer];
            self.consumer = (self.consumer + 1) % N;
            Some(item)
        } else {
            None
        }
    }

    /// Returns the number of items currently in the buffer.
    pub fn len(&self) -> usize {
        (self.producer + N - self.consumer) % N
    }

    /// Returns the number of slots available in the buffer.
    pub fn available(&self) -> usize {
        (self.consumer + N - self.producer - 1) % N
    }

    /// Returns `true` if the buffer is empty.
    pub fn is_empty(&self) -> bool {
        self.producer == self.consumer
    }

    /// Returns `true` if the buffer is full.
    pub fn is_full(&self) -> bool {
        (self.producer + 1) % N == self.consumer
    }

    /// Pushes as many items from the slice into the buffer as possible.
    ///
    /// Returns `Ok(())` if all items were added, or `Err(&[T])` containing the
    /// remaining unbuffered items if the buffer became full.
    pub fn push_slice<'a>(&mut self, s: &'a [T]) -> Result<(), &'a [T]> {
        let free = (self.consumer + N - self.producer - 1) % N;
        let n = core::cmp::min(s.len(), free);

        let mut remaining = n;
        let mut src_idx = 0;

        let chunk1 = core::cmp::min(remaining, N - self.producer);
        if chunk1 > 0 {
            // nosemgrep
            unsafe {
                // SAFETY: the producer is less than N, and chunk1 is calculated
                // to not exceed the remaining space in the buffer.
                core::hint::assert_unchecked(self.producer < N);
                core::hint::assert_unchecked(self.producer + chunk1 <= N);
            }
            self.data[self.producer..self.producer + chunk1]
                .copy_from_slice(&s[src_idx..src_idx + chunk1]);
            self.producer = (self.producer + chunk1) % N;
            remaining -= chunk1;
            src_idx += chunk1;
        }

        if remaining > 0 {
            // nosemgrep
            unsafe {
                // SAFETY: remaining is the wrapped portion, which is less than N.
                // src_idx + remaining is exactly n, which is <= s.len().
                core::hint::assert_unchecked(remaining <= N);
                core::hint::assert_unchecked(src_idx + remaining <= s.len());
            }
            self.data[0..remaining].copy_from_slice(&s[src_idx..src_idx + remaining]);
            self.producer = remaining;
        }

        if n < s.len() {
            Err(&s[n..])
        } else {
            Ok(())
        }
    }

    /// Returns a slice containing the contiguous part of the buffered data.
    ///
    /// If the data wraps around the end of the backing array, this only returns
    /// the first part. Callers should use `consume()` and `as_slice()` again to
    /// retrieve the wrapped portion.
    pub fn as_slice(&self) -> &[T] {
        // nosemgrep
        unsafe {
            // SAFETY: producer and consumer indices are always less than or equal to N.
            core::hint::assert_unchecked(self.consumer <= N);
            core::hint::assert_unchecked(self.producer <= N);
        }
        if self.consumer <= self.producer {
            // The available slice is contiguous in the array.
            &self.data[self.consumer..self.producer]
        } else {
            // Slices can't wrap around the end of the array, so give just the chunk we can give.
            &self.data[self.consumer..]
        }
    }

    /// Advances the consumer pointer by `n` items, effectively removing them from the buffer.
    ///
    /// If `n` is greater than the current length, only the available items are consumed.
    pub fn consume(&mut self, n: usize) {
        let n = core::cmp::min(n, self.len());
        self.consumer = (self.consumer + n) % N;
    }
}

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

    #[test]
    fn test_push_pop() {
        let mut q = RingBuffer::<u8, 4>::default();

        assert_eq!(q.push(b'b'), Ok(()));
        assert_eq!(q.push(b'y'), Ok(()));
        assert_eq!(q.push(b'e'), Ok(()));
        assert_eq!(q.push(b'x'), Err(b'x')); // Overflow
        assert_eq!(q.len(), 3);
        assert_eq!(q.is_empty(), false);
        assert_eq!(q.is_full(), true);

        assert_eq!(q.pop(), Some(b'b'));
        assert_eq!(q.pop(), Some(b'y'));
        assert_eq!(q.pop(), Some(b'e'));
        assert_eq!(q.pop(), None); // No more items.
        assert_eq!(q.len(), 0);
        assert_eq!(q.is_empty(), true);
        assert_eq!(q.is_full(), false);
    }

    #[test]
    fn test_as_slice() {
        let mut q = RingBuffer::<u8, 8>::default();
        assert_eq!(q.push_slice(b"Hello"), Ok(()));

        assert_eq!(q.as_slice(), b"Hello");
        q.consume(5);
        assert_eq!(q.is_empty(), true);

        // This part will be wrapped around the end of the array,
        // so we need to perform two `as_slice` ops to get the whole thing.
        assert_eq!(q.push_slice(b"World"), Ok(()));
        assert_eq!(q.as_slice(), b"Wor");
        q.consume(3);
        assert_eq!(q.as_slice(), b"ld");
        q.consume(2);
        assert_eq!(q.is_empty(), true);
    }
}
