pub use crate::meta::KeyMeta as StringMeta;
use crate::meta::{KeyMeta, RedisType};
pub const STRING_HDR_SIZE: usize = KeyMeta::KVROCKS_SINGLE_KV_ENCODED_SIZE;
#[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],
]
}
pub const STRING_NO_EXPIRY_HEADER: [u8; STRING_HDR_SIZE] = encode_string_header(0);
#[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
}
#[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);
}
pub const STRING_HEADER_FLAG: u8 = KeyMeta::META_64BIT_ENCODING_MASK | (RedisType::String as u8);
#[inline(always)]
pub fn decode_string_value(raw: &[u8]) -> (u64, &[u8]) {
if raw.len() >= STRING_HDR_SIZE && raw[0] == STRING_HEADER_FLAG {
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
}
#[inline(always)]
pub fn with_encoded_string_value<R>(
val_bytes: &[u8],
expire_at_ms: u64,
dyn_buf: &mut Vec<u8>,
f: impl FnOnce(&[u8]) -> R,
) -> R {
if val_bytes.len() <= 55 {
let mut stack_buf = [0u8; 64];
let header = if expire_at_ms == 0 {
STRING_NO_EXPIRY_HEADER
} else {
encode_string_header(expire_at_ms)
};
stack_buf[..STRING_HDR_SIZE].copy_from_slice(&header);
let total = STRING_HDR_SIZE + val_bytes.len();
stack_buf[STRING_HDR_SIZE..total].copy_from_slice(val_bytes);
f(&stack_buf[..total])
} else {
dyn_buf.clear();
encode_string_value_into(val_bytes, expire_at_ms, dyn_buf);
f(dyn_buf)
}
}