use crate::buffer::{
reader::{self, storage::Chunk},
writer,
};
use bytes::buf::UninitSlice;
impl writer::Storage for super::Deque {
#[inline]
fn put_slice(&mut self, bytes: &[u8]) {
self.unfilled().put_slice(bytes);
unsafe {
self.fill(bytes.len()).unwrap();
}
}
#[inline]
fn put_uninit_slice<F, Error>(&mut self, payload_len: usize, f: F) -> Result<bool, Error>
where
F: FnOnce(&mut UninitSlice) -> Result<(), Error>,
{
let (mut head, _) = self.unfilled().into();
let did_write = head.put_uninit_slice(payload_len, f)?;
if did_write {
unsafe {
self.fill(payload_len).unwrap();
}
}
Ok(did_write)
}
#[inline]
fn remaining_capacity(&self) -> usize {
(*self).remaining_capacity()
}
}
impl reader::Storage for super::Deque {
type Error = core::convert::Infallible;
#[inline]
fn buffered_len(&self) -> usize {
self.len()
}
#[inline]
fn read_chunk(&mut self, watermark: usize) -> Result<Chunk<'_>, Self::Error> {
ensure!(watermark > 0 && !self.is_empty(), Ok(Chunk::default()));
let len = {
let (head, _) = self.filled().into();
debug_assert!(!head.is_empty());
head.len().min(watermark)
};
let (head, _) = self.consume_filled(len).into();
Ok(head[..].into())
}
#[inline]
fn partial_copy_into<Dest>(&mut self, dest: &mut Dest) -> Result<Chunk<'_>, Self::Error>
where
Dest: writer::Storage + ?Sized,
{
ensure!(
dest.has_remaining_capacity() && !self.is_empty(),
Ok(Chunk::default())
);
let len = self.len().min(dest.remaining_capacity());
let should_return_tail = {
let (head, _tail) = self.filled().into();
head.len() < len
};
let (head, tail) = self.consume_filled(len).into();
if should_return_tail {
dest.put_slice(head);
Ok(tail[..].into())
} else {
Ok(head[..].into())
}
}
#[inline]
fn copy_into<Dest>(&mut self, dest: &mut Dest) -> Result<(), Self::Error>
where
Dest: writer::Storage + ?Sized,
{
ensure!(dest.has_remaining_capacity() && !self.is_empty(), Ok(()));
let len = self.len().min(dest.remaining_capacity());
self.consume_filled(len).copy_into(dest)
}
}
#[cfg(test)]
mod tests {
use super::{
super::Deque,
reader::{storage::Infallible as _, Reader},
writer::Storage as _,
};
use crate::stream::testing::Data;
use bolero::{check, TypeGenerator};
#[test]
fn storage_test() {
let cap = 16;
let mut buffer = Deque::new(cap);
assert_eq!(buffer.remaining_capacity(), cap);
buffer.put_slice(b"hello");
buffer.put_slice(b" ");
buffer.put_slice(b"world");
let chunk = buffer.infallible_read_chunk(7);
assert_eq!(&chunk[..], b"hello w");
let chunk = buffer.infallible_read_chunk(3);
assert_eq!(&chunk[..], b"orl");
buffer.put_slice(&[42u8; 15]);
let mut out: Vec<u8> = vec![];
let chunk = buffer.infallible_partial_copy_into(&mut out);
assert_eq!(&out[..], &[b'd', 42, 42, 42, 42, 42]);
assert_eq!(&chunk[..], &[42u8; 10]);
}
#[derive(Clone, Copy, Debug, TypeGenerator)]
enum Op {
Put { len: u16 },
ReadChunk { watermark: u16 },
PartialCopy { watermark: u16 },
FullCopy { watermark: u16 },
}
#[derive(Debug)]
struct Model {
buffer: Deque,
send: Data,
recv: Data,
}
impl Default for Model {
fn default() -> Self {
Self {
buffer: Deque::new(u8::MAX as _),
send: Data::new(usize::MAX as _),
recv: Data::new(usize::MAX as _),
}
}
}
impl Model {
fn apply_all(&mut self, ops: &[Op]) {
for op in ops {
self.apply(op);
}
while !self.buffer.is_empty() {
self.apply(&Op::FullCopy {
watermark: u16::MAX,
});
}
}
fn apply(&mut self, op: &Op) {
match *op {
Op::Put { len } => {
let mut stream = self.send.with_read_limit(len as _);
stream.infallible_copy_into(&mut self.buffer);
}
Op::ReadChunk { watermark } => {
let chunk = self.buffer.infallible_read_chunk(watermark as _);
self.recv.receive(&[chunk]);
}
Op::PartialCopy { watermark } => {
let mut recv = self.recv.with_write_limit(watermark as _);
let chunk = self.buffer.infallible_partial_copy_into(&mut recv);
self.recv.receive(&[chunk]);
}
Op::FullCopy { watermark } => {
let mut recv = self.recv.with_write_limit(watermark as _);
self.buffer.infallible_copy_into(&mut recv);
}
}
}
}
#[test]
fn model_test() {
check!()
.with_type::<Vec<Op>>()
.for_each(|ops| Model::default().apply_all(ops))
}
}