bit_mask_ring_buf/
lib.rs

1//! A ring buffer implementation with cheap indexing written in Rust.
2//!
3//! Note, this crate is only beneficial if your algorithm indexes elements one at a time
4//! and has buffer sizes that are always a power of two. If your algorithm instead reads
5//! chunks of data as slices or requires buffer sizes that are not a power of two, then
6//! check out my crate [`slice_ring_buf`].
7//!
8//! This crate has no consumer/producer logic, and is meant to be used for DSP or as
9//! a base for other data structures.
10//!
11//! This crate can also be used without the standard library (`#![no_std]`).
12//!
13//! ## Example
14//! ```rust
15//! use bit_mask_ring_buf::{BitMaskRB, BitMaskRbRefMut};
16//!
17//! // Create a ring buffer with type u32. The data will be
18//! // initialized with the given value (0 in this case).
19//! // The actual length will be set to the next highest
20//! // power of 2 if the given length is not already
21//! // a power of 2.
22//! let mut rb = BitMaskRB::<u32>::new(3, 0);
23//! assert_eq!(rb.len().get(), 4);
24//!
25//! // Read/write to buffer by indexing with an `isize`.
26//! rb[0] = 0;
27//! rb[1] = 1;
28//! rb[2] = 2;
29//! rb[3] = 3;
30//!
31//! // Cheaply wrap when reading/writing outside of bounds.
32//! assert_eq!(rb[-1], 3);
33//! assert_eq!(rb[10], 2);
34//!
35//! // Memcpy into slices at arbitrary `isize` indexes
36//! // and length.
37//! let mut read_buffer = [0u32; 7];
38//! rb.read_into(&mut read_buffer, 2);
39//! assert_eq!(read_buffer, [2, 3, 0, 1, 2, 3, 0]);
40//!
41//! // Memcpy data from a slice into the ring buffer at
42//! // arbitrary `isize` indexes. Earlier data will not be
43//! // copied if it will be overwritten by newer data,
44//! // avoiding unecessary memcpy's. The correct placement
45//! // of the newer data will still be preserved.
46//! rb.write_latest(&[0, 2, 3, 4, 1], 0);
47//! assert_eq!(rb[0], 1);
48//! assert_eq!(rb[1], 2);
49//! assert_eq!(rb[2], 3);
50//! assert_eq!(rb[3], 4);
51//!
52//! // Read/write by retrieving slices directly.
53//! let (s1, s2) = rb.as_slices_len(1, 4);
54//! assert_eq!(s1, &[2, 3, 4]);
55//! assert_eq!(s2, &[1]);
56//!
57//! // Aligned/stack data may also be used.
58//! let mut stack_data = [0u32, 1, 2, 3];
59//! let mut rb_ref = BitMaskRbRefMut::new(&mut stack_data);
60//! rb_ref[-4] = 5;
61//! assert_eq!(rb_ref[0], 5);
62//! assert_eq!(rb_ref[1], 1);
63//! assert_eq!(rb_ref[2], 2);
64//! assert_eq!(rb_ref[3], 3);
65//!
66//! # #[cfg(feature = "interpolation")] {
67//! // Linear interpolation is also provided (requires the
68//! // `interpolation` feature which requires the standard
69//! // library.)
70//! let rb = BitMaskRB::<f32>::from_vec(vec![0.0, 2.0, 4.0, 6.0]);
71//! assert!((rb.lin_interp(-1.75) - 4.5).abs() <= f32::EPSILON);
72//! # }
73//! ```
74//!
75//! [`slice_ring_buf`]: https://crates.io/crates/slice_ring_buf
76
77#![cfg_attr(not(feature = "interpolation"), no_std)]
78
79#[cfg(feature = "alloc")]
80extern crate alloc;
81
82mod inner;
83mod referenced;
84
85pub use referenced::{BitMaskRbRef, BitMaskRbRefMut};
86
87#[cfg(feature = "alloc")]
88mod owned;
89#[cfg(feature = "alloc")]
90pub use owned::BitMaskRB;
91
92#[cfg(feature = "interpolation")]
93mod interpolation;
94
95/// Returns the next highest power of 2 if `n` is not already a power of 2.
96/// This will return `2` if `n < 2`.
97///
98/// # Example
99///
100/// ```
101/// # use bit_mask_ring_buf::next_pow_of_2;
102/// assert_eq!(next_pow_of_2(3), 4);
103/// assert_eq!(next_pow_of_2(8), 8);
104/// assert_eq!(next_pow_of_2(0), 2);
105/// ```
106///
107/// # Panics
108///
109/// * This will panic if `n > (std::usize::MAX/2)+1`
110pub const fn next_pow_of_2(n: usize) -> usize {
111    if n < 2 {
112        return 2;
113    }
114
115    n.checked_next_power_of_two().unwrap()
116}