use off64::u8;
use off64::usz;
use std::cmp::Ordering;
use std::fmt;
use std::fmt::Debug;
use std::fmt::Formatter;
use std::hash::Hash;
use std::hash::Hasher;
use std::mem::size_of;
use std::ops::Deref;
const WORD_SIZE: usize = size_of::<usize>();
const ARRAY_CAP: usize = WORD_SIZE * 4 - 2;
pub enum TinyBuf {
Array(u8, [u8; ARRAY_CAP]),
BoxDyn(Box<dyn AsRef<[u8]> + Send + Sync + 'static>),
BoxSlice(Box<[u8]>),
Static(&'static [u8]),
Vec(Vec<u8>),
}
static_assertions::const_assert_eq!(size_of::<Vec<u8>>(), WORD_SIZE * 3);
static_assertions::const_assert_eq!(size_of::<Box<dyn AsRef<[u8]>>>(), WORD_SIZE * 2);
static_assertions::const_assert_eq!(size_of::<TinyBuf>(), WORD_SIZE * 4);
impl TinyBuf {
pub fn as_slice(&self) -> &[u8] {
match self {
TinyBuf::Array(len, v) => &v[..usz!(*len)],
TinyBuf::BoxDyn(v) => v.as_ref().as_ref(),
TinyBuf::BoxSlice(v) => v,
TinyBuf::Static(v) => v,
TinyBuf::Vec(v) => v.as_slice(),
}
}
}
impl AsRef<[u8]> for TinyBuf {
fn as_ref(&self) -> &[u8] {
self.as_slice()
}
}
impl Deref for TinyBuf {
type Target = [u8];
fn deref(&self) -> &Self::Target {
self.as_slice()
}
}
impl Clone for TinyBuf {
fn clone(&self) -> Self {
Self::Vec(self.as_slice().to_vec())
}
}
impl PartialEq for TinyBuf {
fn eq(&self, other: &Self) -> bool {
self.as_slice() == other.as_slice()
}
}
impl Eq for TinyBuf {}
impl PartialOrd for TinyBuf {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
self.as_slice().partial_cmp(other.as_slice())
}
}
impl Ord for TinyBuf {
fn cmp(&self, other: &Self) -> Ordering {
self.as_slice().cmp(other.as_slice())
}
}
impl Hash for TinyBuf {
fn hash<H: Hasher>(&self, state: &mut H) {
self.as_slice().hash(state);
}
}
impl Debug for TinyBuf {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
self.as_slice().fmt(f)
}
}
impl<const N: usize> From<[u8; N]> for TinyBuf {
fn from(value: [u8; N]) -> Self {
if N <= ARRAY_CAP {
let mut array = [0u8; ARRAY_CAP];
array[..N].copy_from_slice(&value);
Self::Array(u8!(N), array)
} else {
Self::BoxSlice(Box::new(value))
}
}
}
impl From<Box<dyn AsRef<[u8]> + Send + Sync + 'static>> for TinyBuf {
fn from(value: Box<dyn AsRef<[u8]> + Send + Sync + 'static>) -> Self {
Self::BoxDyn(value)
}
}
impl From<Box<[u8]>> for TinyBuf {
fn from(value: Box<[u8]>) -> Self {
Self::BoxSlice(value)
}
}
impl From<&'static [u8]> for TinyBuf {
fn from(value: &'static [u8]) -> Self {
Self::Static(value)
}
}
impl From<Vec<u8>> for TinyBuf {
fn from(value: Vec<u8>) -> Self {
Self::Vec(value)
}
}