SliceRbRef

Struct SliceRbRef 

Source
pub struct SliceRbRef<'a, T> { /* private fields */ }
Expand description

A ring buffer implementation optimized for working with slices. Note this pretty much does the same thing as VecDeque, but with the added ability to index using negative values, as well as working with buffers allocated on the stack. This struct can be used without the standard library (#![no_std]).

This works the same as SliceRB except it uses an immutable reference as its data source instead of an internal Vec.

This struct has no consumer/producer logic, and is meant to be used for DSP or as a base for other data structures.

This data type is optimized for manipulating data in chunks with slices. Indexing one element at a time is slow.

The length of this ring buffer cannot be 0.

§Example

let stack_data = [0u32, 1, 2, 3];
let rb_ref = SliceRbRef::new(&stack_data);
assert_eq!(rb_ref[-3], 1);

let (s1, s2) = rb_ref.as_slices_len(2, 3);
assert_eq!(s1, &[2, 3]);
assert_eq!(s2, &[0]);

Implementations§

Source§

impl<'a, T> SliceRbRef<'a, T>

Source

pub const fn new(slice: &'a [T]) -> Self

Creates a new SliceRbRef with the given data.

§Example
let data = [1u32, 2, 3, 4];
let rb = SliceRbRef::new(&data[..]);

assert_eq!(rb.len().get(), 4);

assert_eq!(rb[0], 1);
assert_eq!(rb[1], 2);
assert_eq!(rb[2], 3);
assert_eq!(rb[3], 4);
§Panics
  • This will panic if the length of slice is 0 or is greater than isize::MAX.
Source

pub const unsafe fn new_unchecked(slice: &'a [T]) -> Self

Creates a new SliceRbRef with the given data without checking that the length of the data is greater than 0 and less than or equal to isize::MAX.

§Example
let data = [1u32, 2, 3, 4];
let rb = unsafe { SliceRbRef::new_unchecked(&data[..]) };

assert_eq!(rb.len().get(), 4);

assert_eq!(rb[0], 1);
assert_eq!(rb[1], 2);
assert_eq!(rb[2], 3);
assert_eq!(rb[3], 4);
§Safety

The length of slice must be greater than 0 and less than or equal to isize::MAX.

Source

pub fn len(&self) -> NonZeroUsize

Returns the length of the ring buffer.

§Example
let data = [0u32; 4];
let rb = SliceRbRef::new(&data[..]);

assert_eq!(rb.len().get(), 4);
Source

pub fn constrain(&self, i: isize) -> isize

Returns the actual index of the ring buffer from the given i index.

  • First, a bounds check will be performed. If it is within bounds, then it is simply returned.
  • If it is not in bounds, then performance will be limited by the modulo (remainder) operation on an isize value.
§Performance

Prefer to manipulate data in bulk with methods that return slices. If you need to index multiple elements one at a time, prefer to use SliceRbRef::at(&mut i) over SliceRbRef[i] to reduce the number of modulo operations to perform.

§Example
let data = [0u32; 4];
let rb = SliceRbRef::new(&data[..]);

assert_eq!(rb.constrain(2), 2);
assert_eq!(rb.constrain(4), 0);
assert_eq!(rb.constrain(-3), 1);
assert_eq!(rb.constrain(7), 3);
Source

pub fn as_slices(&self, start: isize) -> (&[T], &[T])

Returns two slices that contain all the data in the ring buffer starting at the index start.

§Returns
  • The first slice is the starting chunk of data. This will never be empty.
  • The second slice is the second contiguous chunk of data. This may or may not be empty depending if the buffer needed to wrap around to the beginning of its internal memory layout.
§Performance

Prefer to use this to manipulate data in bulk over indexing one element at a time.

§Example
let data = [1u32, 2, 3, 4];
let rb = SliceRbRef::new(&data[..]);

let (s1, s2) = rb.as_slices(-4);
assert_eq!(s1, &[1, 2, 3, 4]);
assert_eq!(s2, &[]);

let (s1, s2) = rb.as_slices(3);
assert_eq!(s1, &[4]);
assert_eq!(s2, &[1, 2, 3]);
Source

pub fn as_slices_len(&self, start: isize, len: usize) -> (&[T], &[T])

Returns two slices of data in the ring buffer starting at the index start and with length len.

  • start - The starting index
  • len - The length of data to read. If len is greater than the capacity of the ring buffer, then that capacity will be used instead.
§Returns
  • The first slice is the starting chunk of data.
  • The second slice is the second contiguous chunk of data. This may or may not be empty depending if the buffer needed to wrap around to the beginning of its internal memory layout.
§Performance

Prefer to use this to manipulate data in bulk over indexing one element at a time.

§Example
let data = [1u32, 2, 3, 4];
let rb = SliceRbRef::new(&data[..]);

let (s1, s2) = rb.as_slices_len(-4, 3);
assert_eq!(s1, &[1, 2, 3]);
assert_eq!(s2, &[]);

let (s1, s2) = rb.as_slices_len(3, 5);
assert_eq!(s1, &[4]);
assert_eq!(s2, &[1, 2, 3]);
Source

pub fn as_slices_latest(&self, start: isize, len: usize) -> (&[T], &[T])

Returns two slices of data in the ring buffer starting at the index start and with length len. If len is greater than the length of the ring buffer, then the buffer’s length will be used instead, while still preserving the position of the last element.

  • start - The starting index
  • len - The length of data to read. If len is greater than the length of the ring buffer, then the buffer’s length will be used instead, while still preserving the position of the last element.
§Returns
  • The first slice is the starting chunk of data.
  • The second slice is the second contiguous chunk of data. This may or may not be empty depending if the buffer needed to wrap around to the beginning of its internal memory layout.
§Performance

Prefer to use this to manipulate data in bulk over indexing one element at a time.

§Example
let data = [1u32, 2, 3, 4];
let rb = SliceRbRef::new(&data[..]);

let (s1, s2) = rb.as_slices_latest(-4, 3);
assert_eq!(s1, &[1, 2, 3]);
assert_eq!(s2, &[]);

let (s1, s2) = rb.as_slices_latest(0, 5);
assert_eq!(s1, &[2, 3, 4]);
assert_eq!(s2, &[1]);
Source

pub fn raw_data(&self) -> &[T]

Returns all the data in the buffer. The starting index will always be 0.

§Example
let data = [1u32, 2, 3, 4];
let rb = SliceRbRef::new(&data[..]);

let raw_data = rb.raw_data();
assert_eq!(raw_data, &[1u32, 2, 3, 4]);
Source

pub fn get(&self, i: isize) -> &T

Returns an immutable reference the element at the index of type isize.

§Performance

Prefer to manipulate data in bulk with methods that return slices. If you need to index multiple elements one at a time, prefer to use this over SliceRbRef[i] to reduce the number of modulo operations to perform.

§Example
let data = [1u32, 2, 3, 4];
let rb = SliceRbRef::new(&data[..]);

assert_eq!(*rb.get(-3), 2);
Source

pub fn constrain_and_get(&self, i: &mut isize) -> &T

Returns an immutable reference to the element at the index of type isize while also constraining the index i. This is more efficient than calling both methods individually.

§Performance

Prefer to manipulate data in bulk with methods that return slices. If you need to index multiple elements one at a time, prefer to use this over SliceRbRef[i] to reduce the number of modulo operations to perform.

§Example
let data = [1u32, 2, 3, 4];
let rb = SliceRbRef::new(&data[..]);

let mut i = -3;
assert_eq!(*rb.constrain_and_get(&mut i), 2);
assert_eq!(i, 1);
Source§

impl<'a, T: Clone + Copy> SliceRbRef<'a, T>

Source

pub fn read_into(&self, slice: &mut [T], start: isize)

Copies the data from the ring buffer starting from the index start into the given slice. If the length of slice is larger than the capacity of the ring buffer, then the data will be reapeated until the given slice is filled.

  • slice - This slice to copy the data into.
  • start - The index of the ring buffer to start copying from.
§Performance

Prefer to use this to manipulate data in bulk over indexing one element at a time.

§Example
let data = [1u32, 2, 3, 4];
let rb = SliceRbRef::new(&data[..]);

let mut read_buf = [0u32; 3];
rb.read_into(&mut read_buf[..], -3);
assert_eq!(read_buf, [2, 3, 4]);

let mut read_buf = [0u32; 9];
rb.read_into(&mut read_buf[..], 2);
assert_eq!(read_buf, [3, 4, 1, 2, 3, 4, 1, 2, 3]);

Trait Implementations§

Source§

impl<'a, T: Debug> Debug for SliceRbRef<'a, T>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<'a, T> Index<isize> for SliceRbRef<'a, T>

Source§

type Output = T

The returned type after indexing.
Source§

fn index(&self, i: isize) -> &T

Performs the indexing (container[index]) operation. Read more
Source§

impl<'a, T> Into<SliceRbRef<'a, T>> for SliceRbRefMut<'a, T>

Source§

fn into(self) -> SliceRbRef<'a, T>

Converts this type into the (usually inferred) input type.

Auto Trait Implementations§

§

impl<'a, T> Freeze for SliceRbRef<'a, T>

§

impl<'a, T> RefUnwindSafe for SliceRbRef<'a, T>
where T: RefUnwindSafe,

§

impl<'a, T> Send for SliceRbRef<'a, T>
where T: Sync,

§

impl<'a, T> Sync for SliceRbRef<'a, T>
where T: Sync,

§

impl<'a, T> Unpin for SliceRbRef<'a, T>

§

impl<'a, T> UnwindSafe for SliceRbRef<'a, T>
where T: RefUnwindSafe,

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.