use std::ptr;
pub struct StringBuffer {
buffer: Vec<u8>,
index: usize,
}
impl StringBuffer {
pub fn with_capacity_fill(num_chars: usize, fill_char: char) -> StringBuffer {
let buffer = fill_char.to_string().into_bytes().repeat(num_chars * 4);
StringBuffer { buffer, index: 0 }
}
pub fn with_capacity(num_chars: usize) -> StringBuffer {
StringBuffer {
buffer: vec![0; num_chars * 4],
index: 0,
}
}
fn get_start_pointer(&mut self) -> *mut u8 {
unsafe { self.buffer.as_mut_ptr().offset(self.index as isize) }
}
fn write(&mut self, bytes: &[u8]) {
unsafe { ptr::copy_nonoverlapping(bytes.as_ptr(), self.get_start_pointer(), bytes.len()) }
}
pub fn push_bytes_fixed_width(&mut self, c: &[u8], num_chars: usize) {
self.write(c);
self.index += num_chars;
}
pub fn push_bytes(&mut self, c: &[u8]) {
self.write(c);
self.index += c.len();
}
pub fn push_chars(&mut self, c: impl AsRef<str>) {
self.push_bytes(c.as_ref().as_bytes())
}
pub fn push_chars_fixed_width(&mut self, c: impl AsRef<str>, num_chars: usize) {
self.push_bytes_fixed_width(c.as_ref().as_bytes(), num_chars)
}
pub fn into_buffer(mut self) -> Vec<u8> {
self.buffer.truncate(self.index);
self.buffer
}
}
impl std::fmt::Display for StringBuffer {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"{}",
std::str::from_utf8(&self.buffer[..self.index]).unwrap()
)
}
}