wedb_embed 0.1.2

Embedded database engine providing Redis-like APIs, built on fjall / 嵌入式数据库引擎,提供类似 Redis 的接口,底层基于 fjall 开发
Documentation
pub use crate::meta::KeyMeta as StringMeta;
use crate::meta::{KeyMeta, RedisType};

/// 单 KV 字符串头部大小(1字节flags + 8字节过期时间,对标 Apache Kvrocks SingleKV 9字节头)
pub const STRING_HDR_SIZE: usize = KeyMeta::KVROCKS_SINGLE_KV_ENCODED_SIZE;

/// 生成 9 字节 SingleKV 紧凑元数据头(1字节flags + 8字节大端过期毫秒时间戳)
#[inline]
pub const fn encode_string_header(expire_at_ms: u64) -> [u8; STRING_HDR_SIZE] {
  let flags = KeyMeta::META_64BIT_ENCODING_MASK | (RedisType::String as u8);
  let exp = expire_at_ms.to_be_bytes();
  [
    flags, exp[0], exp[1], exp[2], exp[3], exp[4], exp[5], exp[6], exp[7],
  ]
}

/// 预计算无过期时间的 9 字节 SingleKV 常量头部(编译期常量,零运行时计算开销)
pub const STRING_NO_EXPIRY_HEADER: [u8; STRING_HDR_SIZE] = encode_string_header(0);

/// 编码 SingleKV 字符串值(9 字节元数据头 + 载荷,对标 Apache Kvrocks Metadata::Encode + payload)
#[inline]
pub fn encode_string_value(value: &[u8], expire_at_ms: u64) -> Vec<u8> {
  let mut out = Vec::with_capacity(STRING_HDR_SIZE + value.len());
  if expire_at_ms == 0 {
    out.extend_from_slice(&STRING_NO_EXPIRY_HEADER);
  } else {
    out.extend_from_slice(&encode_string_header(expire_at_ms));
  }
  out.extend_from_slice(value);
  out
}

/// 将 9 字节头与载荷写入指定 Vec 缓冲区,避免额外堆分配
#[inline]
pub fn encode_string_value_into(value: &[u8], expire_at_ms: u64, out: &mut Vec<u8>) {
  out.reserve(STRING_HDR_SIZE + value.len());
  if expire_at_ms == 0 {
    out.extend_from_slice(&STRING_NO_EXPIRY_HEADER);
  } else {
    out.extend_from_slice(&encode_string_header(expire_at_ms));
  }
  out.extend_from_slice(value);
}

/// 解码 SingleKV 字符串值(9 字节紧凑元数据头 + 载荷)
#[inline(always)]
pub fn decode_string_value(raw: &[u8]) -> (u64, &[u8]) {
  if raw.len() >= STRING_HDR_SIZE
    && (raw[0] & KeyMeta::META_64BIT_ENCODING_MASK != 0)
    && (raw[0] & KeyMeta::META_TYPE_MASK == RedisType::String as u8)
  {
    let exp = u64::from_be_bytes([
      raw[1], raw[2], raw[3], raw[4], raw[5], raw[6], raw[7], raw[8],
    ]);
    (exp, &raw[STRING_HDR_SIZE..])
  } else {
    (0, raw)
  }
}

/// 检查字符串是否已过期
#[inline]
pub const fn is_string_expired(expire_at_ms: u64, now_ms: u64) -> bool {
  expire_at_ms > 0 && expire_at_ms <= now_ms
}