seq_marked/seqv/
mod.rs

1mod impl_from_seq_marked;
2mod impl_seq_value;
3
4use std::fmt;
5use std::ops::Deref;
6use std::ops::DerefMut;
7
8/// Some value bound with a seq number.
9///
10/// [`SeqV`] is the meta-service API level generic value.
11/// Meta-service application uses this type to interact with meta-service.
12///
13/// Inside the meta-service, the value is stored in the form of `Marked`, which could be a
14/// tombstone. A `Marked::TombStone` is converted to `None::<SeqV>` and a `Marked::Normal` is
15/// converted to `Some::<SeqV>`.
16///
17/// A `Marked::TombStone` also has an `internal_seq`, representing the freshness of the tombstone.
18/// `internal_seq` will be discarded when `Marked::TombStone` is converted to `None::<SeqV>`.
19#[derive(Default, Clone, Eq, PartialEq)]
20#[cfg_attr(feature = "seqv-serde", derive(serde::Serialize, serde::Deserialize))]
21pub struct SeqV<M, T = Vec<u8>> {
22    pub seq: u64,
23    pub meta: Option<M>,
24    pub data: T,
25}
26
27impl<M, T> Deref for SeqV<M, T> {
28    type Target = T;
29
30    fn deref(&self) -> &Self::Target {
31        &self.data
32    }
33}
34
35impl<M, T> DerefMut for SeqV<M, T> {
36    fn deref_mut(&mut self) -> &mut Self::Target {
37        &mut self.data
38    }
39}
40
41impl<M, T> fmt::Debug for SeqV<M, T>
42where
43    M: fmt::Debug,
44    T: fmt::Debug,
45{
46    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
47        let mut de = f.debug_struct("SeqV");
48        de.field("seq", &self.seq);
49        de.field("meta", &self.meta);
50        de.field("data", &"[binary]");
51
52        de.finish()
53    }
54}
55
56impl<M, T> SeqV<M, T> {
57    pub fn new(seq: u64, data: T) -> Self {
58        Self {
59            seq,
60            meta: None,
61            data,
62        }
63    }
64
65    pub fn new_with_meta(seq: u64, meta: Option<M>, data: T) -> Self {
66        Self { seq, meta, data }
67    }
68
69    #[must_use]
70    pub fn with_seq(mut self, seq: u64) -> Self {
71        self.seq = seq;
72        self
73    }
74
75    #[must_use]
76    pub fn with_meta(mut self, m: Option<M>) -> Self {
77        self.meta = m;
78        self
79    }
80
81    #[must_use]
82    pub fn with_value(mut self, v: T) -> Self {
83        self.data = v;
84        self
85    }
86
87    /// Convert data to type U and leave seq and meta unchanged.
88    pub fn map<U>(self, f: impl FnOnce(T) -> U) -> SeqV<M, U> {
89        SeqV {
90            seq: self.seq,
91            meta: self.meta,
92            data: f(self.data),
93        }
94    }
95
96    /// Try to convert data to type U and leave seq and meta unchanged.
97    /// `f` returns an error if the conversion fails.
98    pub fn try_map<U, E>(self, f: impl FnOnce(T) -> Result<U, E>) -> Result<SeqV<M, U>, E> {
99        Ok(SeqV {
100            seq: self.seq,
101            meta: self.meta,
102            data: f(self.data)?,
103        })
104    }
105}
106
107#[cfg(test)]
108mod tests {
109    use super::*;
110
111    #[test]
112    fn test_new() {
113        let sv = SeqV::<(), _>::new(42, 100u64);
114        assert_eq!(sv.seq, 42);
115        assert_eq!(sv.meta, None);
116        assert_eq!(sv.data, 100);
117    }
118
119    #[test]
120    fn test_new_with_meta() {
121        let sv = SeqV::new_with_meta(10, Some("metadata"), 200u64);
122        assert_eq!(sv.seq, 10);
123        assert_eq!(sv.meta, Some("metadata"));
124        assert_eq!(sv.data, 200);
125
126        let sv_none = SeqV::new_with_meta(5, None::<String>, 300u64);
127        assert_eq!(sv_none.meta, None);
128    }
129
130    #[test]
131    fn test_builder_methods() {
132        let sv = SeqV::new(1, 100u64).with_seq(42).with_meta(Some("test")).with_value(200u64);
133
134        assert_eq!(sv.seq, 42);
135        assert_eq!(sv.meta, Some("test"));
136        assert_eq!(sv.data, 200);
137    }
138
139    #[test]
140    fn test_map() {
141        let sv = SeqV::new_with_meta(10, Some("meta"), 5u64);
142        let mapped = sv.map(|x| x * 2);
143
144        assert_eq!(mapped.seq, 10);
145        assert_eq!(mapped.meta, Some("meta"));
146        assert_eq!(mapped.data, 10u64);
147    }
148
149    #[test]
150    fn test_try_map_success() {
151        let sv = SeqV::new_with_meta(20, Some("meta"), "123");
152        let result = sv.try_map(|s| s.parse::<u64>());
153
154        assert!(result.is_ok());
155        let mapped = result.unwrap();
156        assert_eq!(mapped.seq, 20);
157        assert_eq!(mapped.meta, Some("meta"));
158        assert_eq!(mapped.data, 123u64);
159    }
160
161    #[test]
162    fn test_try_map_error() {
163        let sv = SeqV::<(), _>::new(30, "invalid");
164        let result = sv.try_map(|s| s.parse::<u64>());
165
166        assert!(result.is_err());
167    }
168
169    #[test]
170    fn test_deref() {
171        let sv = SeqV::<(), _>::new(1, vec![1, 2, 3]);
172        assert_eq!(sv.len(), 3);
173        assert_eq!(sv[0], 1);
174    }
175
176    #[test]
177    fn test_deref_mut() {
178        let mut sv = SeqV::<(), _>::new(1, vec![1, 2, 3]);
179        sv[0] = 10;
180        assert_eq!(sv.data[0], 10);
181    }
182
183    #[test]
184    fn test_default() {
185        let sv = SeqV::<String, u64>::default();
186        assert_eq!(sv.seq, 0);
187        assert_eq!(sv.meta, None);
188        assert_eq!(sv.data, 0);
189    }
190
191    #[test]
192    fn test_debug() {
193        let sv = SeqV::new_with_meta(42, Some("test"), vec![1, 2, 3]);
194        assert_eq!(
195            "SeqV { seq: 42, meta: Some(\"test\"), data: \"[binary]\" }",
196            format!("{:?}", sv)
197        );
198    }
199
200    #[test]
201    fn test_clone_eq() {
202        let sv1 = SeqV::new_with_meta(10, Some("meta"), 100u64);
203        let sv2 = sv1.clone();
204        assert_eq!(sv1, sv2);
205    }
206}
207
208#[cfg(test)]
209#[cfg(feature = "seqv-serde")]
210mod tests_serde {
211    use serde_json;
212
213    use super::*;
214
215    #[test]
216    fn test_serde() {
217        let sv = SeqV::new_with_meta(42, Some("metadata".to_string()), vec![1, 2, 3]);
218        let json = serde_json::to_string(&sv).unwrap();
219        let deserialized: SeqV<String, Vec<u8>> = serde_json::from_str(&json).unwrap();
220        assert_eq!(sv, deserialized);
221
222        // Test with None metadata
223        let sv_none = SeqV::new_with_meta(10, None::<String>, vec![4, 5, 6]);
224        let json_none = serde_json::to_string(&sv_none).unwrap();
225        let deserialized_none: SeqV<String, Vec<u8>> = serde_json::from_str(&json_none).unwrap();
226        assert_eq!(sv_none, deserialized_none);
227    }
228}