use std::cell::RefCell;
use std::io::{BufRead, BufReader, BufWriter, Cursor, IoSlice, IoSliceMut, Read, Result, Write};
use foundation_nostd::comp::basic::{Mutex, RwLock};
use std::rc::Rc;
use std::sync::atomic::AtomicPtr;
use std::sync::Arc;
use crate::err;
use derive_more::derive::From;
pub trait ReadTimeoutOperations: Read {
fn read_timeout_into(
&mut self,
buf: &mut [u8],
timeout: std::time::Duration,
) -> std::result::Result<usize, std::io::Error>;
fn set_read_timeout_as(
&mut self,
timeout: std::time::Duration,
) -> std::result::Result<(), std::io::Error>;
fn get_current_read_timeout(
&self,
) -> std::result::Result<Option<std::time::Duration>, std::io::Error>;
}
pub trait BufferCapacity {
fn read_buffer(&self) -> &[u8];
fn read_capacity(&self) -> usize;
fn buffer_length(&self) -> usize {
self.read_buffer().len()
}
}
pub struct BufferedReader<T: ?Sized> {
inner: BufReader<T>,
}
impl<T: Read> BufferedReader<T> {
pub fn with_capacity(capacity: usize, inner: T) -> Self {
Self {
inner: BufReader::with_capacity(capacity, inner),
}
}
pub fn new(inner: T) -> Self {
Self {
inner: BufReader::new(inner),
}
}
}
impl<T: Read + Write> BufferedReader<BufferedWriter<T>> {
pub fn get_core_ref(&self) -> &T {
self.inner.get_ref().get_inner_ref()
}
pub fn get_core_mut(&mut self) -> &mut T {
self.inner.get_mut().get_inner_mut()
}
}
impl<T: ReadTimeoutOperations> ReadTimeoutOperations for BufferedReader<T> {
fn read_timeout_into(
&mut self,
buf: &mut [u8],
timeout: std::time::Duration,
) -> std::result::Result<usize, std::io::Error> {
self.inner.get_mut().read_timeout_into(buf, timeout)
}
fn set_read_timeout_as(
&mut self,
timeout: std::time::Duration,
) -> std::result::Result<(), std::io::Error> {
self.inner.get_mut().set_read_timeout_as(timeout)
}
fn get_current_read_timeout(
&self,
) -> std::result::Result<Option<std::time::Duration>, std::io::Error> {
self.inner.get_ref().get_current_read_timeout()
}
}
impl<T: Read> BufferedReader<T> {
pub fn get_ref(&self) -> &BufReader<T> {
&self.inner
}
pub fn get_mut(&mut self) -> &mut BufReader<T> {
&mut self.inner
}
pub fn get_inner_ref(&self) -> &T {
self.inner.get_ref()
}
pub fn get_inner_mut(&mut self) -> &mut T {
self.inner.get_mut()
}
pub fn capacity(&mut self) -> usize {
self.inner.capacity()
}
pub fn buffer(&self) -> &[u8] {
self.inner.buffer()
}
pub fn buffer_len(&self) -> usize {
self.inner.buffer().len()
}
pub fn consume(&mut self, amount: usize) {
self.inner.consume(amount);
}
}
impl<T: BufferCapacity> BufferCapacity for BufferedReader<T> {
fn read_buffer(&self) -> &[u8] {
self.inner.buffer()
}
fn read_capacity(&self) -> usize {
self.inner.capacity()
}
}
impl<T: Read + ?Sized> BufRead for BufferedReader<T> {
fn fill_buf(&mut self) -> Result<&[u8]> {
self.inner.fill_buf()
}
fn consume(&mut self, amt: usize) {
self.inner.consume(amt);
}
}
impl<T: Read + ?Sized> Read for BufferedReader<T> {
fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
self.inner.read(buf)
}
fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> Result<usize> {
self.inner.read_vectored(bufs)
}
fn read_exact(&mut self, buf: &mut [u8]) -> Result<()> {
self.inner.read_exact(buf)
}
fn read_to_end(&mut self, buf: &mut Vec<u8>) -> Result<usize> {
self.inner.read_to_end(buf)
}
fn read_to_string(&mut self, buf: &mut String) -> Result<usize> {
self.inner.read_to_string(buf)
}
}
impl<T: Write + ?Sized> Write for BufferedReader<T> {
fn write(&mut self, buf: &[u8]) -> Result<usize> {
self.inner.get_mut().write(buf)
}
fn write_all(&mut self, buf: &[u8]) -> Result<()> {
self.inner.get_mut().write_all(buf)
}
fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> Result<usize> {
self.inner.get_mut().write_vectored(bufs)
}
fn flush(&mut self) -> Result<()> {
self.inner.get_mut().flush()
}
}
#[cfg(test)]
mod buffered_reader_tests {
use super::*;
#[test]
fn can_buffered_reader_peek() {
let content = b"alexander_wonderbat";
let mut reader = BufferedReader::new(&content[..]);
let mut content_to_read = vec![0; 5];
reader
.peek(&mut content_to_read)
.expect("should read data correctly");
assert_eq!(b"alexa", &content_to_read[..]);
assert_eq!(content, reader.buffer());
}
}
pub struct BufferedWriter<T: ?Sized + Write> {
inner: BufWriter<T>,
}
impl<T: Write> BufferedWriter<T> {
pub fn new(inner: T) -> Self {
Self {
inner: BufWriter::new(inner),
}
}
pub fn with_capacity(capacity: usize, inner: T) -> Self {
Self {
inner: BufWriter::with_capacity(capacity, inner),
}
}
}
impl<T: ReadTimeoutOperations + Write> ReadTimeoutOperations for BufferedWriter<T> {
fn read_timeout_into(
&mut self,
buf: &mut [u8],
timeout: std::time::Duration,
) -> std::result::Result<usize, std::io::Error> {
self.inner.get_mut().read_timeout_into(buf, timeout)
}
fn set_read_timeout_as(
&mut self,
timeout: std::time::Duration,
) -> std::result::Result<(), std::io::Error> {
self.inner.get_mut().set_read_timeout_as(timeout)
}
fn get_current_read_timeout(
&self,
) -> std::result::Result<Option<std::time::Duration>, std::io::Error> {
self.inner.get_ref().get_current_read_timeout()
}
}
impl<T: Read + Write + BufferCapacity> BufferedWriter<T> {
pub fn read_capacity(&mut self) -> usize {
self.inner.get_ref().read_capacity()
}
pub fn read_buffer(&self) -> &[u8] {
self.inner.get_ref().read_buffer()
}
}
impl<T: Read + Write> BufferedWriter<BufferedReader<T>> {
pub fn get_core_ref(&self) -> &T {
self.inner.get_ref().get_inner_ref()
}
pub fn get_core_mut(&mut self) -> &mut T {
self.inner.get_mut().get_inner_mut()
}
}
impl<T: Write> BufferedWriter<T> {
pub fn get_ref(&self) -> &BufWriter<T> {
&self.inner
}
pub fn get_mut(&mut self) -> &mut BufWriter<T> {
&mut self.inner
}
pub fn get_inner_ref(&self) -> &T {
self.inner.get_ref()
}
pub fn get_inner_mut(&mut self) -> &mut T {
self.inner.get_mut()
}
pub fn capacity(&mut self) -> usize {
self.inner.capacity()
}
pub fn buffer(&self) -> &[u8] {
self.inner.buffer()
}
}
impl<T: Write + ?Sized> Write for BufferedWriter<T> {
fn write(&mut self, buf: &[u8]) -> Result<usize> {
self.inner.write(buf)
}
fn write_all(&mut self, buf: &[u8]) -> Result<()> {
self.inner.write_all(buf)
}
fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> Result<usize> {
self.inner.write_vectored(bufs)
}
fn flush(&mut self) -> Result<()> {
self.inner.flush()
}
}
impl<T: Write + Read + ?Sized> Read for BufferedWriter<T> {
fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
self.inner.get_mut().read(buf)
}
fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> Result<usize> {
self.inner.get_mut().read_vectored(bufs)
}
fn read_exact(&mut self, buf: &mut [u8]) -> Result<()> {
self.inner.get_mut().read_exact(buf)
}
fn read_to_end(&mut self, buf: &mut Vec<u8>) -> Result<usize> {
self.inner.get_mut().read_to_end(buf)
}
fn read_to_string(&mut self, buf: &mut String) -> Result<usize> {
self.inner.get_mut().read_to_string(buf)
}
}
impl<T: Write + BufRead + ?Sized> BufRead for BufferedWriter<T> {
fn fill_buf(&mut self) -> Result<&[u8]> {
self.inner.get_mut().fill_buf()
}
fn consume(&mut self, amt: usize) {
self.inner.get_mut().consume(amt);
}
}
impl<T: Write + BufRead + BufferCapacity> PeekableReadStream for BufferedWriter<T> {
fn peek(&mut self, buf: &mut [u8]) -> std::result::Result<usize, PeekError> {
if buf.len() > self.get_inner_ref().read_capacity() {
return Err(PeekError::BiggerThanCapacity {
requested: buf.len(),
buffer_capacity: self.get_inner_ref().read_capacity(),
});
}
let mut last_len = 0;
while self.read_buffer().len() < buf.len() {
self.inner.get_mut().fill_buf()?;
let current_len = self.get_inner_ref().read_buffer().len();
if last_len == current_len {
break;
}
last_len = current_len;
}
let buffer = self.get_inner_ref().read_buffer();
let ending = if buffer.len() < buf.len() {
buffer.len()
} else {
buf.len()
};
for (index, elem) in buffer[0..ending].iter().enumerate() {
buf[index] = *elem;
}
Ok(ending)
}
}
pub type BufferedStream<T> = BufferedWriter<BufferedReader<T>>;
pub fn buffered_stream<T: Write + Read>(inner: T) -> BufferedStream<T> {
BufferedWriter::new(BufferedReader::new(inner))
}
pub fn buffered_stream_with_capacity<T: Write + Read>(
capacity: usize,
inner: T,
) -> BufferedStream<T> {
BufferedWriter::with_capacity(capacity, BufferedReader::with_capacity(capacity, inner))
}
#[derive(From, Debug)]
pub enum PeekError {
ZeroLengthNotAllowed,
NotSupported,
LockAcquisitionError,
BiggerThanCapacity {
requested: usize,
buffer_capacity: usize,
},
IOError(std::io::Error),
}
impl std::error::Error for PeekError {}
impl core::fmt::Display for PeekError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{self:?}")
}
}
pub trait PeekableReadStream: Read {
fn peek(&mut self, buf: &mut [u8]) -> std::result::Result<usize, PeekError>;
}
pub trait SplitReadStream: Read + Sized {
fn split_connection(&self) -> std::io::Result<Self>;
}
impl<T: Read> PeekableReadStream for BufferedReader<T> {
fn peek(&mut self, buf: &mut [u8]) -> std::result::Result<usize, PeekError> {
if buf.len() > self.inner.capacity() {
return Err(PeekError::BiggerThanCapacity {
requested: buf.len(),
buffer_capacity: self.inner.capacity(),
});
}
let mut last_len = 0;
while self.inner.buffer().len() < buf.len() {
self.inner.fill_buf()?;
let current_len = self.inner.buffer().len();
if last_len == current_len {
break;
}
last_len = current_len;
}
let buffer = self.inner.buffer();
let ending = if buffer.len() < buf.len() {
buffer.len()
} else {
buf.len()
};
for (index, elem) in buffer[0..ending].iter().enumerate() {
buf[index] = *elem;
}
Ok(ending)
}
}
pub enum OwnedReader<T: Read> {
RefCell(Rc<RefCell<T>>),
Atomic(Arc<AtomicPtr<T>>),
Sync(Arc<Mutex<T>>),
RWrite(Arc<RwLock<T>>),
}
impl<T: Read> OwnedReader<T> {
pub fn rwrite(reader: Arc<RwLock<T>>) -> Self {
Self::RWrite(reader)
}
pub fn sync(reader: Arc<Mutex<T>>) -> Self {
Self::Sync(reader)
}
pub fn atomic(reader: &mut T) -> Self {
Self::Atomic(Arc::new(AtomicPtr::new(reader)))
}
pub fn ref_cell(reader: Rc<RefCell<T>>) -> Self {
Self::RefCell(reader)
}
}
impl<T: Read> OwnedReader<T> {
pub fn do_ref<F, V>(&self, caller: F) -> V
where
F: Fn(&T) -> V,
{
match self {
Self::Atomic(core) => {
let ptr = core.load(std::sync::atomic::Ordering::Acquire);
unsafe {
let atomic_reader: &mut T = &mut *ptr;
(caller)(atomic_reader)
}
}
Self::Sync(core) => {
let guard = core.lock().expect("can acquire");
(caller)(&guard)
}
Self::RWrite(core) => {
let guard = core.read().expect("can acquire");
(caller)(&guard)
}
Self::RefCell(core) => {
let guard = core.borrow();
(caller)(&guard)
}
}
}
pub fn do_once<F, V>(&self, caller: F) -> V
where
F: FnOnce(&T) -> V,
{
match self {
Self::Atomic(core) => {
let ptr = core.load(std::sync::atomic::Ordering::Acquire);
unsafe {
let atomic_reader: &mut T = &mut *ptr;
(caller)(atomic_reader)
}
}
Self::Sync(core) => {
let guard = core.lock().expect("can acquire");
(caller)(&guard)
}
Self::RWrite(core) => {
let guard = core.read().expect("can acquire");
(caller)(&guard)
}
Self::RefCell(core) => {
let guard = core.borrow();
(caller)(&guard)
}
}
}
pub fn do_once_mut<F, V>(&self, caller: F) -> V
where
F: FnOnce(&mut T) -> V,
{
match self {
Self::Atomic(core) => {
let ptr = core.load(std::sync::atomic::Ordering::Acquire);
unsafe {
let atomic_reader: &mut T = &mut *ptr;
(caller)(atomic_reader)
}
}
Self::Sync(core) => {
let mut guard = core.lock().expect("can acquire");
(caller)(&mut *guard)
}
Self::RWrite(core) => {
let mut guard = core.write().expect("can acquire");
(caller)(&mut *guard)
}
Self::RefCell(core) => {
let mut guard = core.borrow_mut();
(caller)(&mut *guard)
}
}
}
pub fn do_mut<F, V>(&self, mut caller: F) -> V
where
F: FnMut(&mut T) -> V,
{
match self {
Self::Atomic(core) => {
let ptr = core.load(std::sync::atomic::Ordering::Acquire);
unsafe {
let atomic_reader: &mut T = &mut *ptr;
(caller)(atomic_reader)
}
}
Self::Sync(core) => {
let mut guard = core.lock().expect("can acquire");
(caller)(&mut guard)
}
Self::RWrite(core) => {
let mut guard = core.write().expect("can acquire");
(caller)(&mut guard)
}
Self::RefCell(core) => {
let mut guard = core.borrow_mut();
(caller)(&mut guard)
}
}
}
}
impl<T: Read> Clone for OwnedReader<T> {
fn clone(&self) -> Self {
match self {
Self::Atomic(core) => Self::Atomic(Arc::clone(core)),
Self::RWrite(core) => Self::RWrite(Arc::clone(core)),
Self::RefCell(core) => Self::RefCell(core.clone()),
Self::Sync(core) => Self::Sync(core.clone()),
}
}
}
impl<T: Read + Write> Write for OwnedReader<T> {
fn write(&mut self, buf: &[u8]) -> Result<usize> {
match self {
Self::Atomic(core) => {
let ptr = core.load(std::sync::atomic::Ordering::Acquire);
unsafe {
let atomic_reader: &mut T = &mut *ptr;
atomic_reader.write(buf)
}
}
Self::Sync(core) => {
let mut guard = core.lock().expect("can acquire");
guard.write(buf)
}
Self::RWrite(core) => {
let mut guard = core.write().expect("can acquire");
guard.write(buf)
}
Self::RefCell(core) => {
let mut guard = core.borrow_mut();
guard.write(buf)
}
}
}
fn flush(&mut self) -> Result<()> {
match self {
Self::Atomic(core) => {
let ptr = core.load(std::sync::atomic::Ordering::Acquire);
unsafe {
let atomic_reader: &mut T = &mut *ptr;
atomic_reader.flush()
}
}
Self::Sync(core) => {
let mut guard = core.lock().expect("can acquire");
guard.flush()
}
Self::RWrite(core) => {
let mut guard = core.write().expect("can acquire");
guard.flush()
}
Self::RefCell(core) => {
let mut guard = core.borrow_mut();
guard.flush()
}
}
}
}
impl<T: ReadTimeoutOperations> ReadTimeoutOperations for OwnedReader<T> {
fn read_timeout_into(
&mut self,
buf: &mut [u8],
timeout: std::time::Duration,
) -> std::result::Result<usize, std::io::Error> {
match self {
Self::Atomic(core) => {
let ptr = core.load(std::sync::atomic::Ordering::Acquire);
unsafe {
let atomic_reader: &mut T = &mut *ptr;
atomic_reader.read_timeout_into(buf, timeout)
}
}
Self::Sync(core) => {
let mut guard = core.lock().expect("can acquire");
guard.read_timeout_into(buf, timeout)
}
Self::RWrite(core) => {
let mut guard = core.write().expect("can acquire");
guard.read_timeout_into(buf, timeout)
}
Self::RefCell(core) => {
let mut guard = core.borrow_mut();
guard.read_timeout_into(buf, timeout)
}
}
}
fn set_read_timeout_as(
&mut self,
timeout: std::time::Duration,
) -> std::result::Result<(), std::io::Error> {
match self {
Self::Atomic(core) => {
let ptr = core.load(std::sync::atomic::Ordering::Acquire);
unsafe {
let atomic_reader: &mut T = &mut *ptr;
atomic_reader.set_read_timeout_as(timeout)
}
}
Self::Sync(core) => {
let mut guard = core.lock().expect("can acquire");
guard.set_read_timeout_as(timeout)
}
Self::RWrite(core) => {
let mut guard = core.write().expect("can acquire");
guard.set_read_timeout_as(timeout)
}
Self::RefCell(core) => {
let mut guard = core.borrow_mut();
guard.set_read_timeout_as(timeout)
}
}
}
fn get_current_read_timeout(
&self,
) -> std::result::Result<Option<std::time::Duration>, std::io::Error> {
match self {
Self::Atomic(core) => {
let ptr = core.load(std::sync::atomic::Ordering::Acquire);
unsafe {
let atomic_reader: &mut T = &mut *ptr;
atomic_reader.get_current_read_timeout()
}
}
Self::Sync(core) => {
let guard = core.lock().expect("can acquire");
guard.get_current_read_timeout()
}
Self::RWrite(core) => {
let guard = core.write().expect("can acquire");
guard.get_current_read_timeout()
}
Self::RefCell(core) => {
let guard = core.borrow_mut();
guard.get_current_read_timeout()
}
}
}
}
impl<T: Read> Read for OwnedReader<T> {
fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
match self {
Self::Atomic(core) => {
let ptr = core.load(std::sync::atomic::Ordering::Acquire);
unsafe {
let atomic_reader: &mut T = &mut *ptr;
atomic_reader.read(buf)
}
}
Self::Sync(core) => {
let mut guard = core.lock().expect("can acquire");
guard.read(buf)
}
Self::RWrite(core) => {
let mut guard = core.write().expect("can acquire");
guard.read(buf)
}
Self::RefCell(core) => {
let mut guard = core.borrow_mut();
guard.read(buf)
}
}
}
fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> Result<usize> {
match self {
Self::Atomic(core) => {
let ptr = core.load(std::sync::atomic::Ordering::Acquire);
unsafe {
let atomic_reader: &mut T = &mut *ptr;
atomic_reader.read_vectored(bufs)
}
}
Self::Sync(core) => {
let mut guard = core.lock().expect("can acquire");
guard.read_vectored(bufs)
}
Self::RWrite(core) => {
let mut guard = core.write().expect("can acquire");
guard.read_vectored(bufs)
}
Self::RefCell(core) => {
let mut guard = core.borrow_mut();
guard.read_vectored(bufs)
}
}
}
fn read_exact(&mut self, buf: &mut [u8]) -> Result<()> {
match self {
Self::Atomic(core) => {
let ptr = core.load(std::sync::atomic::Ordering::Acquire);
unsafe {
let atomic_reader: &mut T = &mut *ptr;
atomic_reader.read_exact(buf)
}
}
Self::Sync(core) => {
let mut guard = core.lock().expect("can acquire");
guard.read_exact(buf)
}
Self::RWrite(core) => {
let mut guard = core.write().expect("can acquire");
guard.read_exact(buf)
}
Self::RefCell(core) => {
let mut guard = core.borrow_mut();
guard.read_exact(buf)
}
}
}
fn read_to_end(&mut self, buf: &mut Vec<u8>) -> Result<usize> {
match self {
Self::Atomic(core) => {
let ptr = core.load(std::sync::atomic::Ordering::Acquire);
unsafe {
let atomic_reader: &mut T = &mut *ptr;
atomic_reader.read_to_end(buf)
}
}
Self::Sync(core) => {
let mut guard = core.lock().expect("can acquire");
guard.read_to_end(buf)
}
Self::RWrite(core) => {
let mut guard = core.write().expect("can acquire");
guard.read_to_end(buf)
}
Self::RefCell(core) => {
let mut guard = core.borrow_mut();
guard.read_to_end(buf)
}
}
}
fn read_to_string(&mut self, buf: &mut String) -> Result<usize> {
match self {
Self::Atomic(core) => {
let ptr = core.load(std::sync::atomic::Ordering::Acquire);
unsafe {
let atomic_reader: &mut T = &mut *ptr;
atomic_reader.read_to_string(buf)
}
}
Self::Sync(core) => {
let mut guard = core.lock().expect("can acquire");
guard.read_to_string(buf)
}
Self::RWrite(core) => {
let mut guard = core.write().expect("can acquire");
guard.read_to_string(buf)
}
Self::RefCell(core) => {
let mut guard = core.borrow_mut();
guard.read_to_string(buf)
}
}
}
}
pub const DEFAULT_READ_SIZE: usize = if cfg!(target_os = "espidf") {
512
} else {
8 * 1024
};
pub trait IsUnixTransport {
fn is_unix(&self) -> bool;
fn should_pool(&self) -> bool {
!self.is_unix()
}
}
pub struct SharedByteBufferStream<T: Read>(OwnedReader<ByteBufferPointer<T>>);
impl<T: Read> core::fmt::Debug for SharedByteBufferStream<T> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
self.0.do_once_mut(|inner| {
f.debug_struct("SharedByteBufferStream")
.field("pull_amount", &inner.pull_amount)
.field("buffer_len", &inner.buffer.len())
.field("pos", &inner.pos)
.field("peek_pos", &inner.peek_pos)
.field("distance", &inner.distance())
.finish()
})
}
}
impl<T: Read> SharedByteBufferStream<T> {
pub fn do_ref<F, V>(&self, caller: F) -> V
where
F: Fn(&ByteBufferPointer<T>) -> V,
{
self.0.do_ref(caller)
}
pub fn do_once<F, V>(&self, caller: F) -> V
where
F: FnOnce(&ByteBufferPointer<T>) -> V,
{
self.0.do_once(caller)
}
pub fn do_once_mut<F, V>(&self, caller: F) -> V
where
F: FnOnce(&mut ByteBufferPointer<T>) -> V,
{
self.0.do_once_mut(caller)
}
pub fn do_mut<F, V>(&self, caller: F) -> V
where
F: FnMut(&mut ByteBufferPointer<T>) -> V,
{
self.0.do_mut(caller)
}
pub fn read_line(&mut self, buf: &mut String) -> std::io::Result<usize> {
self.0.do_once_mut(|inner| inner.read_line(buf))
}
pub fn probe(&mut self) -> std::io::Result<usize> {
self.0.do_once_mut(|inner| {
if inner.is_empty_or_consumed() {
let _ = inner.fill_up()?;
}
Ok(inner.remaining())
})
}
#[must_use]
pub fn is_unix(&self) -> bool
where
T: IsUnixTransport,
{
self.0.do_ref(|bbp| bbp.with_inner(|raw| raw.is_unix()))
}
#[must_use]
pub fn should_pool(&self) -> bool
where
T: IsUnixTransport,
{
self.0.do_ref(|bbp| bbp.with_inner(|raw| raw.should_pool()))
}
pub fn with_inner_ref<V>(&self, f: impl Fn(&T) -> V) -> V {
self.0.do_ref(|bbp| bbp.with_inner(|raw| f(raw)))
}
}
impl<T: Read> Clone for SharedByteBufferStream<T> {
fn clone(&self) -> Self {
Self(self.0.clone())
}
}
impl<T: Read> SharedByteBufferStream<T> {
pub fn ref_cell(reader: T) -> Self {
let wrapped_reader = OwnedReader::ref_cell(Rc::new(RefCell::new(reader)));
let byte_reader = ByteBufferPointer::new(DEFAULT_READ_SIZE, wrapped_reader);
Self(OwnedReader::ref_cell(Rc::new(RefCell::new(byte_reader))))
}
pub fn ref_cell_with_capacity(capacity: usize, reader: T) -> Self {
let wrapped_reader = OwnedReader::ref_cell(Rc::new(RefCell::new(reader)));
let byte_reader = ByteBufferPointer::new(capacity, wrapped_reader);
Self(OwnedReader::ref_cell(Rc::new(RefCell::new(byte_reader))))
}
pub fn rwrite(reader: T) -> Self {
let wrapped_reader = OwnedReader::rwrite(Arc::new(RwLock::new(reader)));
let byte_reader = ByteBufferPointer::new(DEFAULT_READ_SIZE, wrapped_reader);
Self(OwnedReader::rwrite(Arc::new(RwLock::new(byte_reader))))
}
pub fn rwrite_with_capacity(capacity: usize, reader: T) -> Self {
let wrapped_reader = OwnedReader::rwrite(Arc::new(RwLock::new(reader)));
let byte_reader = ByteBufferPointer::new(capacity, wrapped_reader);
Self(OwnedReader::rwrite(Arc::new(RwLock::new(byte_reader))))
}
pub fn sync(reader: &Arc<Mutex<T>>) -> Self {
let wrapped_reader = OwnedReader::sync(Arc::clone(reader));
let byte_reader = ByteBufferPointer::new(DEFAULT_READ_SIZE, wrapped_reader);
Self(OwnedReader::sync(Arc::new(Mutex::new(byte_reader))))
}
}
impl<T: Read> SharedByteBufferStream<BufferedReader<T>> {
pub fn with_owned_reader(reader: T) -> Self {
let wrapped_reader = BufferedReader::new(reader);
Self::rwrite(wrapped_reader)
}
}
impl<T: Read> SharedByteBufferStream<BufferedReader<T>> {
pub fn with_buffered_owned_reader(reader: T) -> Self {
Self::rwrite(BufferedReader::new(reader))
}
}
impl<T: Read> PeekableReadStream for SharedByteBufferStream<T> {
fn peek(&mut self, buf: &mut [u8]) -> std::result::Result<usize, PeekError> {
self.0
.do_once_mut(|binding| match binding.peekby(buf.len()) {
Ok(state) => match state {
PeekState::Request(data) | PeekState::Stalled(data) => {
let ending = if buf.len() > data.len() {
data.len()
} else {
buf.len()
};
for (index, elem) in data[0..ending].iter().enumerate() {
buf[index] = *elem;
}
Ok(data.len())
}
PeekState::ZeroLengthInput
| PeekState::NoNext
| PeekState::LessThanRequested
| PeekState::EndOfBuffered
| PeekState::EndOfFile
| PeekState::Continue => Ok(0),
},
Err(err) => Err(PeekError::IOError(err)),
})
}
}
impl<T: Read + Write> std::io::Write for SharedByteBufferStream<T> {
fn write(&mut self, buf: &[u8]) -> Result<usize> {
self.0.do_once_mut(|binding| binding.write(buf))
}
fn flush(&mut self) -> Result<()> {
self.0.do_once_mut(Write::flush)
}
}
impl<T: ReadTimeoutOperations> ReadTimeoutOperations for SharedByteBufferStream<T> {
fn read_timeout_into(
&mut self,
buf: &mut [u8],
timeout: std::time::Duration,
) -> std::result::Result<usize, std::io::Error> {
self.0
.do_once_mut(|binding| binding.read_timeout_into(buf, timeout))
}
fn set_read_timeout_as(
&mut self,
timeout: std::time::Duration,
) -> std::result::Result<(), std::io::Error> {
self.0
.do_once_mut(|binding| binding.set_read_timeout_as(timeout))
}
fn get_current_read_timeout(
&self,
) -> std::result::Result<Option<std::time::Duration>, std::io::Error> {
self.0
.do_once_mut(|binding| binding.get_current_read_timeout())
}
}
impl<T: Read> std::io::Read for SharedByteBufferStream<T> {
fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
self.0.do_once_mut(|binding| binding.read(buf))
}
fn read_vectored(&mut self, buf: &mut [IoSliceMut<'_>]) -> Result<usize> {
self.0.do_once_mut(|binding| binding.read_vectored(buf))
}
fn read_exact(&mut self, buf: &mut [u8]) -> Result<()> {
if buf.is_empty() {
return Ok(());
}
self.0.do_once_mut(|binding| {
let needed = buf.len();
match binding.peekby(needed) {
Ok(PeekState::Request(data)) if data.len() >= needed => binding.read_exact(buf),
Ok(PeekState::Stalled(_)) => Err(crate::err!(
WouldBlock,
"only part of the {needed} bytes have arrived; retry once the peer sends more"
)),
Ok(_) => Err(crate::err!(
UnexpectedEof,
"failed to fill whole buffer: stream ended before {needed} bytes arrived"
)),
Err(err) => Err(err),
}
})
}
fn read_to_end(&mut self, buf: &mut Vec<u8>) -> Result<usize> {
self.0.do_once_mut(|binding| binding.read_to_end(buf))
}
fn read_to_string(&mut self, buf: &mut String) -> Result<usize> {
self.0.do_once_mut(|binding| binding.read_to_string(buf))
}
}
unsafe impl<T: Read + Send> Send for SharedByteBufferStream<T> {}
unsafe impl<T: Read + Send + Sync> Sync for SharedByteBufferStream<T> {}
pub struct ByteBufferPointer<T: Read> {
reader: OwnedReader<T>,
pull_amount: usize,
peek_pos: usize,
buffer: Vec<u8>,
pos: usize,
}
impl<T: Read> ByteBufferPointer<T> {
#[must_use]
pub fn new(pull_amount: usize, reader: OwnedReader<T>) -> Self {
Self {
buffer: Vec::with_capacity(pull_amount),
pull_amount,
peek_pos: 0,
reader,
pos: 0,
}
}
pub fn from_reader(pull_amount: usize, reader: T) -> Self {
let wrapped_reader = OwnedReader::rwrite(Arc::new(RwLock::new(reader)));
Self::new(pull_amount, wrapped_reader)
}
pub fn reader(reader: T) -> Self {
let wrapped_reader = OwnedReader::rwrite(Arc::new(RwLock::new(reader)));
Self::new(DEFAULT_READ_SIZE, wrapped_reader)
}
pub fn with_inner<F, V>(&self, f: F) -> V
where
F: Fn(&T) -> V,
{
self.reader.do_ref(|inner| f(inner))
}
}
impl<T: ReadTimeoutOperations> ReadTimeoutOperations for ByteBufferPointer<T> {
fn read_timeout_into(
&mut self,
buf: &mut [u8],
timeout: std::time::Duration,
) -> std::result::Result<usize, std::io::Error> {
self.reader.read_timeout_into(buf, timeout)
}
fn set_read_timeout_as(
&mut self,
timeout: std::time::Duration,
) -> std::result::Result<(), std::io::Error> {
self.reader.set_read_timeout_as(timeout)
}
fn get_current_read_timeout(
&self,
) -> std::result::Result<Option<std::time::Duration>, std::io::Error> {
self.reader.get_current_read_timeout()
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Data<'a> {
Request(&'a [u8]), Consumed(Vec<u8>),
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum PeekState<'a> {
Request(&'a [u8]), Stalled(&'a [u8]),
LessThanRequested, EndOfBuffered, EndOfFile, NoNext, Continue,
ZeroLengthInput, }
#[allow(unused)]
impl<T: Read> ByteBufferPointer<T> {
#[inline]
#[must_use]
pub fn distance(&self) -> usize {
self.peek_pos - self.pos
}
#[must_use]
pub fn peek_cursor(&self) -> usize {
self.peek_pos
}
#[must_use]
pub fn data_cursor(&self) -> usize {
self.pos
}
#[inline]
#[must_use]
pub fn len(&self) -> usize {
self.buffer.len()
}
#[inline]
#[must_use]
pub fn is_empty(&self) -> bool {
self.buffer.len() == 0
}
#[inline]
#[must_use]
pub fn remaining(&self) -> usize {
self.buffer.len().saturating_sub(self.pos)
}
#[inline]
#[must_use]
pub fn is_empty_or_consumed(&self) -> bool {
self.remaining() == 0
}
#[inline]
pub fn uncapture(&mut self) {
self.uncapture_by(1);
}
#[inline]
pub fn uncapture_by(&mut self, by: usize) {
if (self.pos - by) > 0 {
self.pos -= by;
} else {
self.pos = 0;
}
}
#[inline]
#[must_use]
pub fn full_scan(&self) -> &[u8] {
&self.buffer[..]
}
#[inline]
#[must_use]
pub fn scan(&self) -> &[u8] {
&self.buffer[self.pos..self.peek_pos]
}
#[inline]
#[must_use]
pub fn greater_than_40_percent(&self) -> bool {
if self.pos == 0 {
return false;
}
let buffer_length = self.buffer.len();
#[allow(clippy::cast_precision_loss)]
let percentage = (buffer_length as f64 / self.pos as f64);
percentage > 0.4
}
#[inline]
pub fn truncate(&mut self, force: bool) {
if self.pos == 0 {
return;
}
let distance = self.peek_pos - self.pos;
let buffer_length = self.buffer.len();
#[allow(clippy::cast_precision_loss)]
let percentage = (buffer_length as f64 / self.pos as f64);
let should_truncate = percentage > 0.7 || force;
if !should_truncate {
return;
}
let slice = &self.buffer[self.pos..buffer_length];
let mut slice_copy = vec![0; slice.len()];
slice_copy.truncate(0);
slice_copy.extend_from_slice(slice);
let slice_length = slice_copy.len();
for (index, byte) in slice_copy.iter().enumerate() {
self.buffer[index] = *byte;
}
self.buffer.truncate(slice_length);
self.pos = 0;
self.peek_pos = self.pos + distance;
}
#[inline]
pub fn fill_up(&mut self) -> std::io::Result<usize> {
let force = self.greater_than_40_percent();
self.truncate(force);
let len = self.buffer.len();
let mut copied = vec![0; self.pull_amount];
let read = match self.reader.read(&mut copied) {
Ok(read_size) => read_size,
Err(err) => {
tracing::trace!("Failed to read data from reader due to: {:?}", &err);
return Err(err);
}
};
self.buffer.extend_from_slice(&copied[0..read]);
Ok(read)
}
#[inline]
pub fn fill_all(&mut self, read_limit: Option<usize>) -> std::io::Result<usize> {
let mut total_read = 0;
let mut copied = vec![0; self.pull_amount];
loop {
let read = self.reader.read(&mut copied)?;
if read == 0 {
break;
}
total_read += read;
if let Some(limited_val) = read_limit {
if limited_val < total_read {
return Err(crate::err!(
Interrupted,
"LimitReadTriggered",
"Crossed read limit {}",
limited_val,
));
}
}
self.buffer.extend_from_slice(&copied[0..read]);
}
Ok(total_read)
}
#[inline]
pub fn forward(&mut self) -> std::io::Result<PeekState<'_>> {
self.forward_by(1)
}
#[inline]
pub fn forward_by(&mut self, by: usize) -> std::io::Result<PeekState<'_>> {
let buffer_length = self.buffer.len();
let new_peek = self.peek_pos + by;
if new_peek > buffer_length {
self.peek_pos = buffer_length;
Ok(PeekState::EndOfBuffered)
} else {
self.peek_pos = new_peek;
Ok(PeekState::Continue)
}
}
#[inline]
pub fn unforward(&mut self) -> std::io::Result<PeekState<'_>> {
self.unforward_by(1)
}
#[inline]
pub fn unforward_by(&mut self, by: usize) -> std::io::Result<PeekState<'_>> {
let new_peek = self.peek_pos - by;
if new_peek <= self.pos {
self.peek_pos = self.pos;
Ok(PeekState::Continue)
} else {
self.peek_pos = new_peek;
Ok(PeekState::Continue)
}
}
pub fn consume_some(&mut self) -> Option<Vec<u8>> {
let from = self.pos;
let until_pos = self.peek_pos;
if from == until_pos {
return None;
}
let slice = &self.buffer[from..until_pos];
let slice_string = String::from_utf8(slice.to_vec());
self.pos = self.peek_pos;
let mut slice_copy = vec![0; slice.len()];
slice_copy.truncate(0);
slice_copy.extend_from_slice(slice);
Some(slice_copy)
}
pub fn consume(&mut self) -> std::io::Result<Vec<u8>> {
match self.consume_some() {
Some(item) => Ok(item),
None => Ok(vec![]),
}
}
pub fn skip(&mut self) {
let from = self.pos;
let until_pos = self.peek_pos;
if from == until_pos {
return;
}
self.pos = self.peek_pos;
}
#[inline]
pub fn peek(&self) -> std::io::Result<PeekState<'_>> {
self.peek_by(1)
}
#[inline]
pub fn peek_by(&self, by: usize) -> std::io::Result<PeekState<'_>> {
let until_pos = self.peek_pos + by;
let buffer_length = self.buffer.len();
if until_pos > buffer_length {
return Ok(PeekState::LessThanRequested);
}
let from = self.peek_pos;
Ok(PeekState::Request(&self.buffer[from..until_pos]))
}
#[inline]
pub fn peek_until<'a>(&'a mut self, signal: &[u8]) -> std::io::Result<PeekState<'a>> {
if signal.is_empty() {
return Ok(PeekState::ZeroLengthInput);
}
let current_peek_pos = self.peek_pos;
loop {
let state = self.peek_by(signal.len())?;
match state {
PeekState::Request(data) => {
if data == signal {
break;
}
}
PeekState::EndOfBuffered | PeekState::LessThanRequested => {
if self.fill_up()? == 0 {
return Ok(PeekState::EndOfFile);
}
continue;
}
PeekState::Continue => continue,
PeekState::EndOfFile => {
return Ok(PeekState::EndOfFile);
}
_ => {
unreachable!("Should never hit this types")
}
}
self.peek_pos += signal.len();
}
self.peek_pos += signal.len();
let slice = &self.buffer[self.pos..self.peek_pos];
self.peek_pos = current_peek_pos;
Ok(PeekState::Request(slice))
}
pub fn peekby2(&mut self, size: usize) -> std::io::Result<&[u8]> {
self.peekby(size).map(|item| match item {
PeekState::Request(inner) | PeekState::Stalled(inner) => Ok(inner),
PeekState::NoNext => Err(crate::err!(UnexpectedEof, "No more data to pull through")),
PeekState::ZeroLengthInput => Err(crate::err!(WriteZero, "Provided zero size request")),
_ => unreachable!("Should not trigger this stage"),
})?
}
#[inline]
pub fn peekby(&mut self, size: usize) -> std::io::Result<PeekState<'_>> {
if size == 0 {
return Ok(PeekState::ZeroLengthInput);
}
let mut stalled = false;
loop {
let available = self.buffer.len().cast_signed() - self.peek_pos.cast_signed();
let rem = size.cast_signed() - available;
if rem <= 0 {
break;
}
match self.fill_up() {
Ok(0) => break,
Ok(_) => {}
Err(err) if err.kind() == std::io::ErrorKind::WouldBlock => {
if available > 0 {
stalled = true;
break;
}
return Err(err);
}
Err(err) => return Err(err),
}
}
let buffer_len = self.buffer.len();
let mut until_pos = self.peek_pos + size;
if until_pos > buffer_len {
until_pos = buffer_len;
}
let slice = &self.buffer[self.peek_pos..until_pos];
if slice.is_empty() {
return Ok(PeekState::NoNext);
}
if stalled && slice.len() < size {
return Ok(PeekState::Stalled(slice));
}
Ok(PeekState::Request(slice))
}
#[inline]
pub fn nextby(&mut self, size: usize) -> std::io::Result<PeekState<'_>> {
if size == 0 {
return Ok(PeekState::ZeroLengthInput);
}
let mut cached_error: Option<std::io::Error> = None;
loop {
let available = self.buffer.len().cast_signed() - self.peek_pos.cast_signed();
let rem = size.cast_signed() - available;
if rem <= 0 {
break;
}
match self.fill_up() {
Ok(fill_size) => {
if fill_size == 0 {
break;
}
}
Err(err) => {
cached_error = Some(err);
break;
}
}
}
let buffer_len = self.buffer.len();
let original_peek = self.peek_pos;
let total_data_left = buffer_len - original_peek;
if total_data_left <= size {
self.peek_pos = buffer_len;
} else {
self.peek_pos = original_peek + size;
}
let slice = &self.buffer[original_peek..self.peek_pos];
if self.peek_pos == original_peek {
if let Some(cached_error) = cached_error.take() {
return Err(cached_error);
}
return Ok(PeekState::NoNext);
}
Ok(PeekState::Request(slice))
}
pub fn read_size(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
let read = match self.nextby(buf.len()) {
Ok(state) => match state {
PeekState::Request(data) => {
let ending = if buf.len() > data.len() {
data.len()
} else {
buf.len()
};
for (index, elem) in data[0..ending].iter().enumerate() {
buf[index] = *elem;
}
Ok(ending)
}
PeekState::LessThanRequested => {
let ending = if buf.len() > self.buffer.len() {
self.buffer.len()
} else {
buf.len()
};
for (index, elem) in self.buffer[0..ending].iter().enumerate() {
buf[index] = *elem;
}
Ok(ending)
}
_ => return Ok(0),
},
Err(err) => Err(err),
};
match read {
Ok(val) => {
self.skip();
Ok(val)
}
Err(err) => Err(err),
}
}
pub fn nextby2(&mut self, size: usize) -> std::io::Result<&[u8]> {
self.nextby(size).map(|item| match item {
PeekState::Request(inner) => Ok(inner),
PeekState::NoNext => Err(crate::err!(UnexpectedEof, "No more data to pull through")),
PeekState::ZeroLengthInput => Err(crate::err!(WriteZero, "Provided zero size request")),
_ => unreachable!("Should not trigger this stage"),
})?
}
#[inline]
pub fn next_until<'a>(&'a mut self, signal: &[u8]) -> std::io::Result<PeekState<'a>> {
if signal.is_empty() {
return Ok(PeekState::ZeroLengthInput);
}
loop {
let state = self.peek_by(signal.len())?;
match state {
PeekState::Request(data) => {
if data == signal {
break;
}
}
PeekState::EndOfBuffered | PeekState::LessThanRequested => {
if self.fill_up()? == 0 {
return Ok(PeekState::EndOfFile);
}
continue;
}
PeekState::Continue => continue,
PeekState::EndOfFile => {
return Ok(PeekState::EndOfFile);
}
_ => {
unreachable!("Should never hit this types")
}
}
self.peek_pos += signal.len();
}
self.peek_pos += signal.len();
Ok(PeekState::Request(&self.buffer[self.pos..self.peek_pos]))
}
pub fn next_line(&mut self, buf: &mut String) -> std::io::Result<usize> {
const NEWLINE_SLICE: &[u8] = b"\n";
let read = {
let inner = self.next_until(NEWLINE_SLICE)?;
match inner {
PeekState::Request(c) => {
unsafe {
let buf_vec = buf.as_mut_vec();
buf_vec.extend_from_slice(c);
};
Ok(c.len())
}
PeekState::EndOfFile => Ok(0),
PeekState::ZeroLengthInput => {
Err(crate::err!(WriteZero, "Provided zero size request"))
}
_ => unreachable!("Should never trigger"),
}
};
match read {
Ok(inner) => {
if inner == 0 {
let slice = &self.buffer[self.pos..self.peek_pos];
let slice_length = slice.len();
unsafe {
let mut buf_vec = buf.as_mut_vec();
buf_vec.extend_from_slice(slice);
};
return Ok(slice_length);
}
Ok(inner)
}
Err(err) => Err(err),
}
}
pub fn next_bytes_until(&mut self, target: &[u8], buf: &mut Vec<u8>) -> std::io::Result<usize> {
let read = {
let inner = self.next_until(target)?;
match inner {
PeekState::Request(c) => {
unsafe {
buf.extend_from_slice(c);
};
Ok(c.len())
}
PeekState::EndOfFile => Ok(0),
PeekState::ZeroLengthInput => {
Err(crate::err!(WriteZero, "Provided zero size request"))
}
_ => unreachable!("Should never trigger"),
}
};
match read {
Ok(inner) => {
if inner == 0 {
let slice = &self.buffer[self.pos..self.peek_pos];
let slice_length = slice.len();
unsafe {
buf.extend_from_slice(slice);
};
return Ok(slice_length);
}
Ok(inner)
}
Err(err) => Err(err),
}
}
pub fn read_bytes_until(&mut self, target: &[u8], buf: &mut Vec<u8>) -> std::io::Result<usize> {
let read = {
let inner = self.next_until(target)?;
match inner {
PeekState::Request(c) => {
unsafe {
buf.extend_from_slice(c);
};
Ok(c.len())
}
PeekState::EndOfFile => Ok(0),
PeekState::ZeroLengthInput => {
Err(crate::err!(WriteZero, "Provided zero size request"))
}
_ => unreachable!("Should never trigger"),
}
};
match read {
Ok(inner) => {
if inner == 0 {
let slice = &self.buffer[self.pos..self.peek_pos];
let slice_length = slice.len();
unsafe {
buf.extend_from_slice(slice);
};
self.skip();
return Ok(slice_length);
}
self.skip();
Ok(inner)
}
Err(err) => Err(err),
}
}
pub fn read_line(&mut self, buf: &mut String) -> std::io::Result<usize> {
const NEWLINE_SLICE: &[u8] = b"\n";
let read = {
let inner = self.next_until(NEWLINE_SLICE)?;
match inner {
PeekState::Request(c) => {
match String::from_utf8(c.to_vec()) {
Ok(inner) => {
buf.push_str(&inner);
Ok(inner.len())
}
Err(err) => {
tracing::error!(
"Received invalid utf8 data {:?} with error: {:?}",
&c,
err,
);
buf.extend(c.iter().map(|b| char::from(*b)));
Ok(c.len())
}
}
}
PeekState::EndOfFile => Ok(0),
PeekState::ZeroLengthInput => {
Err(err!(InvalidInput, "Zero length input not allowed"))
}
_ => unreachable!("Should never trigger"),
}
};
match read {
Ok(inner) => {
if inner == 0 {
let slice = &self.buffer[self.pos..self.peek_pos];
let slice_length = slice.len();
unsafe {
let mut buf_vec = buf.as_mut_vec();
buf_vec.extend_from_slice(slice);
};
self.skip();
return Ok(slice_length);
}
self.skip();
Ok(inner)
}
Err(err) => Err(err),
}
}
pub fn read_all(
&mut self,
buf: &mut Vec<u8>,
read_limit: Option<usize>,
) -> std::io::Result<usize> {
self.fill_all(read_limit)?;
let buffer_len = self.buffer.len();
let original_peek = self.peek_pos;
let slice = &self.buffer[original_peek..buffer_len];
let slice_length = slice.len();
buf.extend_from_slice(slice);
self.peek_pos = buffer_len;
self.skip();
Ok(slice_length)
}
}
impl<T: Read + Write> Write for ByteBufferPointer<T> {
fn write(&mut self, buf: &[u8]) -> Result<usize> {
self.reader.write(buf)
}
fn flush(&mut self) -> Result<()> {
self.reader.flush()
}
}
impl<T: Read> Read for ByteBufferPointer<T> {
fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
self.read_size(buf)
}
}
impl<T: Read> PeekableReadStream for ByteBufferPointer<T> {
fn peek(&mut self, buf: &mut [u8]) -> std::result::Result<usize, PeekError> {
match self.nextby(buf.len()) {
Ok(state) => match state {
PeekState::Request(data) => {
let ending = if buf.len() > data.len() {
data.len()
} else {
buf.len()
};
for (index, elem) in data[0..ending].iter().enumerate() {
buf[index] = *elem;
}
Ok(data.len())
}
PeekState::ZeroLengthInput => Err(PeekError::ZeroLengthNotAllowed),
_ => unreachable!("We should never hit this state"),
},
Err(err) => Err(PeekError::IOError(err)),
}
}
}
impl<T: Read> BufferCapacity for ByteBufferPointer<T> {
fn read_buffer(&self) -> &[u8] {
&self.buffer
}
fn read_capacity(&self) -> usize {
self.pull_amount
}
}
#[cfg(test)]
mod byte_buffered_buffer_pointer {
use std::io::Cursor;
use std::sync::Arc;
use std::sync::Mutex;
use super::*;
#[test]
fn fails_read_all_the_data_when_limit_is_reached() {
let content = b"alexander_wonderbat";
let reader = OwnedReader::Sync(Arc::new(Mutex::new(Cursor::new(content.to_vec()))));
let buffer = Mutex::new(ByteBufferPointer::new(5, reader));
let mut binding = buffer.lock().unwrap();
let mut read_data = Vec::new();
let read_length = binding.read_all(&mut read_data, Some(2));
assert!(read_length.is_err())
}
#[test]
fn can_read_all_the_data() {
let content = b"alexander_wonderbat";
let reader = OwnedReader::Sync(Arc::new(Mutex::new(Cursor::new(content.to_vec()))));
let buffer = Mutex::new(ByteBufferPointer::new(5, reader));
let mut binding = buffer.lock().unwrap();
let mut read_data = Vec::new();
let read_length = binding
.read_all(&mut read_data, None)
.expect("read data successfully");
assert_eq!(read_length, content.len());
let data_4_str = str::from_utf8(&read_data[0..read_length]).expect("convert into string");
assert_eq!(data_4_str, "alexander_wonderbat");
}
#[test]
fn can_read_bytes_until_found() {
const NO_BAR: &[u8] = b"_";
let content = b"alexander_wonderbat\n";
let reader = OwnedReader::Sync(Arc::new(Mutex::new(Cursor::new(content.to_vec()))));
let buffer = Mutex::new(ByteBufferPointer::new(10, reader));
let mut binding = buffer.lock().unwrap();
let mut new_line = Vec::new();
let read = binding.read_bytes_until(NO_BAR, &mut new_line);
assert_eq!(10, read.unwrap());
let data4 = vec![97, 108, 101, 120, 97, 110, 100, 101, 114, 95];
assert_eq!(new_line, data4);
}
#[test]
fn can_read_bytes_until_not_found() {
const NO_BAR: &[u8] = b"-";
let content = b"alexander_wonderbat\n";
let reader = OwnedReader::Sync(Arc::new(Mutex::new(Cursor::new(content.to_vec()))));
let buffer = Mutex::new(ByteBufferPointer::new(10, reader));
let mut binding = buffer.lock().unwrap();
let mut new_line = Vec::new();
let read = binding.read_bytes_until(NO_BAR, &mut new_line);
assert_eq!(content.len(), read.unwrap());
let data4 = vec![
97, 108, 101, 120, 97, 110, 100, 101, 114, 95, 119, 111, 110, 100, 101, 114, 98, 97,
116, 10,
];
assert_eq!(new_line, data4);
}
#[test]
fn can_peek_line() {
let content = b"alexander_wonderbat\n";
let reader = OwnedReader::Sync(Arc::new(Mutex::new(Cursor::new(content.to_vec()))));
let buffer = Mutex::new(ByteBufferPointer::new(10, reader));
let mut binding = buffer.lock().unwrap();
let mut new_line = String::new();
let read = binding.next_line(&mut new_line);
assert_eq!(content.len(), read.unwrap());
assert_eq!(new_line, "alexander_wonderbat\n");
let data4 = vec![
97, 108, 101, 120, 97, 110, 100, 101, 114, 95, 119, 111, 110, 100, 101, 114, 98, 97,
116, 10,
];
assert_eq!(binding.scan(), &data4);
}
#[test]
fn can_read_line() {
let content = b"alexander_wonderbat\n";
let reader = OwnedReader::Sync(Arc::new(Mutex::new(Cursor::new(content.to_vec()))));
let buffer = Mutex::new(ByteBufferPointer::new(10, reader));
let mut binding = buffer.lock().unwrap();
let mut new_line = String::new();
let read = binding.read_line(&mut new_line);
assert_eq!(content.len(), read.unwrap());
assert_eq!(new_line, "alexander_wonderbat\n");
}
#[test]
fn can_peek_until_a_signal_and_consume() {
const SIGNAL: &[u8] = b"_";
let content = b"alexander_wonderbat";
let reader = OwnedReader::Sync(Arc::new(Mutex::new(Cursor::new(content.to_vec()))));
let buffer = Mutex::new(ByteBufferPointer::new(10, reader));
let mut binding = buffer.lock().unwrap();
assert!(matches!(
binding.next_until(SIGNAL).expect("should peek"),
PeekState::Request(_)
));
let result = binding.consume();
let content = result.unwrap();
let data4 = vec![97, 108, 101, 120, 97, 110, 100, 101, 114, 95];
assert_eq!(content, data4);
let data_4_str = str::from_utf8(&data4).expect("convert into string");
assert_eq!(data_4_str, "alexander_");
}
#[test]
fn can_peek_until_a_signal() {
const SIGNAL: &[u8] = b"_";
let content = b"alexander_wonderbat";
let reader = OwnedReader::Sync(Arc::new(Mutex::new(Cursor::new(content.to_vec()))));
let buffer = Mutex::new(ByteBufferPointer::new(10, reader));
let mut binding = buffer.lock().unwrap();
let result = binding.next_until(SIGNAL);
assert!(matches!(result, Ok(PeekState::Request(_))));
let PeekState::Request(content) = result.unwrap() else {
panic!("Failed expectation")
};
let data4 = vec![97, 108, 101, 120, 97, 110, 100, 101, 114, 95];
assert_eq!(content, &data4);
let data_4_str = str::from_utf8(&data4).expect("convert into string");
assert_eq!(data_4_str, "alexander_");
}
#[test]
fn can_peek_until_a_signal_but_not_found() {
const SIGNAL: &[u8] = b"-";
let content = b"alexander_wonderbat";
let reader = OwnedReader::Sync(Arc::new(Mutex::new(Cursor::new(content.to_vec()))));
let buffer = Mutex::new(ByteBufferPointer::new(10, reader));
let mut binding = buffer.lock().unwrap();
let result = binding.next_until(SIGNAL);
assert!(matches!(result, Ok(PeekState::EndOfFile)));
}
#[test]
fn can_take_peeked_data_with_multi_mutex() {
let content = b"alexander_wonderbat";
let reader = OwnedReader::Sync(Arc::new(Mutex::new(Cursor::new(content.to_vec()))));
let buffer = Mutex::new(ByteBufferPointer::new(10, reader));
assert_eq!(
buffer.lock().unwrap().peek().expect("less than requested"),
PeekState::LessThanRequested
);
buffer.lock().unwrap().fill_up().expect("should fill up");
let data3 = vec![97, 108, 101, 120, 97, 110, 100, 101, 114, 95];
assert_eq!(
buffer.lock().unwrap().peek_by(10).expect("capture 3"),
PeekState::Request(data3.as_ref())
);
assert_eq!(
buffer.lock().unwrap().forward_by(9).expect("capture 3"),
PeekState::Continue
);
assert_eq!(buffer.lock().unwrap().scan(), &data3[0..9]);
assert_eq!(buffer.lock().unwrap().full_scan(), &data3[0..10]);
assert_eq!(
buffer.lock().unwrap().forward_by(10).expect("capture 4"),
PeekState::EndOfBuffered
);
let amt = buffer.lock().unwrap().fill_up().expect("should fill up");
assert_eq!(
buffer.lock().unwrap().forward_by(amt).expect("capture 3"),
PeekState::Continue
);
let data4 = vec![
97, 108, 101, 120, 97, 110, 100, 101, 114, 95, 119, 111, 110, 100, 101, 114, 98, 97,
116,
];
assert_eq!(buffer.lock().unwrap().scan(), &data4);
}
#[test]
fn can_read_data_via_byte_buffer_pointer() {
let content = b"alexander_wonderbat";
let mut source = Cursor::new(content.to_vec());
let reader = OwnedReader::atomic(&mut source);
let mut buffer = ByteBufferPointer::new(128, reader);
assert_eq!(
buffer.peek().expect("less than requested"),
PeekState::LessThanRequested
);
buffer.fill_up().expect("should fill up");
let data = vec![97];
assert_eq!(
buffer.peek().expect("capture 1"),
PeekState::Request(data.as_ref())
);
let data2 = vec![97, 108];
assert_eq!(
buffer.peek_by(2).expect("capture 2"),
PeekState::Request(data2.as_ref())
);
let data3 = vec![97, 108, 101, 120, 97, 110, 100, 101, 114, 95];
assert_eq!(
buffer.peek_by(10).expect("capture 3"),
PeekState::Request(data3.as_ref())
);
}
#[test]
fn can_take_peeked_data() {
let content = b"alexander_wonderbat";
let mut source = Cursor::new(content.to_vec());
let reader = OwnedReader::atomic(&mut source);
let mut buffer = ByteBufferPointer::new(128, reader);
assert_eq!(
buffer.peek().expect("less than requested"),
PeekState::LessThanRequested
);
buffer.fill_up().expect("should fill up");
let data3 = vec![97, 108, 101, 120, 97, 110, 100, 101, 114, 95];
assert_eq!(
buffer.peek_by(10).expect("capture 3"),
PeekState::Request(data3.as_ref())
);
}
#[test]
fn can_take_unmove_data() {
let content = b"alexander_wonderbat";
let mut source = Cursor::new(content.to_vec());
let reader = OwnedReader::atomic(&mut source);
let mut buffer = ByteBufferPointer::new(128, reader);
assert_eq!(
buffer.peek().expect("less than requested"),
PeekState::LessThanRequested
);
buffer.fill_up().expect("should fill up");
let data3 = vec![97, 108, 101, 120, 97, 110, 100, 101, 114, 95];
assert_eq!(
buffer.peek_by(10).expect("capture 3"),
PeekState::Request(data3.as_ref())
);
assert_eq!(
buffer.forward_by(10).expect("capture 3"),
PeekState::Continue
);
assert_eq!(buffer.scan(), &data3[0..10]);
assert_eq!(
buffer.unforward_by(5).expect("capture 3"),
PeekState::Continue
);
assert_eq!(buffer.scan(), &data3[0..5]);
}
#[test]
fn can_skip_data() {
let content = b"alexander_wonderbat";
let mut source = Cursor::new(content.to_vec());
let reader = OwnedReader::atomic(&mut source);
let mut buffer = ByteBufferPointer::new(128, reader);
assert_eq!(
buffer.peek().expect("less than requested"),
PeekState::LessThanRequested
);
buffer.fill_up().expect("should fill up");
let data3 = vec![97, 108, 101, 120, 97, 110, 100, 101, 114, 95];
assert_eq!(
buffer.peek_by(10).expect("capture 3"),
PeekState::Request(data3.as_ref())
);
assert_eq!(
buffer.forward_by(10).expect("capture 3"),
PeekState::Continue
);
assert_eq!(buffer.scan(), &data3[0..10]);
assert_eq!(
buffer.unforward_by(5).expect("capture 3"),
PeekState::Continue
);
buffer.skip();
let data4: Vec<u8> = vec![];
assert_eq!(buffer.scan(), &data4);
let data5: Vec<u8> = vec![110, 100, 101, 114, 95];
assert_eq!(
buffer.peek_by(5).expect("capture 3"),
PeekState::Request(data5.as_ref())
);
}
#[test]
fn can_use_buffered_reader_move_next_data() {
let content = b"alexander_wonderbat";
let mut reader = BufferedReader::new(BufferedWriter::new(Cursor::new(content.to_vec())));
let mut buffer = ByteBufferPointer::new(128, OwnedReader::atomic(&mut reader));
assert_eq!(
buffer.peek().expect("less than requested"),
PeekState::LessThanRequested
);
buffer.fill_up().expect("should fill up");
let data3 = vec![97, 108, 101, 120, 97, 110, 100, 101, 114, 95];
assert_eq!(0, buffer.data_cursor());
assert_eq!(0, buffer.peek_cursor());
assert_eq!(
buffer.peek_by(10).expect("capture 3"),
PeekState::Request(data3.as_ref())
);
assert_eq!(
buffer.forward_by(10).expect("capture 3"),
PeekState::Continue
);
assert_eq!(buffer.scan(), &data3[0..10]);
assert!(!buffer.greater_than_40_percent());
assert_eq!(buffer.consume().expect("capture 3"), data3.clone());
assert!(buffer.greater_than_40_percent());
}
#[test]
fn can_move_next_data() {
let content = b"alexander_wonderbat";
let mut source = Cursor::new(content.to_vec());
let reader = OwnedReader::atomic(&mut source);
let mut buffer = ByteBufferPointer::new(128, reader);
assert_eq!(
buffer.peek().expect("less than requested"),
PeekState::LessThanRequested
);
buffer.fill_up().expect("should fill up");
let data3 = vec![97, 108, 101, 120, 97, 110, 100, 101, 114, 95];
assert_eq!(0, buffer.data_cursor());
assert_eq!(0, buffer.peek_cursor());
assert_eq!(
buffer.peek_by(10).expect("capture 3"),
PeekState::Request(data3.as_ref())
);
assert_eq!(
buffer.forward_by(10).expect("capture 3"),
PeekState::Continue
);
assert_eq!(buffer.scan(), &data3[0..10]);
assert!(!buffer.greater_than_40_percent());
assert_eq!(buffer.consume().expect("capture 3"), data3.clone());
assert!(buffer.greater_than_40_percent());
}
#[test]
fn can_pull_more_data() {
let content = b"alexander_wonderbat";
let mut source = Cursor::new(content.to_vec());
let reader = OwnedReader::atomic(&mut source);
let mut buffer = ByteBufferPointer::new(10, reader);
assert_eq!(
buffer.peek().expect("less than requested"),
PeekState::LessThanRequested
);
buffer.fill_up().expect("should fill up");
let data3 = vec![97, 108, 101, 120, 97, 110, 100, 101, 114, 95];
assert_eq!(
buffer.peek_by(10).expect("capture 3"),
PeekState::Request(data3.as_ref())
);
assert_eq!(
buffer.forward_by(9).expect("capture 3"),
PeekState::Continue
);
assert_eq!(buffer.scan(), &data3[0..9]);
assert_eq!(buffer.full_scan(), &data3[0..10]);
assert_eq!(
buffer.forward_by(10).expect("capture 4"),
PeekState::EndOfBuffered
);
let amt = buffer.fill_up().expect("should fill up");
assert_eq!(
buffer.forward_by(amt).expect("capture 3"),
PeekState::Continue
);
let data4 = vec![
97, 108, 101, 120, 97, 110, 100, 101, 114, 95, 119, 111, 110, 100, 101, 114, 98, 97,
116,
];
assert_eq!(buffer.scan(), &data4);
}
#[test]
fn can_pull_more_data_with_mutex() {
let content = b"alexander_wonderbat";
let reader = OwnedReader::Sync(Arc::new(Mutex::new(Cursor::new(content.to_vec()))));
let mut buffer = ByteBufferPointer::new(10, reader);
assert_eq!(
buffer.peek().expect("less than requested"),
PeekState::LessThanRequested
);
buffer.fill_up().expect("should fill up");
let data3 = vec![97, 108, 101, 120, 97, 110, 100, 101, 114, 95];
assert_eq!(
buffer.peek_by(10).expect("capture 3"),
PeekState::Request(data3.as_ref())
);
assert_eq!(
buffer.forward_by(9).expect("capture 3"),
PeekState::Continue
);
assert_eq!(buffer.scan(), &data3[0..9]);
assert_eq!(buffer.full_scan(), &data3[0..10]);
assert_eq!(
buffer.forward_by(10).expect("capture 4"),
PeekState::EndOfBuffered
);
let amt = buffer.fill_up().expect("should fill up");
assert_eq!(
buffer.forward_by(amt).expect("capture 3"),
PeekState::Continue
);
let data4 = vec![
97, 108, 101, 120, 97, 110, 100, 101, 114, 95, 119, 111, 110, 100, 101, 114, 98, 97,
116,
];
assert_eq!(buffer.scan(), &data4);
}
}
pub struct BufferedCapacityCursor<T>(std::io::Cursor<T>);
impl BufferCapacity for BufferedCapacityCursor<&str> {
fn read_buffer(&self) -> &[u8] {
self.0.get_ref().as_bytes()
}
fn read_capacity(&self) -> usize {
self.0.get_ref().len()
}
}
impl BufferCapacity for BufferedCapacityCursor<String> {
fn read_buffer(&self) -> &[u8] {
self.0.get_ref().as_bytes()
}
fn read_capacity(&self) -> usize {
self.0.get_ref().len()
}
}
impl BufferCapacity for BufferedCapacityCursor<&[u8]> {
fn read_buffer(&self) -> &[u8] {
self.0.get_ref()
}
fn read_capacity(&self) -> usize {
self.0.get_ref().len()
}
}
impl BufferCapacity for BufferedCapacityCursor<Vec<u8>> {
fn read_buffer(&self) -> &[u8] {
self.0.get_ref()
}
fn read_capacity(&self) -> usize {
self.0.get_ref().len()
}
}
impl<T> BufferedCapacityCursor<T> {
pub fn new(cursor: std::io::Cursor<T>) -> Self {
Self(cursor)
}
pub fn get_ref(&self) -> &Cursor<T> {
&self.0
}
pub fn get_mut(&mut self) -> &mut Cursor<T> {
&mut self.0
}
pub fn get_inner_ref(&self) -> &T {
self.0.get_ref()
}
pub fn get_inner_mut(&mut self) -> &mut T {
self.0.get_mut()
}
}
#[derive(Clone)]
pub struct SharedBufferWriter {
inner: Arc<Mutex<Vec<u8>>>,
}
impl Write for SharedBufferWriter {
fn write(&mut self, buf: &[u8]) -> Result<usize> {
let mut guard = self.inner.lock().expect("SharedBufferWriter lock poisoned");
guard.extend_from_slice(buf);
Ok(buf.len())
}
fn flush(&mut self) -> Result<()> {
Ok(())
}
}
impl SharedBufferWriter {
pub fn new(inner: Arc<Mutex<Vec<u8>>>) -> Self {
Self { inner }
}
#[must_use]
pub fn clone_arc(&self) -> Arc<Mutex<Vec<u8>>> {
Arc::clone(&self.inner)
}
}
#[derive(Clone)]
pub struct SharedBufferReader {
inner: Arc<Mutex<Vec<u8>>>,
position: usize,
}
impl Read for SharedBufferReader {
fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
let guard = self.inner.lock().expect("SharedBufferReader lock poisoned");
let available = guard.len().saturating_sub(self.position);
if available == 0 {
return Ok(0);
}
let to_read = buf.len().min(available);
buf[..to_read].copy_from_slice(&guard[self.position..self.position + to_read]);
drop(guard);
self.position += to_read;
Ok(to_read)
}
}
impl SharedBufferReader {
pub fn new(inner: Arc<Mutex<Vec<u8>>>) -> Self {
Self { inner, position: 0 }
}
pub fn with_position(inner: Arc<Mutex<Vec<u8>>>, position: usize) -> Self {
Self { inner, position }
}
#[must_use]
pub fn position(&self) -> usize {
self.position
}
#[must_use]
pub fn into_buffered_stream(self) -> SharedByteBufferStream<SharedBufferReadStream> {
SharedByteBufferStream::rwrite(SharedBufferReadStream::new(
Arc::clone(&self.inner),
self.position,
))
}
}
pub struct SharedBufferReadStream {
inner: Arc<Mutex<Vec<u8>>>,
position: usize,
}
impl SharedBufferReadStream {
pub fn new(inner: Arc<Mutex<Vec<u8>>>, position: usize) -> Self {
Self { inner, position }
}
}
impl std::io::Read for SharedBufferReadStream {
fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
let guard = self.inner.lock().expect("SharedBuffer lock poisoned");
let available = guard.len().saturating_sub(self.position);
if available == 0 {
return Ok(0);
}
let to_read = buf.len().min(available);
buf[..to_read].copy_from_slice(&guard[self.position..self.position + to_read]);
drop(guard);
self.position += to_read;
Ok(to_read)
}
}
pub struct SharedBuffer {
inner: Arc<Mutex<Vec<u8>>>,
}
impl SharedBuffer {
#[must_use]
pub fn split() -> (SharedBufferWriter, SharedBufferReader) {
let inner = Arc::new(Mutex::new(Vec::new()));
let writer = SharedBufferWriter::new(Arc::clone(&inner));
let reader = SharedBufferReader::new(inner);
(writer, reader)
}
#[must_use]
pub fn with_initial(initial: &[u8]) -> Self {
let inner = Arc::new(Mutex::new(initial.to_vec()));
Self { inner }
}
#[must_use]
pub fn len(&self) -> usize {
let guard = self.inner.lock().expect("SharedBuffer lock poisoned");
guard.len()
}
#[must_use]
pub fn is_empty(&self) -> bool {
self.len() == 0
}
}
impl Default for SharedBuffer {
fn default() -> Self {
Self {
inner: Arc::new(Mutex::new(Vec::new())),
}
}
}
pub struct SharedWriteReader<T: Read + Write> {
inner: Arc<Mutex<T>>,
}
impl<T: Read + Write> Clone for SharedWriteReader<T> {
fn clone(&self) -> Self {
Self {
inner: Arc::clone(&self.inner),
}
}
}
impl<T: Read + Write> SharedWriteReader<T> {
pub fn new(inner: T) -> Self {
Self {
inner: Arc::new(Mutex::new(inner)),
}
}
pub fn from_arc(arc: Arc<Mutex<T>>) -> Self {
Self { inner: arc }
}
#[must_use]
pub fn clone_arc(&self) -> Arc<Mutex<T>> {
Arc::clone(&self.inner)
}
}
impl<T: Read + Write> Read for SharedWriteReader<T> {
fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
let mut guard = self.inner.lock().expect("SharedWriteReader lock poisoned");
guard.read(buf)
}
fn read_exact(&mut self, buf: &mut [u8]) -> Result<()> {
let mut guard = self.inner.lock().expect("SharedWriteReader lock poisoned");
guard.read_exact(buf)
}
fn read_to_end(&mut self, buf: &mut Vec<u8>) -> Result<usize> {
let mut guard = self.inner.lock().expect("SharedWriteReader lock poisoned");
guard.read_to_end(buf)
}
fn read_to_string(&mut self, buf: &mut String) -> Result<usize> {
let mut guard = self.inner.lock().expect("SharedWriteReader lock poisoned");
guard.read_to_string(buf)
}
fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> Result<usize> {
let mut guard = self.inner.lock().expect("SharedWriteReader lock poisoned");
guard.read_vectored(bufs)
}
}
impl<T: Read + Write> Write for SharedWriteReader<T> {
fn write(&mut self, buf: &[u8]) -> Result<usize> {
let mut guard = self.inner.lock().expect("SharedWriteReader lock poisoned");
guard.write(buf)
}
fn write_all(&mut self, buf: &[u8]) -> Result<()> {
let mut guard = self.inner.lock().expect("SharedWriteReader lock poisoned");
guard.write_all(buf)
}
fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> Result<usize> {
let mut guard = self.inner.lock().expect("SharedWriteReader lock poisoned");
guard.write_vectored(bufs)
}
fn flush(&mut self) -> Result<()> {
let mut guard = self.inner.lock().expect("SharedWriteReader lock poisoned");
guard.flush()
}
}
unsafe impl<T: Read + Write + Send> Send for SharedWriteReader<T> {}
unsafe impl<T: Read + Write + Send + Sync> Sync for SharedWriteReader<T> {}
#[cfg(test)]
mod shared_write_reader_tests {
use super::*;
use std::io::Cursor;
#[test]
fn test_shared_write_reader_write_and_read_position() {
let cursor = Cursor::new(Vec::new());
let shared = SharedWriteReader::new(cursor);
let mut writer = shared.clone();
writer
.write_all(b"hello world")
.expect("write should succeed");
let inner = shared.inner.lock().expect("lock should not be poisoned");
assert_eq!(inner.get_ref(), b"hello world");
}
#[test]
fn test_shared_write_reader_multiple_writers() {
let cursor = Cursor::new(Vec::new());
let shared = SharedWriteReader::new(cursor);
let mut w1 = shared.clone();
let mut w2 = shared.clone();
w1.write_all(b"hello ").expect("write should succeed");
w2.write_all(b"world").expect("write should succeed");
let inner = shared.inner.lock().expect("lock should not be poisoned");
let data = inner.get_ref();
assert_eq!(data, b"hello world");
}
#[test]
fn test_shared_write_reader_from_arc() {
let arc = Arc::new(Mutex::new(Cursor::new(Vec::new())));
let shared = SharedWriteReader::from_arc(arc.clone());
let mut writer = shared.clone();
writer
.write_all(b"test data")
.expect("write should succeed");
let guard = arc.lock().expect("lock should not be poisoned");
let data = guard.get_ref();
assert_eq!(data, b"test data");
}
}
#[cfg(test)]
mod shared_byte_buffer_stream_tests {
use super::*;
#[test]
fn test_shared_write_reader_with_cursor() {
let cursor = Cursor::new(Vec::new());
let shared = SharedWriteReader::new(cursor);
let mut w1 = shared.clone();
w1.write_all(b"hello").expect("write should succeed");
let r1 = shared.clone();
let inner = r1.inner.lock().expect("lock not poisoned");
assert_eq!(inner.get_ref(), b"hello");
}
#[test]
fn test_shared_write_reader_threaded() {
let cursor = Cursor::new(Vec::new());
let shared = SharedWriteReader::new(cursor);
let mut handles = vec![];
for i in 0..3 {
let s = shared.clone();
let handle = std::thread::spawn(move || {
let mut writer = s.clone();
let msg = format!("thread_{}", i);
writer
.write_all(msg.as_bytes())
.expect("write should succeed");
});
handles.push(handle);
}
for handle in handles {
handle.join().expect("thread should join");
}
let inner = shared.inner.lock().expect("lock not poisoned");
let data = inner.get_ref();
assert!(data.starts_with(b"thread_"));
}
}
#[cfg(test)]
mod shared_buffer_tests {
use super::*;
#[test]
fn test_shared_buffer_write_and_read() {
let (mut writer, mut reader) = SharedBuffer::split();
writer.write_all(b"hello").unwrap();
let mut buf = [0u8; 5];
reader.read_exact(&mut buf).unwrap();
assert_eq!(&buf, b"hello");
}
#[test]
fn test_shared_buffer_empty_read() {
let (_, mut reader) = SharedBuffer::split();
let mut buf = [0u8; 5];
let bytes_read = reader.read(&mut buf).unwrap();
assert_eq!(bytes_read, 0);
}
#[test]
fn test_shared_buffer_multiple_writes() {
let (mut writer, mut reader) = SharedBuffer::split();
writer.write_all(b"hello").unwrap();
writer.write_all(b" ").unwrap();
writer.write_all(b"world").unwrap();
let mut buf = [0u8; 11];
reader.read_exact(&mut buf).unwrap();
assert_eq!(&buf, b"hello world");
}
#[test]
fn test_shared_buffer_partial_read() {
let (mut writer, mut reader) = SharedBuffer::split();
writer.write_all(b"hello world").unwrap();
let mut buf = [0u8; 5];
reader.read_exact(&mut buf).unwrap();
assert_eq!(&buf, b"hello");
reader.read_exact(&mut buf).unwrap();
assert_eq!(&buf, b" worl");
}
#[test]
fn test_shared_buffer_clone_writer() {
let (mut writer, mut reader) = SharedBuffer::split();
let mut writer2 = writer.clone();
writer.write_all(b"hello").unwrap();
writer2.write_all(b" ").unwrap();
writer.write_all(b"world").unwrap();
let mut buf = [0u8; 11];
reader.read_exact(&mut buf).unwrap();
assert_eq!(&buf, b"hello world");
}
#[test]
fn test_shared_buffer_clone_reader() {
let (mut writer, mut reader) = SharedBuffer::split();
let mut reader2 = reader.clone();
writer.write_all(b"hello").unwrap();
let mut buf1 = [0u8; 5];
let mut buf2 = [0u8; 5];
reader.read_exact(&mut buf1).unwrap();
reader2.read_exact(&mut buf2).unwrap();
assert_eq!(&buf1, b"hello");
assert_eq!(&buf2, b"hello");
}
#[test]
fn test_shared_buffer_with_initial() {
let buffer = SharedBuffer::with_initial(b"initial data");
let (_, mut reader) = (
SharedBufferWriter::new(buffer.inner.clone()),
SharedBufferReader::new(buffer.inner),
);
let mut buf = [0u8; 12];
reader.read_exact(&mut buf).unwrap();
assert_eq!(&buf, b"initial data");
}
#[test]
fn test_shared_buffer_len() {
let buffer = SharedBuffer::with_initial(b"hello");
assert_eq!(buffer.len(), 5);
let (mut writer, _) = SharedBuffer::split();
assert_eq!(writer.inner.lock().unwrap().len(), 0);
writer.write_all(b"test").unwrap();
assert_eq!(writer.inner.lock().unwrap().len(), 4);
}
#[test]
fn test_shared_buffer_threaded() {
use std::thread;
let (mut writer, mut reader) = SharedBuffer::split();
let handle = thread::spawn(move || {
writer.write_all(b"from thread").unwrap();
});
thread::sleep(std::time::Duration::from_millis(10));
let mut buf = [0u8; 11];
reader.read_exact(&mut buf).unwrap();
handle.join().unwrap();
assert_eq!(&buf, b"from thread");
}
#[test]
fn test_into_buffered_stream_read() {
let (mut writer, reader) = SharedBuffer::split();
writer.write_all(b"hello world").unwrap();
let mut stream = reader.into_buffered_stream();
let mut buf = [0u8; 11];
let bytes_read = stream.read(&mut buf).unwrap();
assert_eq!(bytes_read, 11);
assert_eq!(&buf, b"hello world");
}
#[test]
fn test_into_buffered_stream_read_line() {
let (mut writer, reader) = SharedBuffer::split();
writer.write_all(b"line 1\nline 2\nline 3\n").unwrap();
let mut stream = reader.into_buffered_stream();
let mut line = String::new();
let bytes_read = stream.read_line(&mut line).unwrap();
assert_eq!(bytes_read, 7); assert_eq!(line, "line 1\n");
line.clear();
let bytes_read = stream.read_line(&mut line).unwrap();
assert_eq!(bytes_read, 7); assert_eq!(line, "line 2\n");
line.clear();
let bytes_read = stream.read_line(&mut line).unwrap();
assert_eq!(bytes_read, 7); assert_eq!(line, "line 3\n");
}
#[test]
fn test_into_buffered_stream_sse_format() {
let (mut writer, reader) = SharedBuffer::split();
writer.write_all(b"data: hello\n\n").unwrap();
let mut stream = reader.into_buffered_stream();
let mut buf = Vec::new();
stream.read_to_end(&mut buf).unwrap();
assert_eq!(buf, b"data: hello\n\n");
}
#[test]
fn test_into_buffered_stream_multiple_lines() {
let (mut writer, reader) = SharedBuffer::split();
writer.write_all(b"event: test\ndata: payload\n\n").unwrap();
let mut stream = reader.into_buffered_stream();
let mut line = String::new();
stream.read_line(&mut line).unwrap();
assert_eq!(line, "event: test\n");
line.clear();
stream.read_line(&mut line).unwrap();
assert_eq!(line, "data: payload\n");
line.clear();
stream.read_line(&mut line).unwrap();
assert_eq!(line, "\n");
}
#[test]
fn test_into_buffered_stream_empty_buffer() {
let (_, reader) = SharedBuffer::split();
let mut stream = reader.into_buffered_stream();
let mut buf = [0u8; 5];
let bytes_read = stream.read(&mut buf).unwrap();
assert_eq!(bytes_read, 0);
}
#[test]
fn test_into_buffered_stream_partial_reads() {
let (mut writer, reader) = SharedBuffer::split();
writer.write_all(b"hello world").unwrap();
let mut stream = reader.into_buffered_stream();
let mut buf = [0u8; 5];
let bytes_read = stream.read(&mut buf).unwrap();
assert_eq!(bytes_read, 5);
assert_eq!(&buf, b"hello");
let bytes_read = stream.read(&mut buf).unwrap();
assert_eq!(bytes_read, 5);
assert_eq!(&buf, b" worl");
let bytes_read = stream.read(&mut buf).unwrap();
assert_eq!(bytes_read, 1);
assert_eq!(&buf[0..1], b"d");
}
#[test]
fn test_into_buffered_stream_read_exact() {
let (mut writer, reader) = SharedBuffer::split();
writer.write_all(b"exact data").unwrap();
let mut stream = reader.into_buffered_stream();
let mut buf = [0u8; 10];
stream.read_exact(&mut buf).unwrap();
assert_eq!(&buf, b"exact data");
}
}
#[cfg(test)]
mod buffered_writer_tests {
use std::io::Cursor;
use super::*;
#[test]
fn can_buffered_writer_peek() {
let content = b"alexander_wonderbat";
let mut reader = BufferedReader::new(BufferedWriter::new(Cursor::new(content.to_vec())));
let mut content_to_read = vec![0; 5];
reader
.peek(&mut content_to_read)
.expect("should read data correctly");
assert_eq!(b"alexa", &content_to_read[..]);
assert_eq!(content, reader.buffer());
}
}