#![forbid(missing_docs)]
use std::collections::VecDeque;
pub trait Accountable {
fn record_count(&self) -> i64;
#[inline] fn is_empty(&self) -> bool { self.record_count() == 0 }
}
pub trait DrainContainer {
type Item<'a> where Self: 'a;
type DrainIter<'a>: Iterator<Item=Self::Item<'a>> where Self: 'a;
fn drain(&mut self) -> Self::DrainIter<'_>;
}
pub trait SizableContainer {
fn at_capacity(&self) -> bool;
fn ensure_capacity(&mut self, stash: &mut Option<Self>) where Self: Sized;
}
pub trait PushInto<T> {
fn push_into(&mut self, item: T);
}
pub trait ContainerBuilder: Default {
type Container;
#[must_use]
fn extract(&mut self) -> Option<&mut Self::Container>;
#[must_use]
fn finish(&mut self) -> Option<&mut Self::Container>;
#[inline]
fn relax(&mut self) { }
}
pub trait LengthPreservingContainerBuilder : ContainerBuilder { }
pub use noop::NoopBuilder;
mod noop {
pub struct NoopBuilder<C>{ phantom: std::marker::PhantomData<C> }
impl<C> Default for NoopBuilder<C> { fn default() -> Self { Self { phantom: std::marker::PhantomData } } }
impl<C> super::ContainerBuilder for NoopBuilder<C> {
type Container = C;
#[inline] fn extract(&mut self) -> Option<&mut C> { None }
#[inline] fn finish(&mut self) -> Option<&mut C> { None }
}
}
#[derive(Default, Debug)]
pub struct CapacityContainerBuilder<C>{
current: C,
empty: Option<C>,
pending: VecDeque<C>,
}
impl<T, C: SizableContainer + Default + PushInto<T>> PushInto<T> for CapacityContainerBuilder<C> {
#[inline]
fn push_into(&mut self, item: T) {
self.current.ensure_capacity(&mut self.empty);
self.current.push_into(item);
if self.current.at_capacity() {
self.pending.push_back(std::mem::take(&mut self.current));
}
}
}
impl<C: Accountable + Default> ContainerBuilder for CapacityContainerBuilder<C> {
type Container = C;
#[inline]
fn extract(&mut self) -> Option<&mut C> {
if let Some(container) = self.pending.pop_front() {
self.empty = Some(container);
self.empty.as_mut()
} else {
None
}
}
#[inline]
fn finish(&mut self) -> Option<&mut C> {
if !self.current.is_empty() {
self.pending.push_back(std::mem::take(&mut self.current));
}
self.empty = self.pending.pop_front();
self.empty.as_mut()
}
}
impl<C: Accountable + SizableContainer + Default> LengthPreservingContainerBuilder for CapacityContainerBuilder<C> { }
impl<T> Accountable for Vec<T> {
#[inline] fn record_count(&self) -> i64 { i64::try_from(Vec::len(self)).unwrap() }
#[inline] fn is_empty(&self) -> bool { Vec::is_empty(self) }
}
impl<T> DrainContainer for Vec<T> {
type Item<'a> = T where T: 'a;
type DrainIter<'a> = std::vec::Drain<'a, T> where Self: 'a;
#[inline] fn drain(&mut self) -> Self::DrainIter<'_> {
self.drain(..)
}
}
impl<T> SizableContainer for Vec<T> {
#[inline] fn at_capacity(&self) -> bool {
self.len() == self.capacity()
}
#[inline] fn ensure_capacity(&mut self, stash: &mut Option<Self>) {
if self.capacity() == 0 {
*self = stash.take().unwrap_or_default();
self.clear();
}
let preferred = buffer::default_capacity::<T>();
if self.capacity() < preferred {
self.reserve(preferred - self.capacity());
}
}
}
impl<T> PushInto<T> for Vec<T> {
#[inline]
fn push_into(&mut self, item: T) {
self.push(item)
}
}
impl<T: Clone> PushInto<&T> for Vec<T> {
#[inline]
fn push_into(&mut self, item: &T) {
self.push(item.clone())
}
}
impl<T: Clone> PushInto<&&T> for Vec<T> {
#[inline]
fn push_into(&mut self, item: &&T) {
self.push_into(*item)
}
}
mod rc {
impl<T: crate::Accountable> crate::Accountable for std::rc::Rc<T> {
#[inline] fn record_count(&self) -> i64 { self.as_ref().record_count() }
#[inline] fn is_empty(&self) -> bool { self.as_ref().is_empty() }
}
impl<T> crate::DrainContainer for std::rc::Rc<T>
where
for<'a> &'a T: IntoIterator
{
type Item<'a> = <&'a T as IntoIterator>::Item where Self: 'a;
type DrainIter<'a> = <&'a T as IntoIterator>::IntoIter where Self: 'a;
#[inline] fn drain(&mut self) -> Self::DrainIter<'_> { self.into_iter() }
}
}
mod arc {
impl<T: crate::Accountable> crate::Accountable for std::sync::Arc<T> {
#[inline] fn record_count(&self) -> i64 { self.as_ref().record_count() }
#[inline] fn is_empty(&self) -> bool { self.as_ref().is_empty() }
}
impl<T> crate::DrainContainer for std::sync::Arc<T>
where
for<'a> &'a T: IntoIterator
{
type Item<'a> = <&'a T as IntoIterator>::Item where Self: 'a;
type DrainIter<'a> = <&'a T as IntoIterator>::IntoIter where Self: 'a;
#[inline] fn drain(&mut self) -> Self::DrainIter<'_> { self.into_iter() }
}
}
pub mod buffer {
pub const BUFFER_SIZE_BYTES: usize = 1 << 13;
pub const fn default_capacity<T>() -> usize {
let size = std::mem::size_of::<T>();
if size == 0 {
BUFFER_SIZE_BYTES
} else if size <= BUFFER_SIZE_BYTES {
BUFFER_SIZE_BYTES / size
} else {
1
}
}
}