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);
}
#[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
}