seq_marked/
seq_value_trait.rs

1use crate::Expirable;
2#[cfg(doc)]
3use crate::SeqMarked;
4
5/// Trait for a value with a sequence number and metadata.
6///
7/// [`SeqValue`] is intended for application use and does not include a tombstone concept,
8/// unlike [`SeqMarked`] which is for LSM internals.
9pub trait SeqValue<M, V = Vec<u8>> {
10    /// Return the sequence number of the value.
11    fn seq(&self) -> u64;
12
13    /// Return the reference of the value.
14    fn value(&self) -> Option<&V>;
15
16    /// Consume the value and return the value.
17    fn into_value(self) -> Option<V>;
18
19    /// Return the reference of metadata of the value.
20    fn meta(&self) -> Option<&M>;
21
22    /// Consume self and return the sequence number and the value.
23    fn unpack(self) -> (u64, Option<V>)
24    where Self: Sized {
25        (self.seq(), self.into_value())
26    }
27
28    /// Return the absolute expire time in millisecond since 1970-01-01 00:00:00.
29    fn expires_at_ms_opt(&self) -> Option<u64>
30    where M: Expirable {
31        let meta = self.meta()?;
32        meta.expires_at_ms_opt()
33    }
34
35    /// Returns the absolute expiration time in milliseconds since the Unix epoch (1970-01-01
36    /// 00:00:00 UTC).
37    ///
38    /// If no expiration time is set, returns `u64::MAX`, effectively meaning the value never
39    /// expires. This method provides a consistent way to handle both expiring and non-expiring
40    /// values.
41    fn expires_at_ms(&self) -> u64
42    where M: Expirable {
43        self.meta().expires_at_ms()
44    }
45
46    /// Return true if the record is expired at the given time in milliseconds since the Unix epoch
47    /// (1970-01-01 00:00:00 UTC).
48    fn is_expired(&self, now_ms: u64) -> bool
49    where M: Expirable {
50        self.expires_at_ms() < now_ms
51    }
52}
53
54#[cfg(test)]
55mod tests {
56    use super::*;
57    use crate::testing::*;
58
59    #[test]
60    fn test_seq_value_basic() {
61        let sv = SeqValueImpl {
62            seq: 42,
63            value: Some(100),
64            meta: None,
65        };
66
67        assert_eq!(sv.seq(), 42);
68        assert_eq!(sv.value(), Some(&100));
69        assert_eq!(sv.meta(), None);
70
71        let (seq, value) = sv.unpack();
72        assert_eq!(seq, 42);
73        assert_eq!(value, Some(100));
74    }
75
76    #[test]
77    fn test_seq_value_with_expiration() {
78        let sv = SeqValueImpl {
79            seq: 1,
80            value: Some(200),
81            meta: Some(ExpirableImpl {
82                expires_at_ms: Some(1000),
83            }),
84        };
85
86        assert_eq!(sv.expires_at_ms_opt(), Some(1000));
87        assert_eq!(sv.expires_at_ms(), 1000);
88        assert!(sv.is_expired(1001));
89        assert!(!sv.is_expired(999));
90    }
91
92    #[test]
93    fn test_seq_value_no_expiration() {
94        let sv = SeqValueImpl {
95            seq: 2,
96            value: None,
97            meta: Some(ExpirableImpl {
98                expires_at_ms: None,
99            }),
100        };
101
102        assert_eq!(sv.expires_at_ms_opt(), None);
103        assert_eq!(sv.expires_at_ms(), u64::MAX);
104        assert!(!sv.is_expired(u64::MAX - 1));
105    }
106}