1use std::fmt;
4
5#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
10pub struct Lsn(pub u64);
11
12impl Lsn {
13 pub const NONE: Lsn = Lsn(0);
15
16 pub const FIRST: Lsn = Lsn(1);
18
19 #[inline]
23 #[must_use]
24 pub const fn next(self) -> Lsn {
25 Lsn(self.0.saturating_add(1))
26 }
27
28 #[inline]
30 #[must_use]
31 pub const fn is_none(self) -> bool {
32 self.0 == 0
33 }
34}
35
36impl fmt::Display for Lsn {
37 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
40 write!(f, "{}", self.0)
41 }
42}
43
44#[cfg(test)]
45mod tests {
46 use super::*;
47
48 #[test]
49 fn none_and_first() {
50 assert_eq!(Lsn::NONE, Lsn(0));
51 assert_eq!(Lsn::FIRST, Lsn(1));
52 assert!(Lsn::NONE.is_none());
53 assert!(!Lsn::FIRST.is_none());
54 }
55
56 #[test]
57 fn next_is_monotone_and_dense() {
58 assert_eq!(Lsn::NONE.next(), Lsn::FIRST);
59 assert_eq!(Lsn(41).next(), Lsn(42));
60 }
61
62 #[test]
63 fn next_saturates_without_panicking() {
64 assert_eq!(Lsn(u64::MAX).next(), Lsn(u64::MAX));
65 }
66
67 #[test]
68 fn ordering() {
69 assert!(Lsn(1) < Lsn(2));
70 assert!(Lsn::NONE < Lsn::FIRST);
71 }
72
73 #[test]
74 fn display_is_the_underlying_integer() {
75 assert_eq!(Lsn(0).to_string(), "0");
76 assert_eq!(Lsn(100001).to_string(), "100001");
77 }
78}