use std::{mem::MaybeUninit, ptr, slice};
#[repr(u8)]
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub enum TreePrefix {
ZSetScore = 0x01,
ZSetMember = 0x02,
SetMember = 0x03,
ListIndex = 0x04,
RangeIndexKey = 0x05,
HashField = 0x06,
}
pub const STACK_KEY_BUF_SIZE: usize = 1024;
impl TreePrefix {
#[inline(always)]
pub const fn as_u8(self) -> u8 {
self as u8
}
#[inline(always)]
pub const fn from_u8(val: u8) -> Option<Self> {
match val {
0x01 => Some(Self::ZSetScore),
0x02 => Some(Self::ZSetMember),
0x03 => Some(Self::SetMember),
0x04 => Some(Self::ListIndex),
0x05 => Some(Self::RangeIndexKey),
0x06 => Some(Self::HashField),
_ => None,
}
}
}
impl From<TreePrefix> for u8 {
#[inline(always)]
fn from(prefix: TreePrefix) -> Self {
prefix as Self
}
}
impl TryFrom<u8> for TreePrefix {
type Error = crate::CollectionError;
#[inline]
fn try_from(val: u8) -> Result<Self, Self::Error> {
Self::from_u8(val).ok_or(crate::CollectionError::InvalidArgument("无效的树前缀"))
}
}
#[inline]
pub fn with_prefixed_key<R>(prefix: u8, sub_key: &[u8], f: impl FnOnce(&[u8]) -> R) -> R {
let total_len = 1 + sub_key.len();
if total_len <= STACK_KEY_BUF_SIZE {
let mut buf = [MaybeUninit::<u8>::uninit(); STACK_KEY_BUF_SIZE];
unsafe {
let ptr = buf.as_mut_ptr() as *mut u8;
*ptr = prefix;
ptr::copy_nonoverlapping(sub_key.as_ptr(), ptr.add(1), sub_key.len());
f(slice::from_raw_parts(ptr, total_len))
}
} else {
let mut buf = Vec::with_capacity(total_len);
buf.push(prefix);
buf.extend_from_slice(sub_key);
f(&buf)
}
}
#[inline]
pub fn with_prefixed_key2<R>(
prefix: u8,
part1: &[u8],
part2: &[u8],
f: impl FnOnce(&[u8]) -> R,
) -> R {
let total_len = 1 + part1.len() + part2.len();
if total_len <= STACK_KEY_BUF_SIZE {
let mut buf = [MaybeUninit::<u8>::uninit(); STACK_KEY_BUF_SIZE];
unsafe {
let ptr = buf.as_mut_ptr() as *mut u8;
*ptr = prefix;
ptr::copy_nonoverlapping(part1.as_ptr(), ptr.add(1), part1.len());
ptr::copy_nonoverlapping(part2.as_ptr(), ptr.add(1 + part1.len()), part2.len());
f(slice::from_raw_parts(ptr, total_len))
}
} else {
let mut buf = Vec::with_capacity(total_len);
buf.push(prefix);
buf.extend_from_slice(part1);
buf.extend_from_slice(part2);
f(&buf)
}
}