LCOV - code coverage report
Current view: top level - libs/utils/src - lsn.rs (source / functions) Coverage Total Hit
Test: 02e8c57acd6e2b986849f552ca30280d54699b79.info Lines: 85.0 % 346 294
Test Date: 2024-06-26 17:13:54 Functions: 60.8 % 102 62

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

Generated by: LCOV version 2.1-beta