macro_rules! buffer_ring {
(
// STATIC (option)
// struct definition + optional implementations
$(#[$attr:meta])*
$vis:vis struct $name:ident : $(static)? ($($I:tt)+);
$($rest:tt)*
) => { ... };
( // implementations only
impl $name:ident : $(static)? ($($I:tt)+); $($rest:tt)*
) => { ... };
(
// VIEW: TODO: (slice_mut, slice)
// struct definition + optional implementations
$(#[$_attr:meta])*
$_vis:vis struct $_name:ident : view ($($_I:tt)+);
$($_rest:tt)*
) => { ... };
( // implementations only
impl $_name:ident : view ($($_I:tt)+);
$($_rest:tt)*
) => { ... };
(
// ALLOC TODO: (vec)
// struct definition + optional implementations
$(#[$_attr:meta])*
$_vis:vis struct $_name:ident : alloc ($($_I:tt)+);
$($_rest:tt)*
) => { ... };
( // implementations only
impl $_name:ident : alloc ($($_I:tt)+);
$($_rest:tt)*
) => { ... };
(
/* internals */
%impls_static $name:ident : $I:ty, $P:ty ;) => { ... };
(%impls_static $name:ident : $I:ty, $P:ty ; $(#[$i:meta])* $impl:ident) => { ... };
(%impls_static $name:ident : $I:ty, $P:ty ; $(#[$i:meta])* array , $($rest:tt)*) => { ... };
(%impl1_static $(#[$i:meta])* $name:ident : $I:ty, $P:ty ; array) => { ... };
(%impls_static $name:ident : $I:ty, $P:ty ; $(#[$i:meta])* option , $($rest:tt)*) => { ... };
(%impl1_static $(#[$i:meta])* $name:ident : $I:ty, $P:ty ; option) => { ... };
(%impls_static $_name:ident : $_I:ty, $_P:ty ; $(#[$_i:meta])* $impl:ident , $($_r:tt)*) => { ... };
(%impl1_static $(#[$_i:meta])* $_name:ident : $_I:ty, $_P:ty ; $impl:ident) => { ... };
(%impl_common_static $name:ident, $I:ty, $P:ty) => { ... };
(%common_tracked $name:ident, $I:ty, $P:ty) => { ... };
(%common_static $name:ident, $I:ty, $P:ty) => { ... };
(%guard_index_repr $I:ty) => { ... };
}Expand description
๐๏ธ ๐๏ธ Defines a ring buffer type over contiguous storage backends.
๐ data/layout::buffer_ring
The generated type represents a fixed-capacity circular logical range over contiguous storage.
A ring tracks:
head: the physical start of the logical range.len: the number of live elements.
The tail is not stored. It is derived as (head + len) % capacity.
ยงImplemented backends
Currently implemented:
- static
arrayFully initialized array storage ([T; CAP]). All slots always contain a validT;lencontrols which slots are logically visible. - static
optionArray of options ([Option<T>; CAP]). Occupied logical slots areSome; unused physical slots areNone.
Reserved for later:
- static
uninit - view backends
- alloc backends
ยงIndex type requirements
The index type must:
- Be non-negative.
- Represent zero.
- Form a contiguous integer range.
- Be able to represent the full capacity.
Primitive unsigned integers and supported niche wrappers are accepted
through MaybeNiche.
ยงStorage backends
Backends are opt-in and selected after the struct declaration.
-
arrayFully initialized array storage ([T; CAP]).This backend separates initialization from logical membership: every physical slot stores a valid
T, whilelendetermines which elements are visible through the ring API.Operations that move values out of the array require either:
- copying (
*_copy), - an explicit replacement (
*_with), - or a convenience replacement (
*_default,*_init).
- copying (
-
optionArray of options ([Option<T>; CAP]).This backend stores occupancy explicitly: occupied logical slots are
Some(T), and unused physical slots areNone.It supports moving arbitrary
Tvalues in and out without requiring replacement values.
ยงExamples
use devela::buffer_ring;
buffer_ring!(
/// Static ring buffer.
pub struct RingU8: (u8);
array, option
);
let mut array_ring = RingU8::<i32, [i32; 4]>::new_init();
array_ring.push_back(10).unwrap();
array_ring.push_back(20).unwrap();
assert_eq!(array_ring.pop_front_copy(), Some(10));
assert_eq!(array_ring.peek_front(), Some(&20));
let mut option_ring = RingU8::<i32, [Option<i32>; 4]>::new_empty();
option_ring.push_back(10).unwrap();
option_ring.push_back(20).unwrap();
assert_eq!(option_ring.pop_front(), Some(10));
assert_eq!(option_ring.peek_front(), Some(&20));See also:
BufferRingStaticExample,