use crate::meta::{KeyMeta, RedisType, generate_version};
use serde::{Deserialize, Serialize};
pub use super::sortable::{decode_sortable_f64, encode_sortable_f64};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub struct ZSetMeta {
pub base: KeyMeta,
}
impl ZSetMeta {
pub const ENCODED_SIZE: usize = KeyMeta::ENCODED_SIZE;
pub const KVROCKS_ENCODED_SIZE: usize = KeyMeta::KVROCKS_COMPLEX_ENCODED_SIZE;
#[inline]
pub fn new(expire_at: u64, version: u64, size: u64) -> Self {
Self {
base: KeyMeta::new(RedisType::ZSet, expire_at, version, size),
}
}
#[inline]
pub fn new_with_version(expire_at: u64, size: u64) -> Self {
Self {
base: KeyMeta::new(RedisType::ZSet, expire_at, generate_version(), size),
}
}
#[inline]
pub const fn size(&self) -> u64 {
self.base.size
}
#[inline]
pub const fn is_empty(&self) -> bool {
self.base.size == 0
}
#[inline]
pub fn is_expired(&self, now_ms: u64) -> bool {
self.base.is_expired(now_ms)
}
#[inline]
pub fn encode(&self) -> [u8; Self::ENCODED_SIZE] {
self.base.encode()
}
#[inline]
pub fn encode_kvrocks(&self) -> Vec<u8> {
self.base.encode_kvrocks()
}
#[inline]
pub fn decode(bytes: &[u8]) -> Option<Self> {
let base = KeyMeta::decode(bytes)?;
if base.rtype == RedisType::ZSet {
Some(Self { base })
} else {
None
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_zset_meta_roundtrip() {
let meta = ZSetMeta::new(1700000000000, 202, 88);
let enc = meta.encode();
assert_eq!(enc.len(), ZSetMeta::ENCODED_SIZE);
let dec = ZSetMeta::decode(&enc).expect("decode failed");
assert_eq!(dec.base.rtype, RedisType::ZSet);
assert_eq!(dec.base.expire_at, 1700000000000);
assert_eq!(dec.base.version, 202);
assert_eq!(dec.base.size, 88);
let kv_enc = meta.encode_kvrocks();
assert_eq!(kv_enc.len(), ZSetMeta::KVROCKS_ENCODED_SIZE);
let kv_dec = ZSetMeta::decode(&kv_enc).expect("decode kvrocks failed");
assert_eq!(kv_dec.base.rtype, RedisType::ZSet);
assert_eq!(kv_dec.base.expire_at, 1700000000000);
assert_eq!(kv_dec.base.version, 202);
assert_eq!(kv_dec.base.size, 88);
}
#[test]
fn test_score_sortable_f64_ordering() {
let test_values = vec![
f64::NEG_INFINITY,
-1000.5,
-1.0,
-0.0001,
-0.0,
0.0,
0.0001,
1.0,
1000.5,
f64::INFINITY,
];
for i in 0..test_values.len() - 1 {
let a = test_values[i];
let b = test_values[i + 1];
let enc_a = encode_sortable_f64(a);
let enc_b = encode_sortable_f64(b);
assert!(
enc_a <= enc_b,
"Ordering failed for {} vs {}: {:?} vs {:?}",
a,
b,
enc_a,
enc_b
);
let dec_a = decode_sortable_f64(enc_a);
let dec_b = decode_sortable_f64(enc_b);
if a.is_nan() {
assert!(dec_a.is_nan());
} else if a == 0.0 && dec_a == 0.0 {
} else {
assert_eq!(a, dec_a);
}
if b.is_nan() {
assert!(dec_b.is_nan());
} else if b == 0.0 && dec_b == 0.0 {
} else {
assert_eq!(b, dec_b);
}
}
}
}