pub trait Buffer<T> {
const MAX_CAP: Option<usize>;
fn try_push(&mut self, val: T) -> Option<T>;
}
#[cfg(any(feature = "alloc", feature = "std"))]
#[cfg_attr(docsrs, doc(cfg(any(feature = "alloc", feature = "std"))))]
impl<T> Buffer<T> for std::vec::Vec<T> {
const MAX_CAP: Option<usize> = None;
#[inline]
fn try_push(&mut self, val: T) -> Option<T> {
std::vec::Vec::push(self, val);
None
}
}
impl<T, const N: usize> Buffer<T> for [Option<T>; N] {
const MAX_CAP: Option<usize> = Some(N);
fn try_push(&mut self, val: T) -> Option<T> {
for slot in self.iter_mut() {
if slot.is_none() {
*slot = Some(val);
return None;
}
}
Some(val)
}
}
impl<T> Buffer<T> for &mut [Option<T>] {
const MAX_CAP: Option<usize> = None;
fn try_push(&mut self, val: T) -> Option<T> {
for slot in self.iter_mut() {
if slot.is_none() {
*slot = Some(val);
return None;
}
}
Some(val)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn array_buffer_push_until_full() {
let mut buf: [Option<u32>; 3] = [const { None }; 3];
assert_eq!(buf.try_push(1), None);
assert_eq!(buf.try_push(2), None);
assert_eq!(buf.try_push(3), None);
assert_eq!(buf.try_push(4), Some(4));
assert_eq!(buf.try_push(5), Some(5));
assert_eq!(buf, [Some(1), Some(2), Some(3)]);
}
#[test]
fn slice_buffer_push_until_full() {
let mut underlying: [Option<&'static str>; 2] = [const { None }; 2];
let mut buf: &mut [Option<&str>] = &mut underlying;
assert_eq!(buf.try_push("a"), None);
assert_eq!(buf.try_push("b"), None);
assert_eq!(buf.try_push("c"), Some("c"));
assert_eq!(underlying, [Some("a"), Some("b")]);
}
#[cfg(any(feature = "alloc", feature = "std"))]
#[test]
fn vec_buffer_is_unbounded() {
use std::vec::Vec;
let mut buf: Vec<u32> = Vec::new();
for i in 0..1000 {
assert_eq!(buf.try_push(i), None);
}
assert_eq!(buf.len(), 1000);
assert_eq!(<Vec<u32> as Buffer<u32>>::MAX_CAP, None);
}
#[test]
fn max_cap_constants_are_correct() {
assert_eq!(<[Option<u32>; 8] as Buffer<u32>>::MAX_CAP, Some(8));
assert_eq!(<[Option<u32>; 0] as Buffer<u32>>::MAX_CAP, Some(0));
assert_eq!(<&mut [Option<u32>] as Buffer<u32>>::MAX_CAP, None);
}
}