1mod impl_display;
2mod impl_from_seqv;
3mod impl_seq_value;
4mod impl_try_from_meta_bytes;
5
6use std::fmt;
7
8use crate::Marked;
9
10#[derive(Debug)]
22#[derive(Clone, Copy)]
23#[derive(PartialEq, Eq)]
24#[derive(PartialOrd, Ord)]
25#[cfg_attr(
26 feature = "seq-marked-serde",
27 derive(serde::Serialize, serde::Deserialize)
28)]
29#[cfg_attr(
30 feature = "seq-marked-bincode",
31 derive(bincode::Encode, bincode::Decode)
32)]
33pub struct SeqMarked<D = Vec<u8>> {
34 seq: u64,
36 marked: Marked<D>,
37}
38
39impl<D> SeqMarked<D> {
40 pub fn new(seq: u64, marked: Marked<D>) -> Self {
42 Self { seq, marked }
43 }
44
45 pub fn new_normal(seq: u64, data: D) -> Self {
47 Self {
48 seq,
49 marked: Marked::Normal(data),
50 }
51 }
52
53 pub fn new_tombstone(seq: u64) -> Self {
55 Self {
56 seq,
57 marked: Marked::TombStone,
58 }
59 }
60
61 pub fn new_not_found() -> Self {
63 Self {
64 seq: 0,
65 marked: Marked::TombStone,
66 }
67 }
68
69 pub fn is_normal(&self) -> bool {
71 !self.is_tombstone()
72 }
73
74 pub fn is_tombstone(&self) -> bool {
76 match self.marked {
77 Marked::Normal(_) => false,
78 Marked::TombStone => true,
79 }
80 }
81
82 pub fn is_not_found(&self) -> bool {
83 self.is_absent()
84 }
85
86 pub fn is_absent(&self) -> bool {
87 self.seq == 0 && self.is_tombstone()
88 }
89
90 pub fn map<U>(self, f: impl FnOnce(D) -> U) -> SeqMarked<U> {
102 SeqMarked {
103 seq: self.seq,
104 marked: match self.marked {
105 Marked::Normal(data) => Marked::<U>::Normal(f(data)),
106 Marked::TombStone => Marked::<U>::TombStone,
107 },
108 }
109 }
110
111 pub fn try_map<U, E>(self, f: impl FnOnce(D) -> Result<U, E>) -> Result<SeqMarked<U>, E> {
112 Ok(SeqMarked {
113 seq: self.seq,
114 marked: match self.marked {
115 Marked::Normal(data) => Marked::<U>::Normal(f(data)?),
116 Marked::TombStone => Marked::<U>::TombStone,
117 },
118 })
119 }
120
121 pub fn as_ref(&self) -> SeqMarked<&D> {
123 SeqMarked {
124 seq: self.seq,
125 marked: match &self.marked {
126 Marked::Normal(data) => Marked::Normal(data),
127 Marked::TombStone => Marked::TombStone,
128 },
129 }
130 }
131
132 pub fn order_key(&self) -> SeqMarked<()> {
134 SeqMarked {
135 seq: self.seq,
136 marked: match &self.marked {
137 Marked::Normal(_) => Marked::Normal(()),
138 Marked::TombStone => Marked::TombStone,
139 },
140 }
141 }
142
143 pub fn seq(&self) -> u64 {
145 self.seq
146 }
147
148 pub fn max(a: Self, b: Self) -> Self {
150 if a.order_key() > b.order_key() { a } else { b }
151 }
152
153 pub fn max_ref<'l>(a: &'l Self, b: &'l Self) -> &'l Self {
155 if a.order_key() > b.order_key() { a } else { b }
156 }
157
158 pub fn data_ref(&self) -> Option<&D> {
160 match self.marked {
161 Marked::Normal(ref d) => Some(d),
162 Marked::TombStone => None,
163 }
164 }
165
166 pub fn into_data(self) -> Option<D> {
168 match self.marked {
169 Marked::Normal(data) => Some(data),
170 Marked::TombStone => None,
171 }
172 }
173
174 pub fn into_parts(self) -> (u64, Marked<D>) {
175 (self.seq, self.marked)
176 }
177
178 pub fn display_with_debug(&self) -> impl fmt::Display + '_
180 where D: fmt::Debug {
181 struct DisplaySeqMarked<'a, D>(&'a SeqMarked<D>);
182
183 impl<D> fmt::Display for DisplaySeqMarked<'_, D>
184 where D: fmt::Debug
185 {
186 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
187 write!(f, "{{seq: {}, ", self.0.seq)?;
188 match &self.0.marked {
189 Marked::Normal(data) => write!(f, "({:?})", data)?,
190 Marked::TombStone => write!(f, "TOMBSTONE")?,
191 }
192 write!(f, "}}")
193 }
194 }
195
196 DisplaySeqMarked(self)
197 }
198}
199
200#[cfg(test)]
201mod tests {
202 use std::cmp::Ordering;
203
204 use Ordering::Equal;
205 use Ordering::Greater;
206 use Ordering::Less;
207
208 use super::*;
209 use crate::testing::norm;
210 use crate::testing::ts;
211
212 #[test]
213 fn test_seq_marked_is_copy() {
214 let seq_marked = SeqMarked::new(5, Marked::Normal("data"));
215 let seq_marked_copy = seq_marked;
216 assert_eq!(seq_marked, seq_marked_copy);
217 }
218
219 #[test]
220 fn test_new() {
221 let seq_marked = SeqMarked::new(5, Marked::Normal("data"));
222 assert_eq!(seq_marked.seq, 5);
223 assert_eq!(seq_marked.marked, Marked::Normal("data"));
224 }
225
226 #[test]
227 fn test_map() -> anyhow::Result<()> {
228 let a = norm(1, 1u64);
229 assert_eq!(norm(1, 2u32), a.map(|x| (x * 2) as u32));
230
231 let a = ts::<u64>(1);
232 assert_eq!(ts::<u32>(1), a.map(|x| (x * 2) as u32));
233
234 Ok(())
235 }
236
237 #[test]
238 fn test_as_ref() -> anyhow::Result<()> {
239 let a = norm(1, 1u64);
240 assert_eq!(norm(1, &1u64), a.as_ref());
241
242 let a = ts::<u64>(1);
243 assert_eq!(ts::<&u64>(1), a.as_ref());
244
245 Ok(())
246 }
247
248 #[test]
249 fn test_order_key() -> anyhow::Result<()> {
250 assert!(norm(1, 1u64).order_key() == norm(1, 1u64).order_key());
251 assert!(norm(1, 2u64).order_key() == norm(1, 1u64).order_key());
252 assert!(norm(2, 2u64).order_key() > norm(1, 1u64).order_key());
253
254 assert!(ts::<u64>(1).order_key() > norm(1, 1u64).order_key());
255 assert!(ts::<u64>(2).order_key() > norm(1, 1u64).order_key());
256
257 assert!(ts::<u64>(2).order_key() > ts::<u64>(1).order_key());
258 assert!(ts::<u64>(1).order_key() == ts::<u64>(1).order_key());
259
260 Ok(())
261 }
262
263 #[test]
264 fn test_partial_ord() -> anyhow::Result<()> {
265 fn pcmp<D: PartialOrd>(a: &SeqMarked<D>, b: &SeqMarked<D>) -> Option<Ordering> {
266 PartialOrd::partial_cmp(a, b)
267 }
268
269 assert_eq!(Some(Greater), pcmp(&norm(2, 2u64), &norm(1, 2u64)));
272 assert_eq!(Some(Equal), pcmp(&norm(2, 2u64), &norm(2, 2u64)));
273 assert_eq!(Some(Less), pcmp(&norm(2, 2u64), &norm(3, 2u64)));
274
275 assert_eq!(Some(Greater), pcmp(&norm(2, 2u64), &norm(2, 1u64)));
278 assert_eq!(Some(Equal), pcmp(&norm(2, 2u64), &norm(2, 2u64)));
279 assert_eq!(Some(Less), pcmp(&norm(2, 2u64), &norm(2, 3u64)));
280
281 assert_eq!(Some(Greater), pcmp(&norm(2, 2u64), &ts(1)));
284 assert_eq!(
285 Some(Less),
286 pcmp(&norm(2, 2u64), &ts(2)),
287 "tombstone is greater than a normal with the same seq"
288 );
289 assert_eq!(Some(Less), pcmp(&norm(2, 2u64), &ts(3)));
290
291 assert_eq!(Some(Less), pcmp(&ts(1), &norm(2, 2u64)));
294 assert_eq!(
295 Some(Greater),
296 pcmp(&ts(2), &norm(2, 2u64)),
297 "tombstone is greater than a normal with the same seq"
298 );
299 assert_eq!(Some(Greater), pcmp(&ts(3), &norm(2, 2u64)));
300
301 assert_eq!(Some(Greater), pcmp(&ts::<()>(2), &ts(1)));
304 assert_eq!(Some(Equal), pcmp(&ts::<()>(2), &ts(2)));
305 assert_eq!(Some(Less), pcmp(&ts::<()>(2), &ts(3)));
306 Ok(())
307 }
308
309 #[test]
310 fn test_ord_operator() -> anyhow::Result<()> {
311 assert!(norm(2, 2u64) > norm(1, 2u64));
314 assert!(norm(2, 2u64) >= norm(1, 2u64));
315 assert!(norm(2, 2u64) == norm(2, 2u64));
316 assert!(norm(2, 2u64) <= norm(3, 2u64));
317 assert!(norm(2, 2u64) < norm(3, 2u64));
318
319 assert!(norm(2, 2u64) > norm(2, 1u64));
322 assert!(norm(2, 2u64) >= norm(2, 1u64));
323 assert!(norm(2, 2u64) == norm(2, 2u64));
324 assert!(norm(2, 2u64) <= norm(2, 3u64));
325 assert!(norm(2, 2u64) < norm(2, 3u64));
326
327 assert!(norm(2, 2u64) > ts(1));
330 assert!(norm(2, 2u64) >= ts(1));
331 assert!(
332 norm(2, 2u64) < ts(2),
333 "tombstone is greater than a normal with the same seq"
334 );
335 assert!(
336 norm(2, 2u64) <= ts(2),
337 "tombstone is greater than a normal with the same seq"
338 );
339 assert!(norm(2, 2u64) < ts(3));
340 assert!(norm(2, 2u64) <= ts(3));
341
342 assert!(ts(1) < norm(2, 2u64));
345 assert!(ts(1) <= norm(2, 2u64));
346 assert!(
347 ts(2) > norm(2, 2u64),
348 "tombstone is greater than a normal with the same seq"
349 );
350 assert!(
351 ts(2) >= norm(2, 2u64),
352 "tombstone is greater than a normal with the same seq"
353 );
354 assert!(ts(3) > norm(2, 2u64));
355 assert!(ts(3) >= norm(2, 2u64));
356
357 assert!(ts::<()>(2) > ts(1));
360 assert!(ts::<()>(2) >= ts(1));
361 assert!(ts::<()>(2) >= ts(2));
362 assert!(ts::<()>(2) == ts(2));
363 assert!(ts::<()>(2) <= ts(2));
364 assert!(ts::<()>(2) <= ts(3));
365 assert!(ts::<()>(2) < ts(3));
366
367 Ok(())
368 }
369
370 #[test]
371 fn test_new_absent() {
372 let absent = SeqMarked::<u64>::new_not_found();
373 assert_eq!(absent.seq, 0);
374 assert!(absent.is_tombstone());
375 }
376
377 #[test]
378 fn test_max() {
379 assert_eq!(
380 SeqMarked::<u64>::new_normal(2, 1),
381 SeqMarked::<u64>::max(
382 SeqMarked::<u64>::new_normal(1, 1),
383 SeqMarked::<u64>::new_normal(2, 1)
384 )
385 );
386 assert_eq!(
387 SeqMarked::<u64>::new_normal(2, 1),
388 SeqMarked::<u64>::max(
389 SeqMarked::<u64>::new_normal(1, 2),
390 SeqMarked::<u64>::new_normal(2, 1)
391 )
392 );
393 assert_eq!(
394 SeqMarked::<u64>::new_tombstone(2),
395 SeqMarked::<u64>::max(
396 SeqMarked::<u64>::new_normal(2, 1),
397 SeqMarked::<u64>::new_tombstone(2)
398 )
399 );
400 assert_eq!(
401 SeqMarked::<u64>::new_tombstone(2),
402 SeqMarked::<u64>::max(
403 SeqMarked::<u64>::new_tombstone(1),
404 SeqMarked::<u64>::new_tombstone(2)
405 )
406 );
407 }
408
409 #[test]
410 fn test_max_ref() {
411 let m1 = SeqMarked::new_normal(1, 2);
412 let m2 = SeqMarked::new_normal(3, 2);
413 let m3 = SeqMarked::new_tombstone(2);
414
415 assert_eq!(SeqMarked::max_ref(&m1, &m2), &m2);
416 assert_eq!(SeqMarked::max_ref(&m1, &m3), &m3);
417 assert_eq!(SeqMarked::max_ref(&m2, &m3), &m2);
418
419 assert_eq!(SeqMarked::max_ref(&m1, &m1), &m1);
420 assert_eq!(SeqMarked::max_ref(&m2, &m2), &m2);
421 assert_eq!(SeqMarked::max_ref(&m3, &m3), &m3);
422 }
423
424 #[test]
425 fn test_is_not_found() {
426 assert!(SeqMarked::<u64>::new_not_found().is_not_found());
427 assert!(SeqMarked::<u64>::new_tombstone(0).is_not_found());
428 assert!(!SeqMarked::<u64>::new_tombstone(1).is_not_found());
429 assert!(!SeqMarked::<u64>::new_normal(1, 1).is_not_found());
430 }
431
432 #[test]
433 fn test_into_parts() {
434 let seq_marked = SeqMarked::new_normal(5, "data");
435 let (seq, marked) = seq_marked.into_parts();
436 assert_eq!(seq, 5);
437 assert_eq!(marked, Marked::Normal("data"));
438 }
439
440 #[test]
441 fn test_display_with_debug() {
442 let seq_marked = SeqMarked::new_normal(5, "data");
443 assert_eq!(
444 format!("{}", seq_marked.display_with_debug()),
445 "{seq: 5, (\"data\")}"
446 );
447 }
448
449 #[test]
450 fn test_display_with_debug_tombstone() {
451 let seq_marked = SeqMarked::<u64>::new_tombstone(5);
452 assert_eq!(
453 format!("{}", seq_marked.display_with_debug()),
454 "{seq: 5, TOMBSTONE}"
455 );
456 }
457}
458
459#[cfg(test)]
460#[cfg(feature = "seq-marked-bincode")]
461mod tests_bincode {
462
463 use super::*;
464 use crate::testing::bincode_config;
465 use crate::testing::test_bincode_decode;
466
467 #[test]
468 fn test_marked_bincode() {
469 let a = SeqMarked::new_normal(5, 1u64);
470 let encoded = bincode::encode_to_vec(&a, bincode_config()).unwrap();
471 let (decoded, n): (SeqMarked<u64>, usize) =
472 bincode::decode_from_slice(&encoded, bincode_config()).unwrap();
473 assert_eq!(n, 3);
474 assert_eq!(a, decoded);
475 }
476
477 #[test]
478 fn test_marked_bincode_decode_v010() -> anyhow::Result<()> {
479 let value = SeqMarked::new_normal(5, 1u64);
480 let encoded = vec![5, 0, 1];
481
482 test_bincode_decode(&encoded, &value)?;
483
484 let value = SeqMarked::<u64>::new_tombstone(6);
485 let encoded = vec![6, 1];
486
487 test_bincode_decode(&encoded, &value)?;
488 Ok(())
489 }
490}
491
492#[cfg(test)]
493#[cfg(feature = "seq-marked-serde")]
494mod tests_serde {
495 use super::*;
496 use crate::testing::test_serde_decode;
497
498 #[test]
499 fn test_marked_serde() {
500 let a = SeqMarked::new_normal(5, 1u64);
501 let encoded = serde_json::to_string(&a).unwrap();
502 let decoded: SeqMarked<u64> = serde_json::from_str(&encoded).unwrap();
503 assert_eq!(a, decoded);
504 }
505
506 #[test]
507 fn test_marked_serde_decode_v010() -> anyhow::Result<()> {
508 let value = SeqMarked::new_normal(5, 1u64);
509 let encoded = r#"{"seq":5,"marked":{"Normal":1}}"#;
510
511 test_serde_decode(encoded, &value)?;
512
513 let value = SeqMarked::<u64>::new_tombstone(6);
514 let encoded = r#"{"seq":6,"marked":"TombStone"}"#;
515
516 test_serde_decode(encoded, &value)?;
517 Ok(())
518 }
519}