use core::fmt::Debug;
use alloc::vec::Vec;
use crate::prelude::*;
#[derive(Clone)]
pub struct IntoConsumer<T>(Vec<T>, usize);
impl<T> From<IntoConsumer<T>> for Vec<T> {
fn from(value: IntoConsumer<T>) -> Self {
let (mut v, len) = (value.0, value.1);
v.truncate(len);
v
}
}
impl<T> Debug for IntoConsumer<T>
where
T: Debug,
{
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_tuple("IntoConsumer")
.field(&&self.0[..self.1])
.finish()
}
}
impl<T> IntoConsumer<T> {
pub fn as_slice(&self) -> &[T] {
&self.0[..self.1]
}
pub fn as_mut_slice(&mut self) -> &mut [T] {
&mut self.0[..self.1]
}
pub fn prepare_slots(&mut self, amount: usize)
where
T: Default,
{
let old_len = self.0.len();
self.0.resize_with(old_len + amount, Default::default);
}
}
impl<T> Consumer for IntoConsumer<T> {
type Item = T;
type Final = Infallible;
type Error = Infallible;
async fn consume(&mut self, val: Either<Self::Item, Self::Final>) -> Result<(), Self::Error> {
match val {
Left(item) => {
if self.0.len() == self.1 {
self.0.push(item);
} else {
debug_assert!(self.0.len() > self.1);
self.0[self.1] = item;
}
self.1 += 1;
Ok(())
}
Right(_fin) => unreachable!(),
}
}
async fn flush(&mut self) -> Result<(), Self::Error> {
Ok(())
}
}
impl<T: Default> BulkConsumer for IntoConsumer<T> {
async fn expose_slots_gracefully<F, R>(&mut self, f: F) -> Result<R, (F, Self::Error)>
where
F: AsyncFnOnce(&mut [Self::Item]) -> (usize, R),
{
let len = self.0.len() - self.1;
if len == 0 {
let new_len = self.1 * 2 + 1;
self.0.resize_with(new_len, Default::default);
}
let (amount, ret) = f(&mut self.0[self.1..]).await;
self.1 += amount;
Ok(ret)
}
}
impl<T> crate::IntoConsumer for Vec<T> {
type Item = T;
type Final = Infallible;
type Error = Infallible;
type IntoConsumer = IntoConsumer<T>;
fn into_consumer(self) -> Self::IntoConsumer {
let len = self.len();
IntoConsumer(self, len)
}
}
pub struct IntoConsumerMut<'a, T>(&'a mut Vec<T>, usize);
impl<'a, T> Debug for IntoConsumerMut<'a, T>
where
T: Debug,
{
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_tuple("IntoConsumerMut")
.field(&&self.0[..self.1])
.finish()
}
}
impl<'a, T> Consumer for IntoConsumerMut<'a, T> {
type Item = T;
type Final = Infallible;
type Error = Infallible;
async fn consume(&mut self, val: Either<Self::Item, Self::Final>) -> Result<(), Self::Error> {
match val {
Left(item) => {
if self.0.len() == self.1 {
self.0.push(item);
} else {
debug_assert!(self.0.len() > self.1);
self.0[self.1] = item;
}
self.1 += 1;
Ok(())
}
Right(_fin) => unreachable!(),
}
}
async fn flush(&mut self) -> Result<(), Self::Error> {
Ok(())
}
}
impl<'a, T: Default> BulkConsumer for IntoConsumerMut<'a, T> {
async fn expose_slots_gracefully<F, R>(&mut self, f: F) -> Result<R, (F, Self::Error)>
where
F: AsyncFnOnce(&mut [Self::Item]) -> (usize, R),
{
let len = self.0.len() - self.1;
if len == 0 {
let new_len = self.1 * 2 + 1;
self.0.resize_with(new_len, Default::default);
}
let (amount, ret) = f(&mut self.0[self.1..]).await;
self.1 += amount;
Ok(ret)
}
}
impl<'a, T> crate::IntoConsumer for &'a mut Vec<T> {
type Item = T;
type Final = Infallible;
type Error = Infallible;
type IntoConsumer = IntoConsumerMut<'a, T>;
fn into_consumer(self) -> Self::IntoConsumer {
IntoConsumerMut(self, 0)
}
}