mod test;
use std::{io::BufRead, str::FromStr};
use tokio::io::{AsyncBufRead, AsyncReadExt};
use crate::config::PRE_ALLOCATED_BUFFER_SIZE;
#[derive(Debug, Clone)]
pub enum BufferType {
Stack([u8; PRE_ALLOCATED_BUFFER_SIZE]),
Heap(Vec<u8>),
}
#[derive(Debug, Clone)]
pub struct Buffer {
buffer: BufferType,
read_size: usize,
}
impl Buffer {
pub fn new(size: usize) -> Self {
Self {
buffer: BufferType::new(size),
read_size: 0,
}
}
pub fn read<R: BufRead>(&mut self, reader: &mut R) -> Result<usize, String> {
match self.buffer.read(reader) {
Ok(bytes_read) => {
self.read_size += bytes_read;
Ok(bytes_read)
}
Err(e) => Err(e),
}
}
pub async fn async_read<R: AsyncBufRead + Unpin>(
&mut self,
reader: &mut R,
) -> Result<usize, String> {
match self.buffer.async_read(reader).await {
Ok(bytes_read) => {
self.read_size += bytes_read;
Ok(bytes_read)
}
Err(e) => Err(e),
}
}
pub fn len(&self) -> usize {
self.read_size
}
pub fn to_bytes(self) -> Vec<u8> {
match self.buffer {
BufferType::Heap(h) => h,
BufferType::Stack(s) => s[..self.read_size].to_vec(),
}
}
}
impl ToString for Buffer {
fn to_string(&self) -> String {
match &self.buffer {
BufferType::Stack(buffer) => {
String::from_utf8_lossy(&buffer[..self.read_size]).to_string()
}
BufferType::Heap(vec) => String::from_utf8_lossy(&vec[..self.read_size]).to_string(),
}
}
}
impl FromStr for Buffer {
type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(Self {
buffer: BufferType::from_str(s)?,
read_size: s.len(),
})
}
}
impl BufferType {
pub fn new(size: usize) -> Self {
if size <= PRE_ALLOCATED_BUFFER_SIZE && size > 0 {
Self::Stack([0u8; PRE_ALLOCATED_BUFFER_SIZE])
} else {
let mut vec = Vec::with_capacity(size);
vec.resize(vec.capacity(), 0);
Self::Heap(vec)
}
}
pub fn read<R: BufRead>(&mut self, reader: &mut R) -> Result<usize, String> {
match self {
Self::Stack(buffer) => reader.read(buffer).map_err(|e| e.to_string()),
Self::Heap(vec) => reader.read(vec).map_err(|e| e.to_string()),
}
}
pub async fn async_read<R: AsyncBufRead + Unpin>(
&mut self,
reader: &mut R,
) -> Result<usize, String> {
match self {
Self::Stack(buffer) => reader.read(buffer).await.map_err(|e| e.to_string()),
Self::Heap(vec) => reader.read(vec).await.map_err(|e| e.to_string()),
}
}
}
impl FromStr for BufferType {
type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let mut buffer = BufferType::new(s.len());
let bytes = s.as_bytes();
match &mut buffer {
Self::Stack(arr) => arr[..bytes.len()].copy_from_slice(bytes),
Self::Heap(vec) => vec.extend_from_slice(bytes),
}
Ok(buffer)
}
}
impl From<Vec<u8>> for Buffer {
fn from(vec: Vec<u8>) -> Self {
let read_size = vec.len();
let buffer = if read_size <= PRE_ALLOCATED_BUFFER_SIZE {
let mut stack_buffer = [0u8; PRE_ALLOCATED_BUFFER_SIZE];
stack_buffer[..read_size].copy_from_slice(&vec);
BufferType::Stack(stack_buffer)
} else {
BufferType::Heap(vec)
};
Self { buffer, read_size }
}
}