1use std::fmt;
2
3use serde::{Deserialize, Serialize};
4
5#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
16#[repr(transparent)]
17pub struct Lsn(u64);
18
19impl Lsn {
20 pub const ZERO: Lsn = Lsn(0);
21
22 pub const fn new(value: u64) -> Self {
23 Self(value)
24 }
25
26 pub const fn raw(self) -> u64 {
27 self.0
28 }
29
30 pub const fn is_zero(self) -> bool {
31 self.0 == 0
32 }
33
34 pub fn next(self) -> Self {
38 Self(
39 self.0
40 .checked_add(1)
41 .expect("Lsn overflowed; the WAL has been continuously running for ~580 My"),
42 )
43 }
44}
45
46impl fmt::Display for Lsn {
47 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
48 write!(f, "{}", self.0)
49 }
50}
51
52impl From<u64> for Lsn {
53 fn from(value: u64) -> Self {
54 Self(value)
55 }
56}
57
58impl From<Lsn> for u64 {
59 fn from(value: Lsn) -> Self {
60 value.0
61 }
62}
63
64#[cfg(test)]
65mod tests {
66 use super::*;
67
68 #[test]
69 fn next_advances_monotonically() {
70 let a = Lsn::new(7);
71 let b = a.next();
72 assert!(b > a);
73 assert_eq!(b.raw(), 8);
74 }
75
76 #[test]
77 fn zero_is_sentinel() {
78 assert!(Lsn::ZERO.is_zero());
79 assert!(!Lsn::new(1).is_zero());
80 }
81
82 #[test]
83 #[should_panic(expected = "Lsn overflowed")]
84 fn overflow_panics() {
85 let _ = Lsn::new(u64::MAX).next();
86 }
87}