use crate::util::byte::is_whitespace;
use std::io;
use std::str::from_utf8;
use serde::{Serialize, Serializer};
pub const SIZE: usize = 1024;
#[derive(Debug)]
pub struct Buffer {
pub len: usize,
pub b: [u8; SIZE],
}
pub trait BufferLike {
fn clear(&mut self);
fn clear_unmanaged(&mut self);
fn clear_unmanaged_backwards(&mut self);
fn trim(&self) -> &[u8];
fn unmanaged_len(&self) -> usize;
fn content(&self) -> &[u8];
fn content_unmanaged(&self) -> &[u8];
}
impl Buffer {
pub fn from_str_truncate<A: AsRef<str>>(src: A) -> Self {
let mut buffer = Self::default();
let mut len = 0;
for (i, b) in src.as_ref().bytes().enumerate() {
if i >= SIZE {
break;
}
buffer.b[i] = b;
len += 1;
}
buffer.len = len;
buffer
}
#[must_use]
pub const fn new() -> Self {
Self {
len: 0,
b: [0; SIZE],
}
}
}
impl Default for Buffer {
fn default() -> Self { Self::new() }
}
impl Serialize for Buffer {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
use serde::ser::Error;
match from_utf8(self.content()) {
Ok(string) => serializer.serialize_str(string),
Err(err) => Err(Error::custom(err)),
}
}
}
impl io::Write for Buffer {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
let mut len = 0;
for (i, b) in buf.iter().enumerate() {
if i >= SIZE {
break;
}
self.b[i] = *b;
len += 1;
}
self.len = len;
Ok(len)
}
fn flush(&mut self) -> io::Result<()> { Ok(()) }
}
impl BufferLike for Buffer {
#[inline]
#[must_use]
fn trim(&self) -> &[u8] {
if self.len == 0 {
return &self.b[0..0];
}
let mut start = 0;
while start < self.len && is_whitespace(self.b[start]) {
start += 1;
}
let mut end = self.len - 1;
while end > start && is_whitespace(self.b[end]) {
end -= 1;
}
&self.b[start..=end]
}
#[inline]
#[must_use]
fn content_unmanaged(&self) -> &[u8] {
let mut end = 0;
while end < self.b.len() && self.b[end] != 0_u8 {
end += 1;
}
&self.b[0..end]
}
#[inline]
fn content(&self) -> &[u8] { &self.b[0..self.len] }
#[inline]
fn clear(&mut self) {
for i in 0..self.len {
self.b[i] = 0_u8;
}
self.len = 0;
}
#[inline]
fn clear_unmanaged(&mut self) {
for i in 0..SIZE {
if self.b[i] == 0_u8 {
break;
} else {
self.b[i] = 0_u8;
}
}
self.len = 0;
}
#[inline]
fn clear_unmanaged_backwards(&mut self) {
for i in (0..SIZE).rev() {
if self.b[i] == 0_u8 {
break;
} else {
self.b[i] = 0_u8;
}
}
self.len = 0;
}
#[inline]
#[must_use]
fn unmanaged_len(&self) -> usize { content_len_raw(&self.b) }
}
#[inline]
#[must_use]
pub fn content_len_raw(buf: &[u8]) -> usize {
let mut len: usize = 0;
for byte in buf {
if *byte == 0_u8 {
break;
} else {
len += 1;
}
}
len
}
#[inline]
#[must_use]
pub fn trim_raw(buf: &[u8]) -> &[u8] {
let len: usize = content_len_raw(buf);
if len == 0 {
return &buf[0..=0];
}
let mut start = 0;
while start < len && is_whitespace(buf[start]) {
start += 1;
}
let mut end = len - 1;
while end > start && is_whitespace(buf[end]) {
end -= 1;
}
&buf[start..=end]
}