seq_marked/seq_data/
mod.rs

1use std::fmt;
2
3use crate::InternalSeq;
4use crate::SeqMarked;
5
6mod impl_from_seq_marked;
7mod impl_from_seqv;
8
9/// Sequence-numbered non-marked data.
10///
11/// It is a subset of SeqMarked where data is always normal.
12///
13/// ```rust
14/// use seq_marked::SeqData;
15///
16/// let v1 = SeqData::new(1, "data");
17/// ```
18#[derive(Debug)]
19#[derive(Clone, Copy)]
20#[derive(PartialEq, Eq)]
21#[derive(PartialOrd, Ord)]
22#[cfg_attr(
23    feature = "seq-marked-serde",
24    derive(serde::Serialize, serde::Deserialize)
25)]
26#[cfg_attr(
27    feature = "seq-marked-bincode",
28    derive(bincode::Encode, bincode::Decode)
29)]
30pub struct SeqData<D = Vec<u8>> {
31    // Keep the `seq` as the first field so that it can be compared first.
32    seq: u64,
33    data: D,
34}
35
36impl<D> SeqData<D> {
37    /// Creates normal value with sequence number.
38    pub fn new(seq: u64, data: D) -> Self {
39        Self { seq, data }
40    }
41
42    /// Transforms data `D` to `U` while preserving sequence and tombstone state.
43    ///
44    /// # Example
45    ///
46    /// ```rust
47    /// use seq_marked::SeqData;
48    ///
49    /// let a = SeqData::new(1, "data");
50    /// let b = a.map(|x| x.len());
51    /// assert_eq!(b.data(), &4);
52    /// ```
53    pub fn map<U>(self, f: impl FnOnce(D) -> U) -> SeqData<U> {
54        SeqData {
55            seq: self.seq,
56            data: f(self.data),
57        }
58    }
59
60    pub fn try_map<U, E>(self, f: impl FnOnce(D) -> Result<U, E>) -> Result<SeqData<U>, E> {
61        Ok(SeqData {
62            seq: self.seq,
63            data: f(self.data)?,
64        })
65    }
66
67    /// Creates reference to the data.
68    pub fn as_ref(&self) -> SeqData<&D> {
69        SeqData {
70            seq: self.seq,
71            data: &self.data,
72        }
73    }
74
75    /// Returns ordering key (sequence + tombstone state only).
76    pub fn order_key(&self) -> SeqMarked<()> {
77        SeqMarked::new_normal(self.seq, ())
78    }
79
80    /// Returns the sequence number for internal use, tombstone also has a seq.
81    pub fn internal_seq(&self) -> InternalSeq {
82        InternalSeq::new(self.seq)
83    }
84
85    /// Returns the sequence number for application use, tombstone always has seq 0.
86    pub fn user_seq(&self) -> u64 {
87        self.seq
88    }
89
90    /// Returns the maximum of two values.
91    pub fn max(a: Self, b: Self) -> Self {
92        if a.order_key() > b.order_key() { a } else { b }
93    }
94
95    /// Returns the maximum of two values.
96    pub fn max_ref<'l>(a: &'l Self, b: &'l Self) -> &'l Self {
97        if a.order_key() > b.order_key() { a } else { b }
98    }
99
100    /// Returns reference to data if normal, `None` if tombstone.
101    pub fn data(&self) -> &D {
102        &self.data
103    }
104
105    /// Consumes and returns data if normal, `None` if tombstone.
106    pub fn into_data(self) -> D {
107        self.data
108    }
109
110    pub fn into_parts(self) -> (u64, D) {
111        (self.seq, self.data)
112    }
113
114    /// Returns formatter for display using `Debug` trait.
115    pub fn display_with_debug(&self) -> impl fmt::Display + '_
116    where D: fmt::Debug {
117        struct DisplaySeqData<'a, D>(&'a SeqData<D>);
118
119        impl<D> fmt::Display for DisplaySeqData<'_, D>
120        where D: fmt::Debug
121        {
122            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
123                write!(f, "{{seq: {}, ", self.0.seq)?;
124                write!(f, "({:?})", self.0.data)?;
125                write!(f, "}}")
126            }
127        }
128
129        DisplaySeqData(self)
130    }
131}
132
133#[cfg(test)]
134mod tests {
135    use std::cmp::Ordering;
136
137    use Ordering::Equal;
138    use Ordering::Greater;
139    use Ordering::Less;
140
141    use super::*;
142    use crate::testing::ts;
143
144    /// Create a `SeqMarked::Normal`.
145    pub(crate) fn norm<D>(seq: u64, d: D) -> SeqData<D> {
146        SeqData::new(seq, d)
147    }
148
149    #[test]
150    fn test_seq_data_is_copy() {
151        let seq_marked = SeqData::new(5, "data");
152        let seq_marked_copy = seq_marked;
153        assert_eq!(seq_marked, seq_marked_copy);
154    }
155
156    #[test]
157    fn test_new() {
158        let seq_marked = SeqData::new(5, "data");
159        assert_eq!(seq_marked.seq, 5);
160        assert_eq!(seq_marked.data, "data");
161    }
162
163    #[test]
164    fn test_map() -> anyhow::Result<()> {
165        let a = norm(1, 1u64);
166        assert_eq!(norm(1, 2u32), a.map(|x| (x * 2) as u32));
167
168        let a = ts::<u64>(1);
169        assert_eq!(ts::<u32>(1), a.map(|x| (x * 2) as u32));
170
171        Ok(())
172    }
173
174    #[test]
175    fn test_as_ref() -> anyhow::Result<()> {
176        let a = norm(1, 1u64);
177        assert_eq!(norm(1, &1u64), a.as_ref());
178
179        let a = ts::<u64>(1);
180        assert_eq!(ts::<&u64>(1), a.as_ref());
181
182        Ok(())
183    }
184
185    #[test]
186    fn test_order_key() -> anyhow::Result<()> {
187        assert!(norm(1, 1u64).order_key() == norm(1, 1u64).order_key());
188        assert!(norm(1, 2u64).order_key() == norm(1, 1u64).order_key());
189        assert!(norm(2, 2u64).order_key() > norm(1, 1u64).order_key());
190
191        assert!(ts::<u64>(1).order_key() > norm(1, 1u64).order_key());
192        assert!(ts::<u64>(2).order_key() > norm(1, 1u64).order_key());
193
194        assert!(ts::<u64>(2).order_key() > ts::<u64>(1).order_key());
195        assert!(ts::<u64>(1).order_key() == ts::<u64>(1).order_key());
196
197        Ok(())
198    }
199
200    #[test]
201    fn test_partial_ord() -> anyhow::Result<()> {
202        fn pcmp<D: PartialOrd>(a: &SeqData<D>, b: &SeqData<D>) -> Option<Ordering> {
203            PartialOrd::partial_cmp(a, b)
204        }
205
206        // normal vs normal, with the same data
207
208        assert_eq!(Some(Greater), pcmp(&norm(2, 2u64), &norm(1, 2u64)));
209        assert_eq!(Some(Equal), pcmp(&norm(2, 2u64), &norm(2, 2u64)));
210        assert_eq!(Some(Less), pcmp(&norm(2, 2u64), &norm(3, 2u64)));
211
212        // normal vs normal, same seq, different value
213
214        assert_eq!(Some(Greater), pcmp(&norm(2, 2u64), &norm(2, 1u64)));
215        assert_eq!(Some(Equal), pcmp(&norm(2, 2u64), &norm(2, 2u64)));
216        assert_eq!(Some(Less), pcmp(&norm(2, 2u64), &norm(2, 3u64)));
217
218        Ok(())
219    }
220
221    #[test]
222    fn test_seq_data_order_key() {
223        let a = SeqData::new(1, "data1");
224
225        assert_eq!(a.order_key(), SeqMarked::new_normal(1, ()));
226    }
227
228    #[test]
229    fn test_max() {
230        assert_eq!(
231            SeqData::<u64>::new(2, 1),
232            SeqData::<u64>::max(SeqData::<u64>::new(1, 1), SeqData::<u64>::new(2, 1))
233        );
234        assert_eq!(
235            SeqData::<u64>::new(2, 1),
236            SeqData::<u64>::max(SeqData::<u64>::new(1, 2), SeqData::<u64>::new(2, 1))
237        );
238    }
239
240    #[test]
241    fn test_max_ref() {
242        let m1 = SeqData::new(1, 2);
243        let m2 = SeqData::new(3, 2);
244
245        assert_eq!(SeqData::max_ref(&m1, &m2), &m2);
246
247        assert_eq!(SeqData::max_ref(&m1, &m1), &m1);
248        assert_eq!(SeqData::max_ref(&m2, &m2), &m2);
249    }
250
251    #[test]
252    fn test_into_parts() {
253        let seq_marked = SeqData::new(5, "data");
254        let (seq, marked) = seq_marked.into_parts();
255        assert_eq!(seq, 5);
256        assert_eq!(marked, "data");
257    }
258
259    #[test]
260    fn test_internal_seq() {
261        let seq_marked = SeqData::new(5, "data");
262        assert_eq!(*seq_marked.internal_seq(), 5);
263    }
264
265    #[test]
266    fn test_user_seq() {
267        let seq_marked = SeqData::new(5, "data");
268        assert_eq!(seq_marked.user_seq(), 5);
269    }
270
271    #[test]
272    fn test_display_with_debug() {
273        let seq_marked = SeqData::new(5, "data");
274        assert_eq!(
275            format!("{}", seq_marked.display_with_debug()),
276            "{seq: 5, (\"data\")}"
277        );
278    }
279}
280
281#[cfg(test)]
282#[cfg(feature = "seq-marked-bincode")]
283mod tests_bincode {
284
285    use super::*;
286    use crate::testing::bincode_config;
287    use crate::testing::test_bincode_decode;
288
289    #[test]
290    fn test_marked_bincode() {
291        let a = SeqData::new(5, 1u64);
292        let encoded = bincode::encode_to_vec(&a, bincode_config()).unwrap();
293        let (decoded, n): (SeqData<u64>, usize) =
294            bincode::decode_from_slice(&encoded, bincode_config()).unwrap();
295        assert_eq!(n, 2);
296        assert_eq!(a, decoded);
297    }
298
299    #[test]
300    fn test_marked_bincode_decode_v010() -> anyhow::Result<()> {
301        let value = SeqData::new(5, 1u64);
302        let encoded = vec![5, 1];
303
304        test_bincode_decode(&encoded, &value)?;
305
306        Ok(())
307    }
308}
309
310#[cfg(test)]
311#[cfg(feature = "seq-marked-serde")]
312mod tests_serde {
313    use super::*;
314    use crate::testing::test_serde_decode;
315
316    #[test]
317    fn test_marked_serde() {
318        let a = SeqData::new(5, 1u64);
319        let encoded = serde_json::to_string(&a).unwrap();
320        let decoded: SeqData<u64> = serde_json::from_str(&encoded).unwrap();
321        assert_eq!(a, decoded);
322    }
323
324    #[test]
325    fn test_marked_serde_decode_v010() -> anyhow::Result<()> {
326        let value = SeqData::new(5, 1u64);
327        let encoded = r#"{"seq":5,"data":1}"#;
328
329        test_serde_decode(encoded, &value)?;
330
331        Ok(())
332    }
333}