Struct RingBuffer

Source
pub struct RingBuffer<T, const SIZE: usize> { /* private fields */ }
Expand description

Ring buffer using a boxed array as backing storage. This has the adantage that conversions from Vec or to VecDeque are nearly free. Main use case of this is as a replacement for std::collection::VecDeque in cases where the size is fixed at compile time and one really wants to make invalid states impossible.

Due to this, the only way to put a new item into the buffer is to take an old item out. There is intentionally no way to temporary ownership of items. If you need such an API, you can use the get_mut() method or the index operator to obtain a mutable reference, and then use either methods from std::mem to temporarily place another value there, or use internally unsafe solutions like the replace_with crate.

§Examples

Whenever you push_pop(), the buffer moves to the next element. You can get a reference to contained data using the index operator, or if you want a panic-free way, using the get() or get_mut() methods.

let input = [42,37,23,12];
let buf : RingBuffer<&usize, 4> = RingBuffer::new(input.iter()).expect("Works, enough input.");
assert_eq!(buf[0], &42);
assert_eq!(buf[1], &37);
assert_eq!(buf[2], &23);
assert_eq!(buf[3], &12);
assert_eq!(buf.get(3), Some(&&12));
assert_eq!(buf.get(4), None);
let (buf, forty_two) = buf.push_pop(&1);
assert_eq!(forty_two, &42);
assert_eq!(buf[0], &37);
assert_eq!(buf[1], &23);
assert_eq!(buf[2], &12);
assert_eq!(buf[3], &1);
let (buf, thirty_seven) = buf.push_pop(&2);
assert_eq!(thirty_seven, &37);
let (buf, twenty_three) = buf.push_pop(&3);
assert_eq!(twenty_three, &23);
let (buf, twelve) = buf.push_pop(&4);
assert_eq!(twelve, &12);
let (buf, one) = buf.push_pop(&5);
assert_eq!(one, &1);
assert_eq!(buf[0], &2);
assert_eq!(buf[1], &3);
assert_eq!(buf[2], &4);
assert_eq!(buf[3], &5);

Implementations§

Source§

impl<T, const SIZE: usize> RingBuffer<T, SIZE>

Source

pub fn push_pop(self, new_entry: T) -> (Self, T)

Puts new_entry into the ring buffer at its current location, and returns the value that was there before. Then moves the ring buffer to the next location.

§Examples
let input = [42,37,23,12];
let buf : RingBuffer<&usize, 4> = RingBuffer::new(input.iter()).expect("Works, enough input.");
assert_eq!(buf[0], &42);
assert_eq!(buf[3], &12);
let (buf, forty_two) = buf.push_pop(&1);
assert_eq!(forty_two, &42);
assert_eq!(buf[0], &37);
assert_eq!(buf[3], &1);
Source

pub fn new<I>(input: I) -> Result<Self, Box<[T]>>
where I: Iterator<Item = T>,

Creates a new RingBuffer from an Iterator. If the iterator does not supply enough elements, the elements that have already been taken from the iterator are instead returned in the Err variant as a boxed slice.

§Warning

Beware that it is not considered an error if the iterator would yield more elements. If you need the remaining data in the iterator, make sure to pass it by_ref().

§Examples

If the iterator has at least the required number of elements, a ring buffer is created.

let input = [42,37,23,12,8];
let mut iter = input.iter();
let buf : RingBuffer<&usize, 4> = RingBuffer::new(iter.by_ref()).expect("Works, enough input.");
assert_eq!(iter.next(), Some(&8));
assert_eq!(buf[0], &42);
assert_eq!(buf[1], &37);
assert_eq!(buf[2], &23);
assert_eq!(buf[3], &12);
assert_eq!(buf.get(4),None);

If the iterator does not yield enough elements, an error is returned, containing all elements taken from the iterator.

let input = ["lizard", "fish", "bird"];
let buf : Result<RingBuffer<&str, 4>, _> = RingBuffer::new(input.iter().map(|x| *x));
assert!(buf.is_err());
assert_eq!(buf.unwrap_err()[1], "fish");
Source

pub fn new_copy(init: T) -> Self
where T: Copy,

Initializes the ring buffer with copies of the same value.

§Examples
let buf :RingBuffer<usize,4> = RingBuffer::new_copy(3);
assert_eq!(buf[0], 3);
assert_eq!(buf[1], 3);
assert_eq!(buf[2], 3);
assert_eq!(buf[3], 3);
assert_eq!(buf.get(4), None);
Source

pub fn get(&self, index: usize) -> Option<&T>

Gets an immutable reference to the entry that’s index elements in the future of the buffer. In other words get(0) returns an immutable reference to the next element that would be returned by push_pop(), get(1) to the second-next and so on. Return value is wrapped in an option due to range checking. You can use the index operator [] instead if you are sure your index is valid.

§Examples
let input = [42,37,23,12];
let buf : RingBuffer<&usize, 4> = RingBuffer::new(input.iter()).expect("Works, enough input.");
let (buf, _) = buf.push_pop(&7);
assert_eq!(buf.get(0), Some(&&37));
assert_eq!(buf.get(3), Some(&&7));
assert_eq!(buf.get(4), None);
Source

pub fn get_mut(&mut self, index: usize) -> Option<&mut T>

Similar to get(), but yields a mutable reference instead.

§Examples
let input = [42,37,23,12];
let mut buf : RingBuffer<&usize, 4> = RingBuffer::new(input.iter()).expect("Works, enough input.");
match buf.get_mut(0) {
    Some(x) => { 
        assert_eq!(**x, 42);
        *x = &1;
    }
    _ => {
        unreachable!();
    }
}
assert_eq!(buf.get(0), Some(&&1));
Source

pub fn iter(&self) -> RingBufferIterator<'_, T, SIZE>

Returns an Iterator over references to the contained elements.

§Examples
let input = [42,37,23,12];
let buf : RingBuffer<&usize, 4> = RingBuffer::new(input.iter()).expect("Works, enough input");
let (buf, forty_two) = buf.push_pop(&1);
assert_eq!(forty_two, &42);
assert!(buf.iter().map(|x| *x).eq([37,23,12,1].iter()));

Trait Implementations§

Source§

impl<T: Clone, const SIZE: usize> Clone for RingBuffer<T, SIZE>

Source§

fn clone(&self) -> RingBuffer<T, SIZE>

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl<T: Debug, const SIZE: usize> Debug for RingBuffer<T, SIZE>

Source§

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

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

impl<T, const SIZE: usize> From<RingBuffer<T, SIZE>> for VecDeque<T>

Source§

fn from(buffer: RingBuffer<T, SIZE>) -> VecDeque<T>

Conversion from a RingBuffer<T, const SIZE :usize> into a VecDeque<T>. This works without re-allocations and cannot fail.

§Examples
use std::collections::VecDeque;
let a = vec![42,37,23,12];
let buf : RingBuffer<_, 4> = a.try_into().expect("Works, size matches.");
let (buf, _) = buf.push_pop(5);
let deque : VecDeque<_> = buf.into();
assert_eq!(deque[0], 37);
assert_eq!(deque[3], 5);
Source§

impl<T, const SIZE: usize> Index<usize> for RingBuffer<T, SIZE>

Source§

fn index(&self, index: usize) -> &T

Indexing operation in an immutable context. Internally uses get(). Indices start at the value that would be replaced/returned by the next call to push_pop().

§Examples
let input = [42,37,23,12];
let buf : RingBuffer<&usize, 4> = RingBuffer::new(input.iter()).unwrap();
let (buf, _) = buf.push_pop(&123);
assert_eq!(buf[0],&37);
assert_eq!(buf[3],&123);
§Panics

If the index is out of range (larger than or equal to SIZE), this panics. Use get() if you want sane behaviour.

Source§

type Output = T

The returned type after indexing.
Source§

impl<T, const SIZE: usize> IndexMut<usize> for RingBuffer<T, SIZE>

Source§

fn index_mut(&mut self, index: usize) -> &mut T

Indexing operation in a mutable context. Internally uses get_mut(). Indices start at the value that would be replaced/returned by the next call to push_pop().

§Examples
let input = [42,37,23,12];
let mut buf : RingBuffer<&usize, 4> = RingBuffer::new(input.iter()).unwrap();
buf[1] = &0;
assert_eq!(buf[1], &0);
let (buf, forty_two) = buf.push_pop(&3);
assert_eq!(forty_two, &42);
let (buf, zero) = buf.push_pop(&4);
assert_eq!(zero, &0);
§Panics

If the index is out of range (larger than or equal to SIZE), this panics. Use get_mut() if you want sane behaviour.

Source§

impl<'b, T, const SIZE: usize> IntoIterator for &'b RingBuffer<T, SIZE>

Source§

fn into_iter(self) -> Self::IntoIter

Wrapper around the RingBuffer::iter() to enable for-loop compatibility for &RingBuffer.

§Example
let input = [42,37,23,12];
let buf : RingBuffer<&usize, 4> = RingBuffer::new(input.iter()).unwrap();
let (buf, forty_two) = buf.push_pop(&1);
assert_eq!(forty_two, &42);
let reference = &buf;
assert!(reference.into_iter().map(|x| *x).eq([37,23,12,1].iter()));
Source§

type Item = &'b T

The type of the elements being iterated over.
Source§

type IntoIter = RingBufferIterator<'b, T, SIZE>

Which kind of iterator are we turning this into?
Source§

impl<T, const SIZE: usize> IntoIterator for RingBuffer<T, SIZE>

Source§

fn into_iter(self) -> Self::IntoIter

Consumes the ring buffer into an Iterator. This conversion works without reallocation.

§Example
let input = [42,37,23,12];
let buf : RingBuffer<&usize, 4> = RingBuffer::new(input.iter()).unwrap();
let (buf, forty_two) = buf.push_pop(&1);
assert_eq!(forty_two, &42);
assert!(buf.into_iter().eq([37,23,12,1].iter()));
Source§

type Item = T

The type of the elements being iterated over.
Source§

type IntoIter = IntoIter<T>

Which kind of iterator are we turning this into?
Source§

impl<T, const SIZE: usize> TryFrom<Box<[T]>> for RingBuffer<T, SIZE>

Source§

fn try_from(slice: Box<[T]>) -> Result<Self, Self::Error>

Conversion from a boxed slice. This works without a re-allocation. Returns the input as Err in case the size does not match. Opposed to the new() method that takes an Iterator this conversion fails if the input has more elements than fit into the ring buffer.

§Examples
let a : Box<[_]> = vec![42,37,23,12].into();
let buf : RingBuffer<_, 4> = a.try_into().expect("Works, size matches.");
assert_eq!(buf[0], 42);
assert_eq!(buf[1], 37);
assert_eq!(buf[2], 23);
assert_eq!(buf[3], 12);
assert_eq!(buf.get(4),None);

let b : Box<[_]> = vec![42,37,23,12].into();
let b_cpy = b.clone();
let buf2 : Result<RingBuffer<_,3>,_> = b.try_into();
assert_eq!(buf2.unwrap_err(), b_cpy);
Source§

type Error = Box<[T]>

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

impl<T, const SIZE: usize> TryFrom<Vec<T>> for RingBuffer<T, SIZE>

Source§

fn try_from(vector: Vec<T>) -> Result<Self, Self::Error>

Conversion from a Vec. This works without re-allocation. Returns the input as Err in case the size does not match. Opposed to the new() method that takes an Iterator this conversion fails if the input has more elements than fit into the ring buffer.

§Examples
let a = vec![42,37,23,12];
let buf : RingBuffer<_, 4> = a.try_into().expect("Works, size matches.");
assert_eq!(buf[0], 42);
assert_eq!(buf[1], 37);
assert_eq!(buf[2], 23);
assert_eq!(buf[3], 12);
assert_eq!(buf.get(4),None);

let b = vec![42,37,23,12];
let b_cpy = b.clone();
let buf2 : Result<RingBuffer<_,3>,_> = b.try_into();
assert_eq!(buf2.unwrap_err(), b_cpy);
Source§

type Error = Vec<T>

The type returned in the event of a conversion error.

Auto Trait Implementations§

§

impl<T, const SIZE: usize> Freeze for RingBuffer<T, SIZE>

§

impl<T, const SIZE: usize> RefUnwindSafe for RingBuffer<T, SIZE>
where T: RefUnwindSafe,

§

impl<T, const SIZE: usize> Send for RingBuffer<T, SIZE>
where T: Send,

§

impl<T, const SIZE: usize> Sync for RingBuffer<T, SIZE>
where T: Sync,

§

impl<T, const SIZE: usize> Unpin for RingBuffer<T, SIZE>

§

impl<T, const SIZE: usize> UnwindSafe for RingBuffer<T, SIZE>
where T: UnwindSafe,

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> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. 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> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
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.