LCOV - code coverage report
Current view: top level - libs/utils/src - lsn.rs (source / functions) Coverage Total Hit
Test: 1b0a6a0c05cee5a7de360813c8034804e105ce1c.info Lines: 89.5 % 325 291
Test Date: 2025-03-12 00:01:28 Functions: 59.1 % 110 65

            Line data    Source code
       1              : #![warn(missing_docs)]
       2              : 
       3              : use std::fmt;
       4              : use std::ops::{Add, AddAssign};
       5              : use std::str::FromStr;
       6              : use std::sync::atomic::{AtomicU64, Ordering};
       7              : 
       8              : use serde::de::Visitor;
       9              : use serde::{Deserialize, Serialize};
      10              : 
      11              : use crate::seqwait::MonotonicCounter;
      12              : 
      13              : /// Transaction log block size in bytes
      14              : pub const XLOG_BLCKSZ: u32 = 8192;
      15              : 
      16              : /// A Postgres LSN (Log Sequence Number), also known as an XLogRecPtr
      17              : #[derive(Clone, Copy, Default, Eq, Ord, PartialEq, PartialOrd, Hash)]
      18              : pub struct Lsn(pub u64);
      19              : 
      20              : impl Serialize for Lsn {
      21        44690 :     fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
      22        44690 :     where
      23        44690 :         S: serde::Serializer,
      24        44690 :     {
      25        44690 :         if serializer.is_human_readable() {
      26        36020 :             serializer.collect_str(self)
      27              :         } else {
      28         8670 :             self.0.serialize(serializer)
      29              :         }
      30            9 :     }
      31              : }
      32              : 
      33              : impl<'de> Deserialize<'de> for Lsn {
      34         6247 :     fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
      35         6247 :     where
      36         6247 :         D: serde::Deserializer<'de>,
      37         6247 :     {
      38              :         struct LsnVisitor {
      39              :             is_human_readable_deserializer: bool,
      40              :         }
      41              : 
      42              :         impl Visitor<'_> for LsnVisitor {
      43              :             type Value = Lsn;
      44              : 
      45            2 :             fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
      46            2 :                 if self.is_human_readable_deserializer {
      47            1 :                     formatter.write_str(
      48            1 :                         "value in form of hex string({upper_u32_hex}/{lower_u32_hex}) representing u64 integer",
      49            1 :                     )
      50              :                 } else {
      51            1 :                     formatter.write_str("value in form of integer(u64)")
      52              :                 }
      53            2 :             }
      54              : 
      55         5728 :             fn visit_u64<E>(self, v: u64) -> Result<Self::Value, E>
      56         5728 :             where
      57         5728 :                 E: serde::de::Error,
      58         5728 :             {
      59         5728 :                 Ok(Lsn(v))
      60         5728 :             }
      61              : 
      62          517 :             fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
      63          517 :             where
      64          517 :                 E: serde::de::Error,
      65          517 :             {
      66          517 :                 Lsn::from_str(v).map_err(|e| E::custom(e))
      67          517 :             }
      68              :         }
      69              : 
      70         6247 :         if deserializer.is_human_readable() {
      71          518 :             deserializer.deserialize_str(LsnVisitor {
      72          518 :                 is_human_readable_deserializer: true,
      73          518 :             })
      74              :         } else {
      75         5729 :             deserializer.deserialize_u64(LsnVisitor {
      76         5729 :                 is_human_readable_deserializer: false,
      77         5729 :             })
      78              :         }
      79            7 :     }
      80              : }
      81              : 
      82              : /// Allows (de)serialization of an `Lsn` always as `u64`.
      83              : ///
      84              : /// ### Example
      85              : ///
      86              : /// ```rust
      87              : /// # use serde::{Serialize, Deserialize};
      88              : /// use utils::lsn::Lsn;
      89              : ///
      90              : /// #[derive(PartialEq, Serialize, Deserialize, Debug)]
      91              : /// struct Foo {
      92              : ///   #[serde(with = "utils::lsn::serde_as_u64")]
      93              : ///   always_u64: Lsn,
      94              : /// }
      95              : ///
      96              : /// let orig = Foo { always_u64: Lsn(1234) };
      97              : ///
      98              : /// let res = serde_json::to_string(&orig).unwrap();
      99              : /// assert_eq!(res, r#"{"always_u64":1234}"#);
     100              : ///
     101              : /// let foo = serde_json::from_str::<Foo>(&res).unwrap();
     102              : /// assert_eq!(foo, orig);
     103              : /// ```
     104              : ///
     105              : pub mod serde_as_u64 {
     106              :     use super::Lsn;
     107              : 
     108              :     /// Serializes the Lsn as u64 disregarding the human readability of the format.
     109              :     ///
     110              :     /// Meant to be used via `#[serde(with = "...")]` or `#[serde(serialize_with = "...")]`.
     111            0 :     pub fn serialize<S: serde::Serializer>(lsn: &Lsn, serializer: S) -> Result<S::Ok, S::Error> {
     112              :         use serde::Serialize;
     113            0 :         lsn.0.serialize(serializer)
     114            0 :     }
     115              : 
     116              :     /// Deserializes the Lsn as u64 disregarding the human readability of the format.
     117              :     ///
     118              :     /// Meant to be used via `#[serde(with = "...")]` or `#[serde(deserialize_with = "...")]`.
     119            0 :     pub fn deserialize<'de, D: serde::Deserializer<'de>>(deserializer: D) -> Result<Lsn, D::Error> {
     120              :         use serde::Deserialize;
     121            0 :         u64::deserialize(deserializer).map(Lsn)
     122            0 :     }
     123              : }
     124              : 
     125              : /// We tried to parse an LSN from a string, but failed
     126              : #[derive(Debug, PartialEq, Eq, thiserror::Error)]
     127              : #[error("LsnParseError")]
     128              : pub struct LsnParseError;
     129              : 
     130              : impl Lsn {
     131              :     /// Maximum possible value for an LSN
     132              :     pub const MAX: Lsn = Lsn(u64::MAX);
     133              : 
     134              :     /// Invalid value for InvalidXLogRecPtr, as defined in xlogdefs.h
     135              :     pub const INVALID: Lsn = Lsn(0);
     136              : 
     137              :     /// Subtract a number, returning None on overflow.
     138         4582 :     pub fn checked_sub<T: Into<u64>>(self, other: T) -> Option<Lsn> {
     139         4582 :         let other: u64 = other.into();
     140         4582 :         self.0.checked_sub(other).map(Lsn)
     141         4582 :     }
     142              : 
     143              :     /// Subtract a number, saturating at numeric bounds instead of overflowing.
     144           14 :     pub fn saturating_sub<T: Into<u64>>(self, other: T) -> Lsn {
     145           14 :         Lsn(self.0.saturating_sub(other.into()))
     146           14 :     }
     147              : 
     148              :     /// Subtract a number, returning the difference as i128 to avoid overflow.
     149      9606024 :     pub fn widening_sub<T: Into<u64>>(self, other: T) -> i128 {
     150      9606024 :         let other: u64 = other.into();
     151      9606024 :         i128::from(self.0) - i128::from(other)
     152      9606024 :     }
     153              : 
     154              :     /// Parse an LSN from a string in the form `0000000000000000`
     155        10851 :     pub fn from_hex<S>(s: S) -> Result<Self, LsnParseError>
     156        10851 :     where
     157        10851 :         S: AsRef<str>,
     158        10851 :     {
     159        10851 :         let s: &str = s.as_ref();
     160        10851 :         let n = u64::from_str_radix(s, 16).or(Err(LsnParseError))?;
     161        10838 :         Ok(Lsn(n))
     162            3 :     }
     163              : 
     164              :     /// Compute the offset into a segment
     165              :     #[inline]
     166      1579573 :     pub fn segment_offset(self, seg_sz: usize) -> usize {
     167      1579573 :         (self.0 % seg_sz as u64) as usize
     168      1579573 :     }
     169              : 
     170              :     /// Compute LSN of the segment start.
     171              :     #[inline]
     172           14 :     pub fn segment_lsn(self, seg_sz: usize) -> Lsn {
     173           14 :         Lsn(self.0 - (self.0 % seg_sz as u64))
     174           14 :     }
     175              : 
     176              :     /// Compute the segment number
     177              :     #[inline]
     178        17279 :     pub fn segment_number(self, seg_sz: usize) -> u64 {
     179        17279 :         self.0 / seg_sz as u64
     180        17279 :     }
     181              : 
     182              :     /// Compute the offset into a block
     183              :     #[inline]
     184      1590788 :     pub fn block_offset(self) -> u64 {
     185              :         const BLCKSZ: u64 = XLOG_BLCKSZ as u64;
     186      1590788 :         self.0 % BLCKSZ
     187      1590788 :     }
     188              : 
     189              :     /// Compute the block offset of the first byte of this Lsn within this
     190              :     /// segment
     191              :     #[inline]
     192            5 :     pub fn page_lsn(self) -> Lsn {
     193            5 :         Lsn(self.0 - self.block_offset())
     194            5 :     }
     195              : 
     196              :     /// Compute the block offset of the first byte of this Lsn within this
     197              :     /// segment
     198              :     #[inline]
     199            5 :     pub fn page_offset_in_segment(self, seg_sz: usize) -> u64 {
     200            5 :         (self.0 - self.block_offset()) - self.segment_lsn(seg_sz).0
     201            5 :     }
     202              : 
     203              :     /// Compute the bytes remaining in this block
     204              :     ///
     205              :     /// If the LSN is already at the block boundary, it will return `XLOG_BLCKSZ`.
     206              :     #[inline]
     207      1557561 :     pub fn remaining_in_block(self) -> u64 {
     208              :         const BLCKSZ: u64 = XLOG_BLCKSZ as u64;
     209      1557561 :         BLCKSZ - (self.0 % BLCKSZ)
     210      1557561 :     }
     211              : 
     212              :     /// Compute the bytes remaining to fill a chunk of some size
     213              :     ///
     214              :     /// If the LSN is already at the chunk boundary, it will return 0.
     215        11992 :     pub fn calc_padding<T: Into<u64>>(self, sz: T) -> u64 {
     216        11992 :         let sz: u64 = sz.into();
     217        11992 :         // By using wrapping_sub, we can subtract first and then mod second.
     218        11992 :         // If it's done the other way around, then we would return a full
     219        11992 :         // chunk size if we're already at the chunk boundary.
     220        11992 :         // (Regular subtraction will panic on overflow in debug builds.)
     221        11992 :         (sz.wrapping_sub(self.0)) % sz
     222        11992 :     }
     223              : 
     224              :     /// Align LSN on 8-byte boundary (alignment of WAL records).
     225     10878588 :     pub fn align(&self) -> Lsn {
     226     10878588 :         Lsn((self.0 + 7) & !7)
     227     10878588 :     }
     228              : 
     229              :     /// Align LSN on 8-byte boundary (alignment of WAL records).
     230     10561646 :     pub fn is_aligned(&self) -> bool {
     231     10561646 :         *self == self.align()
     232     10561646 :     }
     233              : 
     234              :     /// Return if the LSN is valid
     235              :     /// mimics postgres XLogRecPtrIsInvalid macro
     236     17449666 :     pub fn is_valid(self) -> bool {
     237     17449666 :         self != Lsn::INVALID
     238     17449666 :     }
     239              : }
     240              : 
     241              : impl From<u64> for Lsn {
     242        21901 :     fn from(n: u64) -> Self {
     243        21901 :         Lsn(n)
     244        21901 :     }
     245              : }
     246              : 
     247              : impl From<Lsn> for u64 {
     248      9828613 :     fn from(lsn: Lsn) -> u64 {
     249      9828613 :         lsn.0
     250      9828613 :     }
     251              : }
     252              : 
     253              : impl FromStr for Lsn {
     254              :     type Err = LsnParseError;
     255              : 
     256              :     /// Parse an LSN from a string in the form `00000000/00000000`
     257              :     ///
     258              :     /// If the input string is missing the '/' character, then use `Lsn::from_hex`
     259         1292 :     fn from_str(s: &str) -> Result<Self, Self::Err> {
     260         1292 :         let mut splitter = s.trim().split('/');
     261         1292 :         if let (Some(left), Some(right), None) = (splitter.next(), splitter.next(), splitter.next())
     262              :         {
     263         1292 :             let left_num = u32::from_str_radix(left, 16).map_err(|_| LsnParseError)?;
     264         1289 :             let right_num = u32::from_str_radix(right, 16).map_err(|_| LsnParseError)?;
     265         1287 :             Ok(Lsn(((left_num as u64) << 32) | right_num as u64))
     266              :         } else {
     267            0 :             Err(LsnParseError)
     268              :         }
     269         1292 :     }
     270              : }
     271              : 
     272              : impl fmt::Display for Lsn {
     273     10335404 :     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     274     10335404 :         write!(f, "{:X}/{:X}", self.0 >> 32, self.0 & 0xffffffff)
     275     10335404 :     }
     276              : }
     277              : 
     278              : impl fmt::Debug for Lsn {
     279        96754 :     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     280        96754 :         write!(f, "{:X}/{:X}", self.0 >> 32, self.0 & 0xffffffff)
     281        96754 :     }
     282              : }
     283              : 
     284              : impl Add<u64> for Lsn {
     285              :     type Output = Lsn;
     286              : 
     287      8105071 :     fn add(self, other: u64) -> Self::Output {
     288      8105071 :         // panic if the addition overflows.
     289      8105071 :         Lsn(self.0.checked_add(other).unwrap())
     290      8105071 :     }
     291              : }
     292              : 
     293              : impl AddAssign<u64> for Lsn {
     294      1931499 :     fn add_assign(&mut self, other: u64) {
     295      1931499 :         // panic if the addition overflows.
     296      1931499 :         self.0 = self.0.checked_add(other).unwrap();
     297      1931499 :     }
     298              : }
     299              : 
     300              : /// An [`Lsn`] that can be accessed atomically.
     301              : pub struct AtomicLsn {
     302              :     inner: AtomicU64,
     303              : }
     304              : 
     305              : impl AtomicLsn {
     306              :     /// Creates a new atomic `Lsn`.
     307         4569 :     pub fn new(val: u64) -> Self {
     308         4569 :         AtomicLsn {
     309         4569 :             inner: AtomicU64::new(val),
     310         4569 :         }
     311         4569 :     }
     312              : 
     313              :     /// Atomically retrieve the `Lsn` value from memory.
     314      9610790 :     pub fn load(&self) -> Lsn {
     315      9610790 :         Lsn(self.inner.load(Ordering::Acquire))
     316      9610790 :     }
     317              : 
     318              :     /// Atomically store a new `Lsn` value to memory.
     319         2849 :     pub fn store(&self, lsn: Lsn) {
     320         2849 :         self.inner.store(lsn.0, Ordering::Release);
     321         2849 :     }
     322              : 
     323              :     /// Adds to the current value, returning the previous value.
     324              :     ///
     325              :     /// This operation will panic on overflow.
     326            1 :     pub fn fetch_add(&self, val: u64) -> Lsn {
     327            1 :         let prev = self.inner.fetch_add(val, Ordering::AcqRel);
     328            1 :         assert!(prev.checked_add(val).is_some(), "AtomicLsn overflow");
     329            1 :         Lsn(prev)
     330            1 :     }
     331              : 
     332              :     /// Atomically sets the Lsn to the max of old and new value, returning the old value.
     333         2358 :     pub fn fetch_max(&self, lsn: Lsn) -> Lsn {
     334         2358 :         let prev = self.inner.fetch_max(lsn.0, Ordering::AcqRel);
     335         2358 :         Lsn(prev)
     336         2358 :     }
     337              : }
     338              : 
     339              : impl From<Lsn> for AtomicLsn {
     340           44 :     fn from(lsn: Lsn) -> Self {
     341           44 :         Self::new(lsn.0)
     342           44 :     }
     343              : }
     344              : 
     345              : /// Pair of LSN's pointing to the end of the last valid record and previous one
     346              : #[derive(Debug, Clone, Copy)]
     347              : pub struct RecordLsn {
     348              :     /// LSN at the end of the current record
     349              :     pub last: Lsn,
     350              :     /// LSN at the end of the previous record
     351              :     pub prev: Lsn,
     352              : }
     353              : 
     354              : /// Expose `self.last` as counter to be able to use RecordLsn in SeqWait
     355              : impl MonotonicCounter<Lsn> for RecordLsn {
     356      9608920 :     fn cnt_advance(&mut self, lsn: Lsn) {
     357      9608920 :         assert!(self.last <= lsn);
     358      9608920 :         let new_prev = self.last;
     359      9608920 :         self.last = lsn;
     360      9608920 :         self.prev = new_prev;
     361      9608920 :     }
     362     11006625 :     fn cnt_value(&self) -> Lsn {
     363     11006625 :         self.last
     364     11006625 :     }
     365              : }
     366              : 
     367              : /// Implements  [`rand::distributions::uniform::UniformSampler`] so we can sample [`Lsn`]s.
     368              : ///
     369              : /// This is used by the `pagebench` pageserver benchmarking tool.
     370              : pub struct LsnSampler(<u64 as rand::distributions::uniform::SampleUniform>::Sampler);
     371              : 
     372              : impl rand::distributions::uniform::SampleUniform for Lsn {
     373              :     type Sampler = LsnSampler;
     374              : }
     375              : 
     376              : impl rand::distributions::uniform::UniformSampler for LsnSampler {
     377              :     type X = Lsn;
     378              : 
     379            0 :     fn new<B1, B2>(low: B1, high: B2) -> Self
     380            0 :     where
     381            0 :         B1: rand::distributions::uniform::SampleBorrow<Self::X> + Sized,
     382            0 :         B2: rand::distributions::uniform::SampleBorrow<Self::X> + Sized,
     383            0 :     {
     384            0 :         Self(
     385            0 :             <u64 as rand::distributions::uniform::SampleUniform>::Sampler::new(
     386            0 :                 low.borrow().0,
     387            0 :                 high.borrow().0,
     388            0 :             ),
     389            0 :         )
     390            0 :     }
     391              : 
     392            0 :     fn new_inclusive<B1, B2>(low: B1, high: B2) -> Self
     393            0 :     where
     394            0 :         B1: rand::distributions::uniform::SampleBorrow<Self::X> + Sized,
     395            0 :         B2: rand::distributions::uniform::SampleBorrow<Self::X> + Sized,
     396            0 :     {
     397            0 :         Self(
     398            0 :             <u64 as rand::distributions::uniform::SampleUniform>::Sampler::new_inclusive(
     399            0 :                 low.borrow().0,
     400            0 :                 high.borrow().0,
     401            0 :             ),
     402            0 :         )
     403            0 :     }
     404              : 
     405            0 :     fn sample<R: rand::prelude::Rng + ?Sized>(&self, rng: &mut R) -> Self::X {
     406            0 :         Lsn(self.0.sample(rng))
     407            0 :     }
     408              : }
     409              : 
     410              : #[cfg(test)]
     411              : mod tests {
     412              :     use serde_assert::{Deserializer, Serializer, Token, Tokens};
     413              : 
     414              :     use super::*;
     415              :     use crate::bin_ser::BeSer;
     416              : 
     417              :     #[test]
     418            1 :     fn test_lsn_strings() {
     419            1 :         assert_eq!("12345678/AAAA5555".parse(), Ok(Lsn(0x12345678AAAA5555)));
     420            1 :         assert_eq!("aaaa/bbbb".parse(), Ok(Lsn(0x0000AAAA0000BBBB)));
     421            1 :         assert_eq!("1/A".parse(), Ok(Lsn(0x000000010000000A)));
     422            1 :         assert_eq!("0/0".parse(), Ok(Lsn(0)));
     423            1 :         "ABCDEFG/12345678".parse::<Lsn>().unwrap_err();
     424            1 :         "123456789/AAAA5555".parse::<Lsn>().unwrap_err();
     425            1 :         "12345678/AAAA55550".parse::<Lsn>().unwrap_err();
     426            1 :         "-1/0".parse::<Lsn>().unwrap_err();
     427            1 :         "1/-1".parse::<Lsn>().unwrap_err();
     428            1 : 
     429            1 :         assert_eq!(format!("{}", Lsn(0x12345678AAAA5555)), "12345678/AAAA5555");
     430            1 :         assert_eq!(format!("{}", Lsn(0x000000010000000A)), "1/A");
     431              : 
     432            1 :         assert_eq!(
     433            1 :             Lsn::from_hex("12345678AAAA5555"),
     434            1 :             Ok(Lsn(0x12345678AAAA5555))
     435            1 :         );
     436            1 :         assert_eq!(Lsn::from_hex("0"), Ok(Lsn(0)));
     437            1 :         assert_eq!(Lsn::from_hex("F12345678AAAA5555"), Err(LsnParseError));
     438              : 
     439            1 :         let expected_lsn = Lsn(0x3C490F8);
     440            1 :         assert_eq!(" 0/3C490F8".parse(), Ok(expected_lsn));
     441            1 :         assert_eq!("0/3C490F8 ".parse(), Ok(expected_lsn));
     442            1 :         assert_eq!(" 0/3C490F8 ".parse(), Ok(expected_lsn));
     443            1 :     }
     444              : 
     445              :     #[test]
     446            1 :     fn test_lsn_math() {
     447            1 :         assert_eq!(Lsn(1234) + 11u64, Lsn(1245));
     448              : 
     449            1 :         assert_eq!(
     450            1 :             {
     451            1 :                 let mut lsn = Lsn(1234);
     452            1 :                 lsn += 11u64;
     453            1 :                 lsn
     454            1 :             },
     455            1 :             Lsn(1245)
     456            1 :         );
     457              : 
     458            1 :         assert_eq!(Lsn(1234).checked_sub(1233u64), Some(Lsn(1)));
     459            1 :         assert_eq!(Lsn(1234).checked_sub(1235u64), None);
     460              : 
     461            1 :         assert_eq!(Lsn(1235).widening_sub(1234u64), 1);
     462            1 :         assert_eq!(Lsn(1234).widening_sub(1235u64), -1);
     463            1 :         assert_eq!(Lsn(u64::MAX).widening_sub(0u64), i128::from(u64::MAX));
     464            1 :         assert_eq!(Lsn(0).widening_sub(u64::MAX), -i128::from(u64::MAX));
     465              : 
     466            1 :         let seg_sz: usize = 16 * 1024 * 1024;
     467            1 :         assert_eq!(Lsn(0x1000007).segment_offset(seg_sz), 7);
     468            1 :         assert_eq!(Lsn(0x1000007).segment_number(seg_sz), 1u64);
     469              : 
     470            1 :         assert_eq!(Lsn(0x4007).block_offset(), 7u64);
     471            1 :         assert_eq!(Lsn(0x4000).block_offset(), 0u64);
     472            1 :         assert_eq!(Lsn(0x4007).remaining_in_block(), 8185u64);
     473            1 :         assert_eq!(Lsn(0x4000).remaining_in_block(), 8192u64);
     474              : 
     475            1 :         assert_eq!(Lsn(0xffff01).calc_padding(seg_sz as u64), 255u64);
     476            1 :         assert_eq!(Lsn(0x2000000).calc_padding(seg_sz as u64), 0u64);
     477            1 :         assert_eq!(Lsn(0xffff01).calc_padding(8u32), 7u64);
     478            1 :         assert_eq!(Lsn(0xffff00).calc_padding(8u32), 0u64);
     479            1 :     }
     480              : 
     481              :     #[test]
     482            1 :     fn test_atomic_lsn() {
     483            1 :         let lsn = AtomicLsn::new(0);
     484            1 :         assert_eq!(lsn.fetch_add(1234), Lsn(0));
     485            1 :         assert_eq!(lsn.load(), Lsn(1234));
     486            1 :         lsn.store(Lsn(5678));
     487            1 :         assert_eq!(lsn.load(), Lsn(5678));
     488              : 
     489            1 :         assert_eq!(lsn.fetch_max(Lsn(6000)), Lsn(5678));
     490            1 :         assert_eq!(lsn.fetch_max(Lsn(5000)), Lsn(6000));
     491            1 :     }
     492              : 
     493              :     #[test]
     494            1 :     fn test_lsn_serde() {
     495            1 :         let original_lsn = Lsn(0x0123456789abcdef);
     496            1 :         let expected_readable_tokens = Tokens(vec![Token::U64(0x0123456789abcdef)]);
     497            1 :         let expected_non_readable_tokens =
     498            1 :             Tokens(vec![Token::Str(String::from("1234567/89ABCDEF"))]);
     499            1 : 
     500            1 :         // Testing human_readable ser/de
     501            1 :         let serializer = Serializer::builder().is_human_readable(false).build();
     502            1 :         let readable_ser_tokens = original_lsn.serialize(&serializer).unwrap();
     503            1 :         assert_eq!(readable_ser_tokens, expected_readable_tokens);
     504              : 
     505            1 :         let mut deserializer = Deserializer::builder()
     506            1 :             .is_human_readable(false)
     507            1 :             .tokens(readable_ser_tokens)
     508            1 :             .build();
     509            1 :         let des_lsn = Lsn::deserialize(&mut deserializer).unwrap();
     510            1 :         assert_eq!(des_lsn, original_lsn);
     511              : 
     512              :         // Testing NON human_readable ser/de
     513            1 :         let serializer = Serializer::builder().is_human_readable(true).build();
     514            1 :         let non_readable_ser_tokens = original_lsn.serialize(&serializer).unwrap();
     515            1 :         assert_eq!(non_readable_ser_tokens, expected_non_readable_tokens);
     516              : 
     517            1 :         let mut deserializer = Deserializer::builder()
     518            1 :             .is_human_readable(true)
     519            1 :             .tokens(non_readable_ser_tokens)
     520            1 :             .build();
     521            1 :         let des_lsn = Lsn::deserialize(&mut deserializer).unwrap();
     522            1 :         assert_eq!(des_lsn, original_lsn);
     523              : 
     524              :         // Testing mismatching ser/de
     525            1 :         let serializer = Serializer::builder().is_human_readable(false).build();
     526            1 :         let non_readable_ser_tokens = original_lsn.serialize(&serializer).unwrap();
     527            1 : 
     528            1 :         let mut deserializer = Deserializer::builder()
     529            1 :             .is_human_readable(true)
     530            1 :             .tokens(non_readable_ser_tokens)
     531            1 :             .build();
     532            1 :         Lsn::deserialize(&mut deserializer).unwrap_err();
     533            1 : 
     534            1 :         let serializer = Serializer::builder().is_human_readable(true).build();
     535            1 :         let readable_ser_tokens = original_lsn.serialize(&serializer).unwrap();
     536            1 : 
     537            1 :         let mut deserializer = Deserializer::builder()
     538            1 :             .is_human_readable(false)
     539            1 :             .tokens(readable_ser_tokens)
     540            1 :             .build();
     541            1 :         Lsn::deserialize(&mut deserializer).unwrap_err();
     542            1 :     }
     543              : 
     544              :     #[test]
     545            1 :     fn test_lsn_ensure_roundtrip() {
     546            1 :         let original_lsn = Lsn(0xaaaabbbb);
     547            1 : 
     548            1 :         let serializer = Serializer::builder().is_human_readable(false).build();
     549            1 :         let ser_tokens = original_lsn.serialize(&serializer).unwrap();
     550            1 : 
     551            1 :         let mut deserializer = Deserializer::builder()
     552            1 :             .is_human_readable(false)
     553            1 :             .tokens(ser_tokens)
     554            1 :             .build();
     555            1 : 
     556            1 :         let des_lsn = Lsn::deserialize(&mut deserializer).unwrap();
     557            1 :         assert_eq!(des_lsn, original_lsn);
     558            1 :     }
     559              : 
     560              :     #[test]
     561            1 :     fn test_lsn_bincode_serde() {
     562            1 :         let lsn = Lsn(0x0123456789abcdef);
     563            1 :         let expected_bytes = [0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef];
     564            1 : 
     565            1 :         let ser_bytes = lsn.ser().unwrap();
     566            1 :         assert_eq!(ser_bytes, expected_bytes);
     567              : 
     568            1 :         let des_lsn = Lsn::des(&ser_bytes).unwrap();
     569            1 :         assert_eq!(des_lsn, lsn);
     570            1 :     }
     571              : 
     572              :     #[test]
     573            1 :     fn test_lsn_bincode_ensure_roundtrip() {
     574            1 :         let original_lsn = Lsn(0x01_02_03_04_05_06_07_08);
     575            1 :         let expected_bytes = vec![0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08];
     576            1 : 
     577            1 :         let ser_bytes = original_lsn.ser().unwrap();
     578            1 :         assert_eq!(ser_bytes, expected_bytes);
     579              : 
     580            1 :         let des_lsn = Lsn::des(&ser_bytes).unwrap();
     581            1 :         assert_eq!(des_lsn, original_lsn);
     582            1 :     }
     583              : }
        

Generated by: LCOV version 2.1-beta