reddb_server/replication/
bookmark.rs1#[derive(Debug, Clone, Copy, PartialEq, Eq)]
4pub struct CausalBookmark {
5 term: u64,
6 commit_lsn: u64,
7}
8
9#[derive(Debug, Clone, PartialEq, Eq)]
10pub enum BookmarkDecodeError {
11 InvalidPrefix,
12 InvalidLength,
13 InvalidHex,
14}
15
16impl std::fmt::Display for BookmarkDecodeError {
17 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
18 match self {
19 Self::InvalidPrefix => write!(f, "invalid causal bookmark prefix"),
20 Self::InvalidLength => write!(f, "invalid causal bookmark length"),
21 Self::InvalidHex => write!(f, "invalid causal bookmark hex payload"),
22 }
23 }
24}
25
26impl std::error::Error for BookmarkDecodeError {}
27
28impl CausalBookmark {
29 pub fn new(term: u64, commit_lsn: u64) -> Self {
30 Self { term, commit_lsn }
31 }
32
33 pub fn term(self) -> u64 {
34 self.term
35 }
36
37 pub fn commit_lsn(self) -> u64 {
38 self.commit_lsn
39 }
40
41 pub fn encode(self) -> String {
42 format!("rbm1.{:016x}{:016x}", self.term, self.commit_lsn)
43 }
44
45 pub fn decode(token: &str) -> Result<Self, BookmarkDecodeError> {
46 let Some(payload) = token.strip_prefix("rbm1.") else {
47 return Err(BookmarkDecodeError::InvalidPrefix);
48 };
49 if payload.len() != 32 {
50 return Err(BookmarkDecodeError::InvalidLength);
51 }
52 let term =
53 u64::from_str_radix(&payload[..16], 16).map_err(|_| BookmarkDecodeError::InvalidHex)?;
54 let commit_lsn =
55 u64::from_str_radix(&payload[16..], 16).map_err(|_| BookmarkDecodeError::InvalidHex)?;
56 Ok(Self { term, commit_lsn })
57 }
58}