use std::collections::VecDeque;
#[ derive( Debug, Clone, PartialEq, Eq ) ]
pub enum BufferStrategy
{
Vector,
Circular,
Chunked {
chunk_size : usize
},
}
pub( crate ) enum StreamBuffer< T >
{
Vector( Vec< Result< T, crate::error::Error > > ),
Circular( VecDeque< Result< T, crate::error::Error > > ),
Chunked {
chunks : Vec< Vec< Result< T, crate::error::Error > > >,
current_chunk : Vec< Result< T, crate::error::Error > >,
chunk_size : usize
},
}
impl< T > StreamBuffer< T >
{
pub fn new( strategy : &BufferStrategy, _chunk_size : Option< usize > ) -> Self
{
match strategy
{
BufferStrategy::Vector => Self::Vector( Vec::new() ),
BufferStrategy::Circular => Self::Circular( VecDeque::new() ),
BufferStrategy::Chunked { chunk_size } => Self::Chunked {
chunks : Vec::new(),
current_chunk : Vec::new(),
chunk_size : *chunk_size,
},
}
}
pub fn push( &mut self, item : Result< T, crate::error::Error > )
{
match self
{
Self::Vector( vec ) => vec.push( item ),
Self::Circular( deque ) => deque.push_back( item ),
Self::Chunked { chunks, current_chunk, chunk_size } => {
if current_chunk.len() >= *chunk_size
{
let mut new_chunk = Vec::new();
std ::mem::swap( current_chunk, &mut new_chunk );
chunks.push( new_chunk );
current_chunk.clear();
}
current_chunk.push( item );
},
}
}
pub fn drain_all( &mut self ) -> Vec< Result< T, crate::error::Error > >
{
match self
{
Self::Vector( vec ) => vec.drain( .. ).collect(),
Self::Circular( deque ) => deque.drain( .. ).collect(),
Self::Chunked { chunks, current_chunk, .. } => {
let mut all_items = Vec::new();
for chunk in chunks.drain( .. )
{
all_items.extend( chunk );
}
all_items.extend( current_chunk.drain( .. ) );
all_items
},
}
}
pub fn len( &self ) -> usize
{
match self
{
Self::Vector( vec ) => vec.len(),
Self::Circular( deque ) => deque.len(),
Self::Chunked { chunks, current_chunk, .. } => {
chunks.iter().map( |c| c.len() ).sum::< usize >() + current_chunk.len()
},
}
}
#[ allow( dead_code ) ]
pub fn is_empty( &self ) -> bool
{
self.len() == 0
}
}