pub struct DescriptorRing<D, const N: usize> {
descriptors: [D; N],
current: usize,
}
impl<D, const N: usize> DescriptorRing<D, N> {
#[must_use]
pub const fn new(descriptors: [D; N]) -> Self {
Self {
descriptors,
current: 0,
}
}
#[inline(always)]
#[must_use]
pub const fn len(&self) -> usize {
N
}
#[inline(always)]
#[must_use]
pub const fn is_empty(&self) -> bool {
N == 0
}
#[inline(always)]
#[must_use]
pub const fn current_index(&self) -> usize {
self.current
}
#[inline(always)]
pub fn advance(&mut self) {
self.current = (self.current + 1) % N;
}
#[inline(always)]
pub fn advance_by(&mut self, count: usize) {
self.current = (self.current + count) % N;
}
#[inline(always)]
pub fn reset(&mut self) {
self.current = 0;
}
#[inline(always)]
pub fn current(&self) -> &D {
&self.descriptors[self.current]
}
#[inline(always)]
pub fn current_mut(&mut self) -> &mut D {
&mut self.descriptors[self.current]
}
#[inline(always)]
pub fn get(&self, index: usize) -> &D {
&self.descriptors[index % N]
}
#[inline(always)]
pub fn get_mut(&mut self, index: usize) -> &mut D {
&mut self.descriptors[index % N]
}
#[inline(always)]
pub fn base_addr(&self) -> *const D {
self.descriptors.as_ptr()
}
pub fn iter(&self) -> impl Iterator<Item = &D> {
self.descriptors.iter()
}
pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut D> {
self.descriptors.iter_mut()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn ring_len() {
let ring = DescriptorRing::new([0u32; 8]);
assert_eq!(ring.len(), 8);
assert!(!ring.is_empty());
}
#[test]
fn ring_advance_wraps() {
let mut ring = DescriptorRing::new([0u32; 4]);
assert_eq!(ring.current_index(), 0);
ring.advance();
assert_eq!(ring.current_index(), 1);
ring.advance();
assert_eq!(ring.current_index(), 2);
ring.advance();
assert_eq!(ring.current_index(), 3);
ring.advance();
assert_eq!(ring.current_index(), 0); }
#[test]
fn ring_current_changes_after_advance() {
let mut ring = DescriptorRing::new([10u32, 20, 30]);
assert_eq!(*ring.current(), 10);
ring.advance();
assert_eq!(*ring.current(), 20);
ring.advance();
assert_eq!(*ring.current(), 30);
}
#[test]
fn ring_reset() {
let mut ring = DescriptorRing::new([0u32; 4]);
ring.advance();
ring.advance();
assert_eq!(ring.current_index(), 2);
ring.reset();
assert_eq!(ring.current_index(), 0);
}
#[test]
fn ring_base_addr() {
let ring = DescriptorRing::new([10u32, 20, 30]);
let ptr = ring.base_addr();
assert!(!ptr.is_null());
unsafe {
assert_eq!(*ptr, 10);
}
}
#[test]
fn ring_get_by_index() {
let ring = DescriptorRing::new([10u32, 20, 30, 40]);
assert_eq!(*ring.get(0), 10);
assert_eq!(*ring.get(1), 20);
assert_eq!(*ring.get(3), 40);
}
#[test]
fn ring_get_wraps() {
let ring = DescriptorRing::new([10u32, 20, 30, 40]);
assert_eq!(*ring.get(4), 10); assert_eq!(*ring.get(5), 20);
}
#[test]
fn ring_get_mut_modifies() {
let mut ring = DescriptorRing::new([10u32, 20, 30]);
*ring.get_mut(1) = 999;
assert_eq!(*ring.get(1), 999);
}
#[test]
fn ring_current_mut_modifies() {
let mut ring = DescriptorRing::new([10u32, 20, 30]);
*ring.current_mut() = 42;
assert_eq!(*ring.current(), 42);
}
#[test]
fn ring_iter() {
let ring = DescriptorRing::new([1u32, 2, 3, 4]);
let mut iter = ring.iter();
assert_eq!(iter.next(), Some(&1));
assert_eq!(iter.next(), Some(&2));
assert_eq!(iter.next(), Some(&3));
assert_eq!(iter.next(), Some(&4));
assert_eq!(iter.next(), None);
}
#[test]
fn ring_iter_mut() {
let mut ring = DescriptorRing::new([1u32, 2, 3, 4]);
for val in ring.iter_mut() {
*val *= 10;
}
assert_eq!(*ring.get(0), 10);
assert_eq!(*ring.get(1), 20);
assert_eq!(*ring.get(2), 30);
assert_eq!(*ring.get(3), 40);
}
#[test]
fn ring_single_element() {
let mut ring = DescriptorRing::new([42u32]);
assert_eq!(ring.len(), 1);
assert_eq!(*ring.current(), 42);
ring.advance();
assert_eq!(ring.current_index(), 0); }
#[test]
fn ring_wraparound_stress() {
let mut ring = DescriptorRing::new([0u32; 7]);
for i in 0..100 {
assert_eq!(ring.current_index(), i % 7);
ring.advance();
}
}
}