LCOV - code coverage report
Current view: top level - libs/utils/src - lsn.rs (source / functions) Coverage Total Hit
Test: 7eb96e224e685167ad85f58f858387d8cf253f63.info Lines: 86.4 % 323 279
Test Date: 2024-09-23 21:23:07 Functions: 67.4 % 92 62

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

Generated by: LCOV version 2.1-beta