seq_marked/seq_data/
mod.rs

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