macro_rules! stack_heap_buf {
(
$(#[$enum_meta:meta])*
$name:ident, $cap:expr
) => {
$(#[$enum_meta])*
#[derive(Debug, Clone)]
pub enum $name {
Stack([u8; $cap], u8),
Heap(Vec<u8>),
}
impl ::core::ops::Deref for $name {
type Target = [u8];
#[inline(always)]
fn deref(&self) -> &Self::Target {
match self {
Self::Stack(buf, len) => {
let len = (*len as usize).min($cap);
unsafe { buf.get_unchecked(..len) }
}
Self::Heap(vec) => vec.as_slice(),
}
}
}
impl AsRef<[u8]> for $name {
#[inline(always)]
fn as_ref(&self) -> &[u8] {
self.as_slice()
}
}
impl ::core::borrow::Borrow<[u8]> for $name {
#[inline(always)]
fn borrow(&self) -> &[u8] {
self.as_slice()
}
}
impl PartialEq for $name {
#[inline(always)]
fn eq(&self, other: &Self) -> bool {
$crate::simd::fast_key_eq(self.as_slice(), other.as_slice())
}
}
impl Eq for $name {}
impl PartialOrd for $name {
#[inline(always)]
fn partial_cmp(&self, other: &Self) -> Option<::core::cmp::Ordering> {
Some(self.cmp(other))
}
}
impl Ord for $name {
#[inline(always)]
fn cmp(&self, other: &Self) -> ::core::cmp::Ordering {
self.as_slice().cmp(other.as_slice())
}
}
impl ::core::hash::Hash for $name {
#[inline(always)]
fn hash<H: ::core::hash::Hasher>(&self, state: &mut H) {
self.as_slice().hash(state);
}
}
impl PartialEq<[u8]> for $name {
#[inline(always)]
fn eq(&self, other: &[u8]) -> bool {
$crate::simd::fast_key_eq(self.as_slice(), other)
}
}
impl PartialEq<&[u8]> for $name {
#[inline(always)]
fn eq(&self, other: &&[u8]) -> bool {
$crate::simd::fast_key_eq(self.as_slice(), other)
}
}
impl From<Vec<u8>> for $name {
#[inline]
fn from(vec: Vec<u8>) -> Self {
if vec.len() <= $cap {
let mut buf = [0u8; $cap];
buf[..vec.len()].copy_from_slice(&vec);
Self::Stack(buf, vec.len() as u8)
} else {
Self::Heap(vec)
}
}
}
impl From<&[u8]> for $name {
#[inline]
fn from(slice: &[u8]) -> Self {
if slice.len() <= $cap {
let mut buf = [0u8; $cap];
buf[..slice.len()].copy_from_slice(slice);
Self::Stack(buf, slice.len() as u8)
} else {
Self::Heap(slice.to_vec())
}
}
}
impl $name {
#[inline(always)]
pub fn as_slice(&self) -> &[u8] {
self
}
#[inline(always)]
pub fn len(&self) -> usize {
self.as_slice().len()
}
#[inline(always)]
pub fn is_empty(&self) -> bool {
self.len() == 0
}
#[inline(always)]
pub const fn is_stack(&self) -> bool {
matches!(self, Self::Stack(..))
}
#[inline(always)]
pub const fn is_heap(&self) -> bool {
matches!(self, Self::Heap(..))
}
#[inline]
pub fn into_vec(self) -> Vec<u8> {
match self {
Self::Stack(buf, len) => {
let len = (len as usize).min($cap);
unsafe { buf.get_unchecked(..len) }.to_vec()
}
Self::Heap(vec) => vec,
}
}
}
};
}
pub(crate) use stack_heap_buf;