use std::borrow::Cow;
const OFFSETS: [u64; 9] = [
0,
128,
128 + (1 << 14),
128 + (1 << 14) + (1 << 21),
128 + (1 << 14) + (1 << 21) + (1 << 28),
128 + (1 << 14) + (1 << 21) + (1 << 28) + (1 << 35),
128 + (1 << 14) + (1 << 21) + (1 << 28) + (1 << 35) + (1 << 42),
128 + (1 << 14) + (1 << 21) + (1 << 28) + (1 << 35) + (1 << 42) + (1 << 49),
128 + (1 << 14) + (1 << 21) + (1 << 28) + (1 << 35) + (1 << 42) + (1 << 49) + (1 << 56),
];
#[inline]
pub fn encode_u64_varint(val: u64, out: &mut Vec<u8>) {
if val < OFFSETS[1] {
out.push(val as u8);
} else if val < OFFSETS[2] {
let adj = val - OFFSETS[1];
out.push(0x80 | (adj >> 8) as u8);
out.push(adj as u8);
} else if val < OFFSETS[3] {
let adj = val - OFFSETS[2];
out.push(0xC0 | (adj >> 16) as u8);
out.push((adj >> 8) as u8);
out.push(adj as u8);
} else if val < OFFSETS[4] {
let adj = val - OFFSETS[3];
out.push(0xE0 | (adj >> 24) as u8);
out.push((adj >> 16) as u8);
out.push((adj >> 8) as u8);
out.push(adj as u8);
} else if val < OFFSETS[5] {
let adj = val - OFFSETS[4];
out.push(0xF0 | (adj >> 32) as u8);
out.push((adj >> 24) as u8);
out.push((adj >> 16) as u8);
out.push((adj >> 8) as u8);
out.push(adj as u8);
} else if val < OFFSETS[6] {
let adj = val - OFFSETS[5];
out.push(0xF8 | (adj >> 40) as u8);
out.push((adj >> 32) as u8);
out.push((adj >> 24) as u8);
out.push((adj >> 16) as u8);
out.push((adj >> 8) as u8);
out.push(adj as u8);
} else if val < OFFSETS[7] {
let adj = val - OFFSETS[6];
out.push(0xFC | (adj >> 48) as u8);
out.push((adj >> 40) as u8);
out.push((adj >> 32) as u8);
out.push((adj >> 24) as u8);
out.push((adj >> 16) as u8);
out.push((adj >> 8) as u8);
out.push(adj as u8);
} else if val < OFFSETS[8] {
let adj = val - OFFSETS[7];
out.push(0xFE | (adj >> 56) as u8);
out.push((adj >> 48) as u8);
out.push((adj >> 40) as u8);
out.push((adj >> 32) as u8);
out.push((adj >> 24) as u8);
out.push((adj >> 16) as u8);
out.push((adj >> 8) as u8);
out.push(adj as u8);
} else {
out.push(0xFF);
out.extend_from_slice(&val.to_be_bytes());
}
}
#[inline]
pub fn decode_u64_varint(bytes: &[u8]) -> Option<(u64, usize)> {
if bytes.is_empty() {
return None;
}
let first = bytes[0];
let len = (first.leading_ones() as usize) + 1;
if len > 9 || bytes.len() < len {
return None;
}
if len == 1 {
Some((first as u64, 1))
} else if len == 9 {
let mut buf = [0u8; 8];
buf.copy_from_slice(&bytes[1..9]);
Some((u64::from_be_bytes(buf), 9))
} else {
let mask = (1u8 << (8 - len)) - 1;
let mut val = (first & mask) as u64;
for &b in &bytes[1..len] {
val = (val << 8) | (b as u64);
}
Some((val + OFFSETS[len - 1], len))
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct ScopeId {
pub tenant_id: u64,
pub db_id: u64,
}
impl ScopeId {
pub const DEFAULT: Self = Self {
tenant_id: 0,
db_id: 0,
};
pub const PREFIX_ESCAPE: [u8; 2] = [0x00, 0x00];
#[inline]
pub const fn new(tenant_id: u64, db_id: u64) -> Self {
Self { tenant_id, db_id }
}
#[inline]
pub const fn is_default(&self) -> bool {
self.tenant_id == 0 && self.db_id == 0
}
#[inline]
pub fn encode_key<'a>(&self, user_key: &'a [u8]) -> Cow<'a, [u8]> {
if self.is_default() {
if user_key.starts_with(&Self::PREFIX_ESCAPE) {
let mut out = Vec::with_capacity(6 + user_key.len());
out.extend_from_slice(&Self::PREFIX_ESCAPE);
encode_u64_varint(0, &mut out);
encode_u64_varint(0, &mut out);
out.push(b'k');
out.extend_from_slice(user_key);
Cow::Owned(out)
} else {
Cow::Borrowed(user_key)
}
} else {
let mut out = Vec::with_capacity(12 + user_key.len());
out.extend_from_slice(&Self::PREFIX_ESCAPE);
encode_u64_varint(self.tenant_id, &mut out);
encode_u64_varint(self.db_id, &mut out);
out.push(b'k');
out.extend_from_slice(user_key);
Cow::Owned(out)
}
}
#[inline]
pub fn encode_meta_key(&self, type_tag: u8, user_key: &[u8]) -> Vec<u8> {
if self.is_default() {
let mut out = Vec::with_capacity(4 + user_key.len());
out.push(0);
out.push(type_tag);
out.push(b'm');
out.push(b':');
out.extend_from_slice(user_key);
out
} else {
let mut out = Vec::with_capacity(12 + user_key.len());
out.extend_from_slice(&Self::PREFIX_ESCAPE);
encode_u64_varint(self.tenant_id, &mut out);
encode_u64_varint(self.db_id, &mut out);
out.push(type_tag.to_ascii_uppercase()); out.extend_from_slice(user_key);
out
}
}
#[inline]
pub fn encode_sub_key(
&self,
type_tag: u8,
user_key: &[u8],
version: u64,
sub_key: &[u8],
) -> Vec<u8> {
let klen = user_key.len() as u32;
if self.is_default() {
let mut out = Vec::with_capacity(14 + user_key.len() + sub_key.len());
out.push(0);
out.push(type_tag);
out.extend_from_slice(&klen.to_be_bytes());
out.extend_from_slice(user_key);
out.extend_from_slice(&version.to_be_bytes());
out.extend_from_slice(sub_key);
out
} else {
let mut out = Vec::with_capacity(20 + user_key.len() + sub_key.len());
out.extend_from_slice(&Self::PREFIX_ESCAPE);
encode_u64_varint(self.tenant_id, &mut out);
encode_u64_varint(self.db_id, &mut out);
out.push(type_tag.to_ascii_lowercase()); out.extend_from_slice(&klen.to_be_bytes());
out.extend_from_slice(user_key);
out.extend_from_slice(&version.to_be_bytes());
out.extend_from_slice(sub_key);
out
}
}
#[inline]
pub fn flush_db_prefix(&self) -> Vec<u8> {
let mut out = Vec::with_capacity(12);
out.extend_from_slice(&Self::PREFIX_ESCAPE);
encode_u64_varint(self.tenant_id, &mut out);
encode_u64_varint(self.db_id, &mut out);
out
}
#[inline]
pub fn tenant_prefix(&self) -> Vec<u8> {
let mut out = Vec::with_capacity(8);
out.extend_from_slice(&Self::PREFIX_ESCAPE);
encode_u64_varint(self.tenant_id, &mut out);
out
}
#[inline]
pub fn parse_scope(full_key: &[u8]) -> Option<ScopeId> {
if full_key.is_empty() || full_key[0] != 0 {
return Some(ScopeId::DEFAULT);
}
if full_key.len() >= 2 && full_key[1] == 0 {
let mut offset = 2;
if let Some((tenant_id, t_len)) = decode_u64_varint(&full_key[offset..]) {
offset += t_len;
if let Some((db_id, d_len)) = decode_u64_varint(&full_key[offset..]) {
offset += d_len;
if full_key.len() > offset {
return Some(ScopeId::new(tenant_id, db_id));
}
}
}
}
Some(ScopeId::DEFAULT)
}
#[inline]
pub fn extract_user_key(full_key: &[u8]) -> Option<&[u8]> {
if full_key.is_empty() || full_key[0] != 0 {
return Some(full_key);
}
if full_key.len() >= 2 && full_key[1] == 0 {
let mut offset = 2;
if let Some((_, t_len)) = decode_u64_varint(&full_key[offset..]) {
offset += t_len;
if let Some((_, d_len)) = decode_u64_varint(&full_key[offset..]) {
offset += d_len;
if full_key.len() > offset {
let tag = full_key[offset];
offset += 1;
let body = &full_key[offset..];
if tag.is_ascii_uppercase() || tag == b'k' {
return Some(body);
} else if body.len() >= 4 {
let mut len_buf = [0u8; 4];
len_buf.copy_from_slice(&body[..4]);
let klen = u32::from_be_bytes(len_buf) as usize;
if body.len() >= 4 + klen {
return Some(&body[4..4 + klen]);
}
}
}
}
}
}
if full_key.len() >= 4 && full_key[2] == b'm' && full_key[3] == b':' {
Some(&full_key[4..])
} else if full_key.len() >= 6 {
let mut len_buf = [0u8; 4];
len_buf.copy_from_slice(&full_key[2..6]);
let klen = u32::from_be_bytes(len_buf) as usize;
if full_key.len() >= 6 + klen + 8 {
return Some(&full_key[6..6 + klen]);
}
Some(full_key)
} else {
Some(full_key)
}
}
}