use std::fmt;
use std::str::FromStr;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ParseLsnError(pub String);
impl fmt::Display for ParseLsnError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "invalid LSN: {}", self.0)
}
}
impl std::error::Error for ParseLsnError {}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
pub struct Lsn(pub u64);
impl Lsn {
pub const ZERO: Lsn = Lsn(0);
pub fn parse(s: &str) -> Result<Lsn, ParseLsnError> {
let (hi_str, lo_str) = s
.split_once('/')
.ok_or_else(|| ParseLsnError(format!("missing '/' separator: {s}")))?;
let hi = u64::from_str_radix(hi_str, 16)
.map_err(|_| ParseLsnError(format!("invalid high part '{hi_str}': {s}")))?;
let lo = u64::from_str_radix(lo_str, 16)
.map_err(|_| ParseLsnError(format!("invalid low part '{lo_str}': {s}")))?;
Ok(Lsn((hi << 32) | lo))
}
#[inline]
pub fn to_pg_string(self) -> String {
self.to_string()
}
#[inline]
pub fn is_zero(self) -> bool {
self.0 == 0
}
#[inline]
pub fn as_u64(self) -> u64 {
self.0
}
#[inline]
pub fn from_u64(value: u64) -> Self {
Lsn(value)
}
}
impl fmt::Display for Lsn {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let v: u64 = self.as_u64();
let hi = (v >> 32) as u32;
let lo = (v & 0xFFFF_FFFF) as u32;
write!(f, "{:X}/{:X}", hi, lo)
}
}
impl FromStr for Lsn {
type Err = ParseLsnError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Lsn::parse(s)
}
}
impl From<u64> for Lsn {
fn from(value: u64) -> Self {
Lsn(value)
}
}
impl From<Lsn> for u64 {
fn from(lsn: Lsn) -> Self {
lsn.0
}
}