#[cfg(feature = "alloc")]
use alloc::{boxed::Box, vec::Vec};
use core::cmp::min;
mod contiguous;
pub use contiguous::*;
#[cfg(feature = "alloc")]
mod unbounded;
#[cfg(feature = "alloc")]
pub use unbounded::*;
#[cfg(feature = "alloc")]
mod elastic;
#[cfg(feature = "alloc")]
pub use elastic::*;
#[cfg(feature = "alloc")]
mod unbounded_elastic;
#[cfg(feature = "alloc")]
pub use unbounded_elastic::*;
#[cfg(feature = "alloc")]
mod fault_tolerant_elastic;
#[cfg(feature = "alloc")]
pub use fault_tolerant_elastic::*;
#[cfg(feature = "dev")]
pub mod dev;
pub trait Queue {
type Item;
fn len(&self) -> usize;
fn is_empty(&self) -> bool {
self.len() == 0
}
fn is_full(&self) -> bool;
fn max_capacity(&self) -> Option<usize>;
fn enqueue(&mut self, item: Self::Item) -> Option<Self::Item>;
async fn expose_slots<F, R>(&mut self, f: F) -> R
where
F: AsyncFnOnce(&mut [Self::Item]) -> (usize, R);
fn dequeue(&mut self) -> Option<Self::Item>;
async fn expose_items<F, R>(&mut self, f: F) -> R
where
F: AsyncFnOnce(&[Self::Item]) -> (usize, R);
}
pub trait BoundedQueue: Queue {
fn bounded_capacity(&self) -> usize {
self.max_capacity()
.expect("A bounded queue must not report None as its max_capacity()")
}
fn available_slots(&self) -> usize {
self.bounded_capacity() - self.len()
}
}
pub trait QueueExt: Queue {
async fn bulk_enqueue(&mut self, buffer: &[Self::Item]) -> usize
where
Self::Item: Clone,
{
self.expose_slots(async |slots| {
let amount = min(slots.len(), buffer.len());
slots[..amount].clone_from_slice(&buffer[..amount]);
(amount, amount)
})
.await
}
async fn bulk_dequeue(&mut self, buffer: &mut [Self::Item]) -> usize
where
Self::Item: Clone,
{
self.expose_items(async |items| {
let amount = min(items.len(), buffer.len());
buffer[..amount].clone_from_slice(&items[..amount]);
(amount, amount)
})
.await
}
}
impl<Q> QueueExt for Q where Q: Queue {}
pub fn new_contiguous<S, T>(buffer: S) -> Contiguous<S, T>
where
T: Default,
{
Contiguous::new(buffer, Default::default)
}
pub fn new_contiguous_with<S, T>(buffer: S, initialise_memory: fn() -> T) -> Contiguous<S, T> {
Contiguous::new(buffer, initialise_memory)
}
pub fn new_static<T, const N: usize>() -> Contiguous<[T; N], T>
where
T: Default,
{
Contiguous::new(core::array::from_fn(|_| T::default()), T::default)
}
pub fn new_static_with<T, const N: usize>(initialise_memory: fn() -> T) -> Contiguous<[T; N], T> {
Contiguous::new(
core::array::from_fn(|_| initialise_memory()),
initialise_memory,
)
}
#[cfg(feature = "alloc")]
pub fn new_fixed<T>(capacity: usize) -> Contiguous<Box<[T]>, T>
where
T: Default,
{
let mut v = Vec::with_capacity(capacity);
v.resize_with(capacity, Default::default);
Contiguous::new(v.into_boxed_slice(), T::default)
}
#[cfg(feature = "alloc")]
pub fn new_fixed_with<T>(capacity: usize, initialise_memory: fn() -> T) -> Contiguous<Box<[T]>, T> {
let mut v = Vec::with_capacity(capacity);
v.resize_with(capacity, initialise_memory);
Contiguous::new(v.into_boxed_slice(), initialise_memory)
}
#[cfg(feature = "alloc")]
pub fn new_unbounded<T>() -> Unbounded<T>
where
T: Default,
{
Unbounded::new(T::default)
}
#[cfg(feature = "alloc")]
pub fn new_unbounded_with<T>(initialise_memory: fn() -> T) -> Unbounded<T> {
Unbounded::new(initialise_memory)
}
#[cfg(feature = "alloc")]
pub fn new_elastic<T>(minimum_capacity: usize, maximum_capacity: usize) -> Elastic<T>
where
T: Default,
{
Elastic::new(minimum_capacity, maximum_capacity, Default::default)
}
#[cfg(feature = "alloc")]
pub fn new_elastic_with<T>(
minimum_capacity: usize,
maximum_capacity: usize,
initialise_memory: fn() -> T,
) -> Elastic<T> {
Elastic::new(minimum_capacity, maximum_capacity, initialise_memory)
}
#[cfg(feature = "alloc")]
pub fn new_unbounded_elastic<T>() -> UnboundedElastic<T>
where
T: Default,
{
UnboundedElastic::new(Default::default)
}
#[cfg(feature = "alloc")]
pub fn new_unbounded_elastic_with<T>(initialise_memory: fn() -> T) -> UnboundedElastic<T> {
UnboundedElastic::new(initialise_memory)
}
#[cfg(feature = "alloc")]
pub fn new_fault_tolerant_elastic<T>(
minimum_capacity: usize,
maximum_capacity: usize,
) -> FaultTolerantElastic<T>
where
T: Default,
{
FaultTolerantElastic::new(minimum_capacity, maximum_capacity, Default::default)
}
#[cfg(feature = "alloc")]
pub fn new_fault_tolerant_elastic_with<T>(
minimum_capacity: usize,
maximum_capacity: usize,
initialise_memory: fn() -> T,
) -> FaultTolerantElastic<T> {
FaultTolerantElastic::new(minimum_capacity, maximum_capacity, initialise_memory)
}