pub struct BMRingBufRef<'a, T: Copy + Clone + Default> { /* private fields */ }
Expand description

A fast ring buffer implementation with cheap and safe indexing. It works by bit-masking an integer index to get the corresponding index in an array/vec whose length is a power of 2. This is best used when indexing the buffer with an isize value. Copies/reads with slices are implemented with memcpy. This works the same as BMRingBuf except it uses a reference as its data source instead of an internal Vec.

Implementations§

source§

impl<'a> BMRingBufRef<'a, f32>

source

pub fn lin_interp_f32(&self, index: f32) -> f32

Gets the linearly interpolated value between the two values at index.floor() and index.floor() + 1, where index is an f32.

Example
use bit_mask_ring_buf::BMRingBufRef;
let mut data = [0.0f32, 2.0, 4.0, 6.0];
let rb = BMRingBufRef::new(&mut data[..]);

assert!((rb.lin_interp_f32(1.0) - 2.0).abs() <= f32::EPSILON);
assert!((rb.lin_interp_f32(1.25) - 2.5).abs() <= f32::EPSILON);
assert!((rb.lin_interp_f32(3.75) - 1.5).abs() <= f32::EPSILON);
source

pub fn lin_interp_f64(&self, index: f64) -> f32

Gets the linearly interpolated value between the two values at index.floor() and index.floor() + 1, where index is an f64.

Example
use bit_mask_ring_buf::BMRingBufRef;
let mut data = [0.0f32, 2.0, 4.0, 6.0];
let rb = BMRingBufRef::new(&mut data[..]);

assert!((rb.lin_interp_f64(1.0f64) - 2.0).abs() <= f32::EPSILON);
assert!((rb.lin_interp_f64(1.25f64) - 2.5).abs() <= f32::EPSILON);
assert!((rb.lin_interp_f64(3.75f64) - 1.5).abs() <= f32::EPSILON);
source§

impl<'a> BMRingBufRef<'a, f64>

source

pub fn lin_interp_f32(&self, index: f32) -> f64

Gets the linearly interpolated value between the two values at index.floor() and index.floor() + 1, where index is an f32.

Example
use bit_mask_ring_buf::BMRingBufRef;
let mut data = [0.0f64, 2.0, 4.0, 6.0];
let rb = BMRingBufRef::new(&mut data[..]);

assert!((rb.lin_interp_f32(1.0f32) - 2.0).abs() <= f64::EPSILON);
assert!((rb.lin_interp_f32(1.25f32) - 2.5).abs() <= f64::EPSILON);
assert!((rb.lin_interp_f32(3.75f32) - 1.5).abs() <= f64::EPSILON);
source

pub fn lin_interp_f64(&self, index: f64) -> f64

Gets the linearly interpolated value between the two values at index.floor() and index.floor() + 1, where index is an f64.

Example
use bit_mask_ring_buf::BMRingBufRef;
let mut data = [0.0f64, 2.0, 4.0, 6.0];
let rb = BMRingBufRef::new(&mut data[..]);

assert!((rb.lin_interp_f64(1.0) - 2.0).abs() <= f64::EPSILON);
assert!((rb.lin_interp_f64(1.25) - 2.5).abs() <= f64::EPSILON);
assert!((rb.lin_interp_f64(3.75) - 1.5).abs() <= f64::EPSILON);
source§

impl<'a, T: Copy + Clone + Default> BMRingBufRef<'a, T>

source

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

Creates a new BMRingBufRef with the given data.

Safety
  • Using this struct may cause undefined behavior if the given data in slice was not initialized first
  • The data in slice must be valid and properly aligned. See std::slice::from_raw_parts for more details.
  • The size in bytes of the data in slice should be no larger than isize::MAX. See std::ptr::offset for more information when indexing very large buffers on 32-bit and 16-bit platforms.
Example
use bit_mask_ring_buf::BMRingBufRef;

let mut data = [1u32, 2, 3, 4];
let rb = BMRingBufRef::new(&mut data[..]);

assert_eq!(rb.len(), 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 the given slice is not a power of 2
  • This will panic if the length of the slice is less than 2
  • This will panic if the length of the slice is greater than (std::usize::MAX/2)+1
source

pub fn clear(&mut self)

Clears all values in the ring buffer to the default value.

Example
use bit_mask_ring_buf::BMRingBufRef;

let mut data = [1u32, 2, 3, 4];
let mut rb = BMRingBufRef::new(&mut data[..]);

rb.clear();

assert_eq!(rb[0], 0);
assert_eq!(rb[1], 0);
assert_eq!(rb[2], 0);
assert_eq!(rb[3], 0);
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.

Safety
  • Using this may cause undefined behavior if the given data in slice in BMRingBufRef::new() was not initialized first.
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
use bit_mask_ring_buf::BMRingBufRef;

let mut data = [1u32, 2, 3, 4];
let mut rb = BMRingBufRef::new(&mut 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 length of the ring buffer, then the buffer’s length will be used instead.
Safety
  • Using this may cause undefined behavior if the given data in slice in BMRingBufRef::new() was not initialized first.
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
use bit_mask_ring_buf::BMRingBufRef;

let mut data = [1u32, 2, 3, 4];
let mut rb = BMRingBufRef::new(&mut 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.
Safety
  • Using this may cause undefined behavior if the given data in slice in BMRingBufRef::new() was not initialized first.
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
use bit_mask_ring_buf::BMRingBufRef;

let mut data = [1u32, 2, 3, 4];
let mut rb = BMRingBufRef::new(&mut 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 as_mut_slices(&mut self, start: isize) -> (&mut [T], &mut [T])

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

Safety
  • Using this may cause undefined behavior if the given data in slice in BMRingBufRef::new() was not initialized first.
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
use bit_mask_ring_buf::BMRingBufRef;

let mut data = [1u32, 2, 3, 4];
let mut rb = BMRingBufRef::new(&mut data[..]);

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

let (s1, s2) = rb.as_mut_slices(3);
assert_eq!(s1, &mut [4]);
assert_eq!(s2, &mut [1, 2, 3]);
source

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

Returns two mutable 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 length of the ring buffer, then the buffer’s length will be used instead.
Safety
  • Using this may cause undefined behavior if the given data in slice in BMRingBufRef::new() was not initialized first.
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
use bit_mask_ring_buf::BMRingBufRef;

let mut data = [1u32, 2, 3, 4];
let mut rb = BMRingBufRef::new(&mut data[..]);

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

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

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

Returns two mutable 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.
Safety
  • Using this may cause undefined behavior if the given data in slice in BMRingBufRef::new() was not initialized first.
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
use bit_mask_ring_buf::BMRingBufRef;

let mut data = [1u32, 2, 3, 4];
let mut rb = BMRingBufRef::new(&mut data[..]);

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

let (s1, s2) = rb.as_mut_slices_latest(0, 5);
assert_eq!(s1, &mut [2, 3, 4]);
assert_eq!(s2, &mut [1]);
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 length of the ring buffer, then the data will be reapeated until the given slice is filled.

Safety
  • Using this may cause undefined behavior if the given data in slice in BMRingBufRef::new() was not initialized first.

  • 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
use bit_mask_ring_buf::BMRingBufRef;

let mut data = [1u32, 2, 3, 4];
let mut rb = BMRingBufRef::new(&mut 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]);
source

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

Copies data from the given slice into the ring buffer starting from the index start.

Earlier data will not be copied if it will be overwritten by newer data, avoiding unecessary memcpy’s. The correct placement of the newer data will still be preserved.

  • slice - This slice to copy data from.
  • 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
use bit_mask_ring_buf::BMRingBufRef;

let mut data = [0u32; 4];
let mut rb = BMRingBufRef::new(&mut data[..]);

let input = [1u32, 2, 3];
rb.write_latest(&input[..], -3);
assert_eq!(rb[0], 0);
assert_eq!(rb[1], 1);
assert_eq!(rb[2], 2);
assert_eq!(rb[3], 3);

let input = [1u32, 2, 3, 4, 5, 6, 7, 8, 9];
rb.write_latest(&input[..], 2);
assert_eq!(rb[0], 7);
assert_eq!(rb[1], 8);
assert_eq!(rb[2], 9);
assert_eq!(rb[3], 6);
source

pub fn write_latest_2(&mut self, first: &[T], second: &[T], start: isize)

Copies data from two given slices into the ring buffer starting from the index start. The first slice will be copied first then second will be copied next.

Earlier data will not be copied if it will be overwritten by newer data, avoiding unecessary memcpy’s. The correct placement of the newer data will still be preserved.

  • first - This first slice to copy data from.
  • second - This second slice to copy data from.
  • 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
use bit_mask_ring_buf::{BMRingBuf, BMRingBufRef};

let mut input_rb = BMRingBuf::<u32>::from_len(4);
input_rb[0] = 1;
input_rb[1] = 2;
input_rb[2] = 3;
input_rb[3] = 4;

let mut output_data = [0u32; 4];
let mut output_rb = BMRingBufRef::new(&mut output_data[..]);
// s1 == &[1, 2], s2 == &[]
let (s1, s2) = input_rb.as_slices_len(0, 2);
output_rb.write_latest_2(s1, s2, -3);
assert_eq!(output_rb[0], 0);
assert_eq!(output_rb[1], 1);
assert_eq!(output_rb[2], 2);
assert_eq!(output_rb[3], 0);

let mut output_data = [0u32; 2];
let mut output_rb = BMRingBufRef::new(&mut output_data[..]);
// s1 == &[4],  s2 == &[1, 2, 3]
let (s1, s2) = input_rb.as_slices_len(3, 4);
// rb[1] = 4  ->  rb[0] = 1  ->  rb[1] = 2  ->  rb[0] = 3
output_rb.write_latest_2(s1, s2, 1);
assert_eq!(output_rb[0], 3);
assert_eq!(output_rb[1], 2);
source

pub fn len(&self) -> usize

Returns the length of the ring buffer.

Example
use bit_mask_ring_buf::BMRingBufRef;
let mut data = [0u32; 4];
let mut rb = BMRingBufRef::new(&mut data[..]);

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

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

Returns the actual index of the ring buffer from the given i index. This is cheap due to the ring buffer’s bit-masking algorithm. This is useful to keep indexes from growing indefinitely.

Example
use bit_mask_ring_buf::BMRingBufRef;
let mut data = [0u32; 4];
let mut rb = BMRingBufRef::new(&mut 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 raw_data(&self) -> &[T]

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

Example
use bit_mask_ring_buf::BMRingBufRef;
let mut data = [1u32, 2, 3, 4];
let mut rb = BMRingBufRef::new(&mut data[..]);

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

pub fn raw_data_mut(&mut self) -> &mut [T]

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

Example
use bit_mask_ring_buf::BMRingBufRef;
let mut data = [1u32, 2, 3, 4];
let mut rb = BMRingBufRef::new(&mut data[..]);

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

pub fn raw_at(&self, i: usize) -> &T

Returns the element at the index of type usize.

Please note this does NOT wrap around. This is equivalent to indexing a normal slice type.

Example
use bit_mask_ring_buf::BMRingBufRef;
let mut data = [1u32, 2, 3, 4];
let mut rb = BMRingBufRef::new(&mut data[..]);

assert_eq!(*rb.raw_at(0), 1);
assert_eq!(*rb.raw_at(3), 4);

// These will panic!
// assert_eq!(*rb.raw_at(-3), 2);
// assert_eq!(*rb.raw_at(4), 1);
Panics
  • This will panic if i is out of bounds of the internal slice.
source

pub fn raw_at_mut(&mut self, i: usize) -> &mut T

Returns the element at the index of type usize as mutable.

Please note this does NOT wrap around. This is equivalent to indexing a normal slice type.

Example
use bit_mask_ring_buf::BMRingBufRef;
let mut data = [0u32; 4];
let mut rb = BMRingBufRef::new(&mut data[..]);

*rb.raw_at_mut(0) = 1;
*rb.raw_at_mut(3) = 4;

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

// These will panic!
// *rb.raw_at_mut(-3) = 2;
// *rb.raw_at_mut(4) = 1;
Panics
  • This will panic if i is out of bounds of the internal slice.
source

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

Returns the element at the index of type usize while also constraining the index i. This is slightly more efficient than calling both methods individually.

Performance

Prefer to manipulate data in bulk with methods that return slices.

Example
use bit_mask_ring_buf::BMRingBufRef;
let mut data = [1u32, 2, 3, 4];
let mut rb = BMRingBufRef::new(&mut data[..]);

let mut i = -3;
assert_eq!(*rb.at(&mut i), 2);
assert_eq!(i, 1);
source

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

Returns the element at the index of type usize as mutable while also constraining the index i. This is slightly more efficient than calling both methods individually.

Performance

Prefer to manipulate data in bulk with methods that return slices.

Example
use bit_mask_ring_buf::BMRingBufRef;
let mut data = [0u32; 4];
let mut rb = BMRingBufRef::new(&mut data[..]);

let mut i = -3;
*rb.at_mut(&mut i) = 2;

assert_eq!(rb[1], 2);
assert_eq!(i, 1);

Trait Implementations§

source§

impl<'a, T: Debug + Copy + Clone + Default> Debug for BMRingBufRef<'a, T>

source§

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

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

impl<'a, T: Copy + Clone + Default> Index<isize> for BMRingBufRef<'a, T>

§

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: Copy + Clone + Default> IndexMut<isize> for BMRingBufRef<'a, T>

source§

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

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

Auto Trait Implementations§

§

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

§

impl<'a, T> Send for BMRingBufRef<'a, T>where T: Send,

§

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

§

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

§

impl<'a, T> !UnwindSafe for BMRingBufRef<'a, T>

Blanket Implementations§

source§

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

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

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

const: unstable · source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

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

const: unstable · source§

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

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

const: unstable · source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

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

const: unstable · 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 Twhere U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
const: unstable · source§

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

Performs the conversion.
source§

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

§

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

The type returned in the event of a conversion error.
const: unstable · source§

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

Performs the conversion.