LCOV - code coverage report
Current view: top level - libs/utils/src - lsn.rs (source / functions) Coverage Total Hit
Test: a43a77853355b937a79c57b07a8f05607cf29e6c.info Lines: 84.8 % 329 279
Test Date: 2024-09-19 12:04:32 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        61650 :     fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
      21        61650 :     where
      22        61650 :         S: serde::Serializer,
      23        61650 :     {
      24        61650 :         if serializer.is_human_readable() {
      25        51193 :             serializer.collect_str(self)
      26              :         } else {
      27        10457 :             self.0.serialize(serializer)
      28              :         }
      29        61650 :     }
      30              : }
      31              : 
      32              : impl<'de> Deserialize<'de> for Lsn {
      33        65631 :     fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
      34        65631 :     where
      35        65631 :         D: serde::Deserializer<'de>,
      36        65631 :     {
      37              :         struct LsnVisitor {
      38              :             is_human_readable_deserializer: bool,
      39              :         }
      40              : 
      41              :         impl<'de> Visitor<'de> for LsnVisitor {
      42              :             type Value = Lsn;
      43              : 
      44            2 :             fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
      45            2 :                 if self.is_human_readable_deserializer {
      46            1 :                     formatter.write_str(
      47            1 :                         "value in form of hex string({upper_u32_hex}/{lower_u32_hex}) representing u64 integer",
      48            1 :                     )
      49              :                 } else {
      50            1 :                     formatter.write_str("value in form of integer(u64)")
      51              :                 }
      52            2 :             }
      53              : 
      54        64974 :             fn visit_u64<E>(self, v: u64) -> Result<Self::Value, E>
      55        64974 :             where
      56        64974 :                 E: serde::de::Error,
      57        64974 :             {
      58        64974 :                 Ok(Lsn(v))
      59        64974 :             }
      60              : 
      61          655 :             fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
      62          655 :             where
      63          655 :                 E: serde::de::Error,
      64          655 :             {
      65          655 :                 Lsn::from_str(v).map_err(|e| E::custom(e))
      66          655 :             }
      67              :         }
      68              : 
      69        65631 :         if deserializer.is_human_readable() {
      70          656 :             deserializer.deserialize_str(LsnVisitor {
      71          656 :                 is_human_readable_deserializer: true,
      72          656 :             })
      73              :         } else {
      74        64975 :             deserializer.deserialize_u64(LsnVisitor {
      75        64975 :                 is_human_readable_deserializer: false,
      76        64975 :             })
      77              :         }
      78        65631 :     }
      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              :         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              :         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        18185 :     pub fn checked_sub<T: Into<u64>>(self, other: T) -> Option<Lsn> {
     138        18185 :         let other: u64 = other.into();
     139        18185 :         self.0.checked_sub(other).map(Lsn)
     140        18185 :     }
     141              : 
     142              :     /// Subtract a number, returning the difference as i128 to avoid overflow.
     143     14409064 :     pub fn widening_sub<T: Into<u64>>(self, other: T) -> i128 {
     144     14409064 :         let other: u64 = other.into();
     145     14409064 :         i128::from(self.0) - i128::from(other)
     146     14409064 :     }
     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        14829 :     pub fn from_hex<S>(s: S) -> Result<Self, LsnParseError>
     158        14829 :     where
     159        14829 :         S: AsRef<str>,
     160        14829 :     {
     161        14829 :         let s: &str = s.as_ref();
     162        14829 :         let n = u64::from_str_radix(s, 16).or(Err(LsnParseError))?;
     163        14828 :         Ok(Lsn(n))
     164        14829 :     }
     165              : 
     166              :     /// Compute the offset into a segment
     167              :     #[inline]
     168      2467509 :     pub fn segment_offset(self, seg_sz: usize) -> usize {
     169      2467509 :         (self.0 % seg_sz as u64) as usize
     170      2467509 :     }
     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        66675 :     pub fn segment_number(self, seg_sz: usize) -> u64 {
     181        66675 :         self.0 / seg_sz as u64
     182        66675 :     }
     183              : 
     184              :     /// Compute the offset into a block
     185              :     #[inline]
     186      2383896 :     pub fn block_offset(self) -> u64 {
     187              :         const BLCKSZ: u64 = XLOG_BLCKSZ as u64;
     188      2383896 :         self.0 % BLCKSZ
     189      2383896 :     }
     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      2300945 :     pub fn remaining_in_block(self) -> u64 {
     210              :         const BLCKSZ: u64 = XLOG_BLCKSZ as u64;
     211      2300945 :         BLCKSZ - (self.0 % BLCKSZ)
     212      2300945 :     }
     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            4 :     pub fn calc_padding<T: Into<u64>>(self, sz: T) -> u64 {
     218            4 :         let sz: u64 = sz.into();
     219            4 :         // By using wrapping_sub, we can subtract first and then mod second.
     220            4 :         // If it's done the other way around, then we would return a full
     221            4 :         // chunk size if we're already at the chunk boundary.
     222            4 :         // (Regular subtraction will panic on overflow in debug builds.)
     223            4 :         (sz.wrapping_sub(self.0)) % sz
     224            4 :     }
     225              : 
     226              :     /// Align LSN on 8-byte boundary (alignment of WAL records).
     227     16318772 :     pub fn align(&self) -> Lsn {
     228     16318772 :         Lsn((self.0 + 7) & !7)
     229     16318772 :     }
     230              : 
     231              :     /// Align LSN on 8-byte boundary (alignment of WAL records).
     232     15841182 :     pub fn is_aligned(&self) -> bool {
     233     15841182 :         *self == self.align()
     234     15841182 :     }
     235              : 
     236              :     /// Return if the LSN is valid
     237              :     /// mimics postgres XLogRecPtrIsInvalid macro
     238     26171994 :     pub fn is_valid(self) -> bool {
     239     26171994 :         self != Lsn::INVALID
     240     26171994 :     }
     241              : }
     242              : 
     243              : impl From<u64> for Lsn {
     244        37394 :     fn from(n: u64) -> Self {
     245        37394 :         Lsn(n)
     246        37394 :     }
     247              : }
     248              : 
     249              : impl From<Lsn> for u64 {
     250     14776744 :     fn from(lsn: Lsn) -> u64 {
     251     14776744 :         lsn.0
     252     14776744 :     }
     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         2375 :     fn from_str(s: &str) -> Result<Self, Self::Err> {
     262         2375 :         let mut splitter = s.trim().split('/');
     263         2375 :         if let (Some(left), Some(right), None) = (splitter.next(), splitter.next(), splitter.next())
     264              :         {
     265         2375 :             let left_num = u32::from_str_radix(left, 16).map_err(|_| LsnParseError)?;
     266         2372 :             let right_num = u32::from_str_radix(right, 16).map_err(|_| LsnParseError)?;
     267         2370 :             Ok(Lsn((left_num as u64) << 32 | right_num as u64))
     268              :         } else {
     269            0 :             Err(LsnParseError)
     270              :         }
     271         2375 :     }
     272              : }
     273              : 
     274              : impl fmt::Display for Lsn {
     275     15503334 :     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     276     15503334 :         write!(f, "{:X}/{:X}", self.0 >> 32, self.0 & 0xffffffff)
     277     15503334 :     }
     278              : }
     279              : 
     280              : impl fmt::Debug for Lsn {
     281        21976 :     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     282        21976 :         write!(f, "{:X}/{:X}", self.0 >> 32, self.0 & 0xffffffff)
     283        21976 :     }
     284              : }
     285              : 
     286              : impl Add<u64> for Lsn {
     287              :     type Output = Lsn;
     288              : 
     289      8907324 :     fn add(self, other: u64) -> Self::Output {
     290      8907324 :         // panic if the addition overflows.
     291      8907324 :         Lsn(self.0.checked_add(other).unwrap())
     292      8907324 :     }
     293              : }
     294              : 
     295              : impl AddAssign<u64> for Lsn {
     296      2247001 :     fn add_assign(&mut self, other: u64) {
     297      2247001 :         // panic if the addition overflows.
     298      2247001 :         self.0 = self.0.checked_add(other).unwrap();
     299      2247001 :     }
     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         6181 :     pub fn new(val: u64) -> Self {
     310         6181 :         AtomicLsn {
     311         6181 :             inner: AtomicU64::new(val),
     312         6181 :         }
     313         6181 :     }
     314              : 
     315              :     /// Atomically retrieve the `Lsn` value from memory.
     316     14420764 :     pub fn load(&self) -> Lsn {
     317     14420764 :         Lsn(self.inner.load(Ordering::Acquire))
     318     14420764 :     }
     319              : 
     320              :     /// Atomically store a new `Lsn` value to memory.
     321         6293 :     pub fn store(&self, lsn: Lsn) {
     322         6293 :         self.inner.store(lsn.0, Ordering::Release);
     323         6293 :     }
     324              : 
     325              :     /// Adds to the current value, returning the previous value.
     326              :     ///
     327              :     /// This operation will panic on overflow.
     328            1 :     pub fn fetch_add(&self, val: u64) -> Lsn {
     329            1 :         let prev = self.inner.fetch_add(val, Ordering::AcqRel);
     330            1 :         assert!(prev.checked_add(val).is_some(), "AtomicLsn overflow");
     331            1 :         Lsn(prev)
     332            1 :     }
     333              : 
     334              :     /// Atomically sets the Lsn to the max of old and new value, returning the old value.
     335         3422 :     pub fn fetch_max(&self, lsn: Lsn) -> Lsn {
     336         3422 :         let prev = self.inner.fetch_max(lsn.0, Ordering::AcqRel);
     337         3422 :         Lsn(prev)
     338         3422 :     }
     339              : }
     340              : 
     341              : impl From<Lsn> for AtomicLsn {
     342           18 :     fn from(lsn: Lsn) -> Self {
     343           18 :         Self::new(lsn.0)
     344           18 :     }
     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     14413266 :     fn cnt_advance(&mut self, lsn: Lsn) {
     359     14413266 :         assert!(self.last <= lsn);
     360     14413266 :         let new_prev = self.last;
     361     14413266 :         self.last = lsn;
     362     14413266 :         self.prev = new_prev;
     363     14413266 :     }
     364     16515748 :     fn cnt_value(&self) -> Lsn {
     365     16515748 :         self.last
     366     16515748 :     }
     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            1 :     fn test_lsn_strings() {
     422            1 :         assert_eq!("12345678/AAAA5555".parse(), Ok(Lsn(0x12345678AAAA5555)));
     423            1 :         assert_eq!("aaaa/bbbb".parse(), Ok(Lsn(0x0000AAAA0000BBBB)));
     424            1 :         assert_eq!("1/A".parse(), Ok(Lsn(0x000000010000000A)));
     425            1 :         assert_eq!("0/0".parse(), Ok(Lsn(0)));
     426            1 :         "ABCDEFG/12345678".parse::<Lsn>().unwrap_err();
     427            1 :         "123456789/AAAA5555".parse::<Lsn>().unwrap_err();
     428            1 :         "12345678/AAAA55550".parse::<Lsn>().unwrap_err();
     429            1 :         "-1/0".parse::<Lsn>().unwrap_err();
     430            1 :         "1/-1".parse::<Lsn>().unwrap_err();
     431            1 : 
     432            1 :         assert_eq!(format!("{}", Lsn(0x12345678AAAA5555)), "12345678/AAAA5555");
     433            1 :         assert_eq!(format!("{}", Lsn(0x000000010000000A)), "1/A");
     434              : 
     435            1 :         assert_eq!(
     436            1 :             Lsn::from_hex("12345678AAAA5555"),
     437            1 :             Ok(Lsn(0x12345678AAAA5555))
     438            1 :         );
     439            1 :         assert_eq!(Lsn::from_hex("0"), Ok(Lsn(0)));
     440            1 :         assert_eq!(Lsn::from_hex("F12345678AAAA5555"), Err(LsnParseError));
     441              : 
     442            1 :         let expected_lsn = Lsn(0x3C490F8);
     443            1 :         assert_eq!(" 0/3C490F8".parse(), Ok(expected_lsn));
     444            1 :         assert_eq!("0/3C490F8 ".parse(), Ok(expected_lsn));
     445            1 :         assert_eq!(" 0/3C490F8 ".parse(), Ok(expected_lsn));
     446            1 :     }
     447              : 
     448              :     #[test]
     449            1 :     fn test_lsn_math() {
     450            1 :         assert_eq!(Lsn(1234) + 11u64, Lsn(1245));
     451              : 
     452            1 :         assert_eq!(
     453            1 :             {
     454            1 :                 let mut lsn = Lsn(1234);
     455            1 :                 lsn += 11u64;
     456            1 :                 lsn
     457            1 :             },
     458            1 :             Lsn(1245)
     459            1 :         );
     460              : 
     461            1 :         assert_eq!(Lsn(1234).checked_sub(1233u64), Some(Lsn(1)));
     462            1 :         assert_eq!(Lsn(1234).checked_sub(1235u64), None);
     463              : 
     464            1 :         assert_eq!(Lsn(1235).widening_sub(1234u64), 1);
     465            1 :         assert_eq!(Lsn(1234).widening_sub(1235u64), -1);
     466            1 :         assert_eq!(Lsn(u64::MAX).widening_sub(0u64), i128::from(u64::MAX));
     467            1 :         assert_eq!(Lsn(0).widening_sub(u64::MAX), -i128::from(u64::MAX));
     468              : 
     469            1 :         let seg_sz: usize = 16 * 1024 * 1024;
     470            1 :         assert_eq!(Lsn(0x1000007).segment_offset(seg_sz), 7);
     471            1 :         assert_eq!(Lsn(0x1000007).segment_number(seg_sz), 1u64);
     472              : 
     473            1 :         assert_eq!(Lsn(0x4007).block_offset(), 7u64);
     474            1 :         assert_eq!(Lsn(0x4000).block_offset(), 0u64);
     475            1 :         assert_eq!(Lsn(0x4007).remaining_in_block(), 8185u64);
     476            1 :         assert_eq!(Lsn(0x4000).remaining_in_block(), 8192u64);
     477              : 
     478            1 :         assert_eq!(Lsn(0xffff01).calc_padding(seg_sz as u64), 255u64);
     479            1 :         assert_eq!(Lsn(0x2000000).calc_padding(seg_sz as u64), 0u64);
     480            1 :         assert_eq!(Lsn(0xffff01).calc_padding(8u32), 7u64);
     481            1 :         assert_eq!(Lsn(0xffff00).calc_padding(8u32), 0u64);
     482            1 :     }
     483              : 
     484              :     #[test]
     485            1 :     fn test_atomic_lsn() {
     486            1 :         let lsn = AtomicLsn::new(0);
     487            1 :         assert_eq!(lsn.fetch_add(1234), Lsn(0));
     488            1 :         assert_eq!(lsn.load(), Lsn(1234));
     489            1 :         lsn.store(Lsn(5678));
     490            1 :         assert_eq!(lsn.load(), Lsn(5678));
     491              : 
     492            1 :         assert_eq!(lsn.fetch_max(Lsn(6000)), Lsn(5678));
     493            1 :         assert_eq!(lsn.fetch_max(Lsn(5000)), Lsn(6000));
     494            1 :     }
     495              : 
     496              :     #[test]
     497            1 :     fn test_lsn_serde() {
     498            1 :         let original_lsn = Lsn(0x0123456789abcdef);
     499            1 :         let expected_readable_tokens = Tokens(vec![Token::U64(0x0123456789abcdef)]);
     500            1 :         let expected_non_readable_tokens =
     501            1 :             Tokens(vec![Token::Str(String::from("1234567/89ABCDEF"))]);
     502            1 : 
     503            1 :         // Testing human_readable ser/de
     504            1 :         let serializer = Serializer::builder().is_human_readable(false).build();
     505            1 :         let readable_ser_tokens = original_lsn.serialize(&serializer).unwrap();
     506            1 :         assert_eq!(readable_ser_tokens, expected_readable_tokens);
     507              : 
     508            1 :         let mut deserializer = Deserializer::builder()
     509            1 :             .is_human_readable(false)
     510            1 :             .tokens(readable_ser_tokens)
     511            1 :             .build();
     512            1 :         let des_lsn = Lsn::deserialize(&mut deserializer).unwrap();
     513            1 :         assert_eq!(des_lsn, original_lsn);
     514              : 
     515              :         // Testing NON human_readable ser/de
     516            1 :         let serializer = Serializer::builder().is_human_readable(true).build();
     517            1 :         let non_readable_ser_tokens = original_lsn.serialize(&serializer).unwrap();
     518            1 :         assert_eq!(non_readable_ser_tokens, expected_non_readable_tokens);
     519              : 
     520            1 :         let mut deserializer = Deserializer::builder()
     521            1 :             .is_human_readable(true)
     522            1 :             .tokens(non_readable_ser_tokens)
     523            1 :             .build();
     524            1 :         let des_lsn = Lsn::deserialize(&mut deserializer).unwrap();
     525            1 :         assert_eq!(des_lsn, original_lsn);
     526              : 
     527              :         // Testing mismatching ser/de
     528            1 :         let serializer = Serializer::builder().is_human_readable(false).build();
     529            1 :         let non_readable_ser_tokens = original_lsn.serialize(&serializer).unwrap();
     530            1 : 
     531            1 :         let mut deserializer = Deserializer::builder()
     532            1 :             .is_human_readable(true)
     533            1 :             .tokens(non_readable_ser_tokens)
     534            1 :             .build();
     535            1 :         Lsn::deserialize(&mut deserializer).unwrap_err();
     536            1 : 
     537            1 :         let serializer = Serializer::builder().is_human_readable(true).build();
     538            1 :         let readable_ser_tokens = original_lsn.serialize(&serializer).unwrap();
     539            1 : 
     540            1 :         let mut deserializer = Deserializer::builder()
     541            1 :             .is_human_readable(false)
     542            1 :             .tokens(readable_ser_tokens)
     543            1 :             .build();
     544            1 :         Lsn::deserialize(&mut deserializer).unwrap_err();
     545            1 :     }
     546              : 
     547              :     #[test]
     548            1 :     fn test_lsn_ensure_roundtrip() {
     549            1 :         let original_lsn = Lsn(0xaaaabbbb);
     550            1 : 
     551            1 :         let serializer = Serializer::builder().is_human_readable(false).build();
     552            1 :         let ser_tokens = original_lsn.serialize(&serializer).unwrap();
     553            1 : 
     554            1 :         let mut deserializer = Deserializer::builder()
     555            1 :             .is_human_readable(false)
     556            1 :             .tokens(ser_tokens)
     557            1 :             .build();
     558            1 : 
     559            1 :         let des_lsn = Lsn::deserialize(&mut deserializer).unwrap();
     560            1 :         assert_eq!(des_lsn, original_lsn);
     561            1 :     }
     562              : 
     563              :     #[test]
     564            1 :     fn test_lsn_bincode_serde() {
     565            1 :         let lsn = Lsn(0x0123456789abcdef);
     566            1 :         let expected_bytes = [0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef];
     567            1 : 
     568            1 :         let ser_bytes = lsn.ser().unwrap();
     569            1 :         assert_eq!(ser_bytes, expected_bytes);
     570              : 
     571            1 :         let des_lsn = Lsn::des(&ser_bytes).unwrap();
     572            1 :         assert_eq!(des_lsn, lsn);
     573            1 :     }
     574              : 
     575              :     #[test]
     576            1 :     fn test_lsn_bincode_ensure_roundtrip() {
     577            1 :         let original_lsn = Lsn(0x01_02_03_04_05_06_07_08);
     578            1 :         let expected_bytes = vec![0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08];
     579            1 : 
     580            1 :         let ser_bytes = original_lsn.ser().unwrap();
     581            1 :         assert_eq!(ser_bytes, expected_bytes);
     582              : 
     583            1 :         let des_lsn = Lsn::des(&ser_bytes).unwrap();
     584            1 :         assert_eq!(des_lsn, original_lsn);
     585            1 :     }
     586              : }
        

Generated by: LCOV version 2.1-beta