use core::str;
use std::{error::Error, fmt, ptr};
#[derive(Default, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct ConstantSizeString {
pub vec: Vec<u8>,
}
impl ConstantSizeString {
#[inline]
#[must_use]
pub unsafe fn new(vec: Vec<u8>) -> Self {
Self { vec }
}
pub unsafe fn push_byte(&mut self, byte: u8) -> Result<(), Overflow> {
let len = self.vec.len();
if len < self.vec.capacity() {
let ptr = unsafe { self.vec.as_mut_ptr().add(len) };
unsafe {
*ptr = byte;
}
unsafe {
#[allow(clippy::arithmetic_side_effects)]
self.vec.set_len(len + 1);
}
Ok(())
} else {
Err(Overflow)
}
}
pub unsafe fn push_bytes(&mut self, bytes: &[u8]) -> Result<(), Overflow> {
#[allow(clippy::arithmetic_side_effects)]
let len = self.vec.len() + bytes.len();
if len > self.vec.capacity() {
Err(Overflow)
} else {
let ptr = unsafe { self.vec.as_mut_ptr().add(self.vec.len()) };
unsafe {
ptr::copy(bytes.as_ptr(), ptr, bytes.len());
}
unsafe {
self.vec.set_len(len);
}
Ok(())
}
}
#[inline]
pub fn pop_byte(&mut self) -> Option<u8> {
self.vec.pop()
}
#[inline]
pub fn clear(&mut self) {
unsafe { self.vec.set_len(0) }
}
#[inline]
#[must_use]
pub fn len(&self) -> usize {
self.vec.len()
}
#[must_use]
pub fn is_empty(&self) -> bool {
self.len() == 0
}
#[must_use]
pub fn get(&self, index: usize) -> Option<u8> {
self.vec.get(index).copied()
}
pub fn set(&mut self, index: usize, value: u8) -> Result<(), Overflow> {
self.vec.get_mut(index).map_or(Err(Overflow), |v| {
*v = value;
Ok(())
})
}
}
impl fmt::Debug for ConstantSizeString {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
#[allow(clippy::expect_used)]
fmt::Debug::fmt(
str::from_utf8(&self.vec).expect("invalid `ConstantSizeString` print attempts"),
f,
)
}
}
impl fmt::Display for ConstantSizeString {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
#[allow(clippy::expect_used)]
f.write_str(str::from_utf8(&self.vec).expect("invalid `ConstantSizeString` print attempts"))
}
}
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Overflow;
impl fmt::Display for Overflow {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("Overflow")
}
}
impl Error for Overflow {}