use bytes::BytesMut;
use std::io::Read;
use std::sync::Arc;
use crate::io::buffer_pool::{BytesPool, PooledBuffer};
pub trait ReadBytesExt: Read {
fn read_into_bytes(&mut self, buf: &mut BytesMut, max_len: usize) -> std::io::Result<usize>;
fn read_exact_into_bytes(&mut self, len: usize) -> std::io::Result<BytesMut>;
fn read_byte(&mut self) -> std::io::Result<Option<u8>>;
fn read_pooled_buffer(
&mut self,
pool: &Arc<BytesPool>,
max_len: usize,
) -> std::io::Result<Option<PooledBuffer>>;
}
impl<R: Read> ReadBytesExt for R {
fn read_into_bytes(&mut self, buf: &mut BytesMut, max_len: usize) -> std::io::Result<usize> {
let available = buf.spare_capacity_mut();
let to_read = max_len.min(available.len());
if to_read == 0 {
return Ok(0);
}
let slice = &mut available[..to_read];
let ptr = slice.as_mut_ptr().cast();
let n = unsafe { Read::read(self, std::slice::from_raw_parts_mut(ptr, to_read))? };
unsafe {
buf.set_len(buf.len() + n);
}
Ok(n)
}
fn read_exact_into_bytes(&mut self, len: usize) -> std::io::Result<BytesMut> {
let mut buf = BytesMut::with_capacity(len);
buf.resize(len, 0);
self.read_exact(&mut buf)?;
Ok(buf)
}
fn read_byte(&mut self) -> std::io::Result<Option<u8>> {
let mut byte = [0u8; 1];
match self.read(&mut byte)? {
0 => Ok(None),
_ => Ok(Some(byte[0])),
}
}
fn read_pooled_buffer(
&mut self,
pool: &Arc<BytesPool>,
max_len: usize,
) -> std::io::Result<Option<PooledBuffer>> {
let mut buf = pool.acquire_with_capacity(max_len);
buf.resize(max_len, 0);
let n = self.read(&mut buf)?;
if n == 0 {
return Ok(None);
}
buf.truncate(n);
Ok(Some(buf))
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::io::Cursor;
#[test]
fn test_read_into_bytes() {
let mut cursor = Cursor::new(b"hello world");
let mut buf = BytesMut::with_capacity(1024);
let n = cursor.read_into_bytes(&mut buf, 5).unwrap();
assert_eq!(n, 5);
assert_eq!(&buf[..], b"hello");
}
#[test]
fn test_read_exact_into_bytes() {
let mut cursor = Cursor::new(b"hello world");
let buf = cursor.read_exact_into_bytes(5).unwrap();
assert_eq!(buf.len(), 5);
assert_eq!(&buf[..], b"hello");
}
#[test]
fn test_read_byte() {
let mut cursor = Cursor::new(b"hello");
assert_eq!(cursor.read_byte().unwrap(), Some(b'h'));
assert_eq!(cursor.read_byte().unwrap(), Some(b'e'));
cursor.read_byte().unwrap();
cursor.read_byte().unwrap();
cursor.read_byte().unwrap();
assert_eq!(cursor.read_byte().unwrap(), None);
}
#[test]
fn test_read_into_bytes_empty() {
let mut cursor = Cursor::new(b"");
let mut buf = BytesMut::with_capacity(1024);
let n = cursor.read_into_bytes(&mut buf, 5).unwrap();
assert_eq!(n, 0);
assert!(buf.is_empty());
}
#[test]
fn test_read_exact_into_bytes_eof() {
let mut cursor = Cursor::new(b"hi");
let result = cursor.read_exact_into_bytes(5);
assert!(result.is_err());
}
#[test]
fn test_read_pooled_buffer() {
let pool = Arc::new(BytesPool::new(1024, 1));
let mut cursor = Cursor::new(b"hello world");
let result = cursor.read_pooled_buffer(&pool, 1024).unwrap();
assert!(result.is_some());
let buf = result.unwrap();
assert_eq!(&buf[..], b"hello world");
}
#[test]
fn test_read_pooled_buffer_eof() {
let pool = Arc::new(BytesPool::new(1024, 1));
let mut cursor = Cursor::new(b"");
let result = cursor.read_pooled_buffer(&pool, 1024).unwrap();
assert!(result.is_none());
}
#[test]
fn test_pooled_buffer_return() {
let pool = Arc::new(BytesPool::new(1024, 1));
let _buf1 = pool.acquire();
let stats1 = pool.stats();
assert_eq!(stats1.pool_hits, 1);
drop(_buf1);
let _buf2 = pool.acquire();
let stats2 = pool.stats();
assert_eq!(stats2.pool_hits, 2);
}
}