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 fn encode_string_value(value: &[u8], expire_at_ms: u64) -> Vec<u8> {
let flags = KeyMeta::META_64BIT_ENCODING_MASK | (RedisType::String as u8);
let mut out = Vec::with_capacity(STRING_HDR_SIZE + value.len());
out.push(flags);
out.extend_from_slice(&expire_at_ms.to_be_bytes());
out.extend_from_slice(value);
out
}
#[inline]
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 expire_at = u64::from_be_bytes(raw[1..STRING_HDR_SIZE].try_into().unwrap_or_default());
(expire_at, &raw[STRING_HDR_SIZE..])
} else if raw.len() >= 5 && raw[0] == RedisType::String as u8 {
let expire_sec = u32::from_be_bytes(raw[1..5].try_into().unwrap_or_default()) as u64;
let expire_ms = if expire_sec > 0 { expire_sec * 1000 } else { 0 };
(expire_ms, &raw[5..])
} 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
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_string_value_roundtrip() {
let val = b"hello string";
let expire = 1_850_000_000_000;
let enc = encode_string_value(val, expire);
assert_eq!(enc.len(), STRING_HDR_SIZE + val.len());
assert_eq!(enc[0], 0x81);
let (dec_exp, dec_val) = decode_string_value(&enc);
assert_eq!(dec_exp, expire);
assert_eq!(dec_val, val);
let enc_raw = encode_string_value(val, 0);
assert_eq!(enc_raw.len(), STRING_HDR_SIZE + val.len());
assert_eq!(enc_raw[0], 0x81);
let (dec_exp0, dec_val0) = decode_string_value(&enc_raw);
assert_eq!(dec_exp0, 0);
assert_eq!(dec_val0, val);
}
#[test]
fn test_string_legacy_32bit_decode() {
let val = b"legacy value";
let mut legacy = vec![0x01]; legacy.extend_from_slice(&12345u32.to_be_bytes()); legacy.extend_from_slice(val);
let (dec_exp, dec_val) = decode_string_value(&legacy);
assert_eq!(dec_exp, 12345000);
assert_eq!(dec_val, val);
}
}