use alloc::collections::VecDeque;
use bytes::{Buf as _, Bytes};
macro_rules! count_chunk {
($self: ident) => {
if !$self.chunk_counted {
$self.num_chunks_read += 1;
$self.chunk_counted = true;
}
};
}
pub struct ChunkedBytesInput {
chunks: VecDeque<Bytes>,
position: usize,
num_chunks_read: usize,
chunk_counted: bool,
}
impl ChunkedBytesInput {
pub fn new(chunks: VecDeque<Bytes>) -> Self {
Self { chunks, position: 0, num_chunks_read: 0, chunk_counted: false }
}
pub fn num_chunks_read(&self) -> usize {
self.num_chunks_read
}
pub fn position(&self) -> usize {
self.position
}
pub fn peek_within_chunk_skipping_empty_chunks(&mut self) -> Option<Bytes> {
while let Some(chunk) = self.chunks.front_mut() {
count_chunk!(self);
if chunk.is_empty() {
self.chunks.pop_front();
self.chunk_counted = false;
continue;
}
return Some(chunk.clone());
}
None
}
pub fn read_within_chunk_skipping_empty_chunks(&mut self, length: usize) -> Option<Bytes> {
while let Some(chunk) = self.chunks.front_mut() {
count_chunk!(self);
if chunk.is_empty() {
self.chunks.pop_front();
self.chunk_counted = false;
continue;
}
let n = length.min(chunk.len());
self.position += n;
return Some(chunk.split_to(n));
}
None
}
}
impl codec::Input for ChunkedBytesInput {
fn remaining_len(&mut self) -> Result<Option<usize>, codec::Error> {
Ok(None)
}
fn read(&mut self, mut buf: &mut [u8]) -> Result<(), codec::Error> {
if buf.is_empty() {
return Ok(());
}
while let Some(chunk) = self.chunks.front_mut() {
count_chunk!(self);
if chunk.is_empty() {
self.chunks.pop_front();
self.chunk_counted = false;
continue;
}
let n = buf.len().min(chunk.len());
let (part, rest) = buf.split_at_mut(n);
part.copy_from_slice(&chunk[..n]);
buf = rest;
self.position += n;
chunk.advance(n);
if buf.is_empty() {
return Ok(());
}
}
if !buf.is_empty() {
return Err("Buffer overflow".into());
}
Ok(())
}
}
pub struct ChunkedVecDequeBytes {
chunks: VecDeque<VecDeque<Bytes>>,
num_chunks_read: usize,
chunk_counted: bool,
}
impl ChunkedVecDequeBytes {
pub fn new(chunks: VecDeque<VecDeque<Bytes>>) -> Self {
Self { chunks, num_chunks_read: 0, chunk_counted: false }
}
pub fn num_chunks_read(&self) -> usize {
self.num_chunks_read
}
pub fn peek_front_skipping_empty_chunks(&mut self) -> Option<Bytes> {
self.pop_empty_chunks();
match self.chunks.front_mut() {
Some(chunk) => {
count_chunk!(self);
chunk.front().cloned()
},
None => None,
}
}
pub fn pop_front_skipping_empty_chunks(&mut self) -> Option<Bytes> {
self.pop_empty_chunks();
match self.chunks.front_mut() {
Some(chunk) => {
count_chunk!(self);
chunk.pop_front()
},
None => None,
}
}
fn pop_empty_chunks(&mut self) {
while let Some(chunk) = self.chunks.front() {
count_chunk!(self);
if !chunk.is_empty() {
break;
}
self.chunks.pop_front();
self.chunk_counted = false;
}
}
}