TLA 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 CBC 640361986 : #[derive(Clone, Copy, Eq, Ord, PartialEq, PartialOrd, Hash)]
17 : pub struct Lsn(pub u64);
18 :
19 : impl Serialize for Lsn {
20 217242 : fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
21 217242 : where
22 217242 : S: serde::Serializer,
23 217242 : {
24 217242 : if serializer.is_human_readable() {
25 40069 : serializer.collect_str(self)
26 : } else {
27 177173 : self.0.serialize(serializer)
28 : }
29 217242 : }
30 : }
31 :
32 : impl<'de> Deserialize<'de> for Lsn {
33 9937681 : fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
34 9937681 : where
35 9937681 : D: serde::Deserializer<'de>,
36 9937681 : {
37 9937681 : struct LsnVisitor {
38 9937681 : is_human_readable_deserializer: bool,
39 9937681 : }
40 9937681 :
41 9937681 : impl<'de> Visitor<'de> for LsnVisitor {
42 9937681 : type Value = Lsn;
43 9937681 :
44 9937681 : fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
45 2 : if self.is_human_readable_deserializer {
46 9937681 : formatter.write_str(
47 1 : "value in form of hex string({upper_u32_hex}/{lower_u32_hex}) representing u64 integer",
48 1 : )
49 9937681 : } else {
50 9937681 : formatter.write_str("value in form of integer(u64)")
51 9937681 : }
52 9937681 : }
53 9937681 :
54 9937681 : fn visit_u64<E>(self, v: u64) -> Result<Self::Value, E>
55 9930667 : where
56 9930667 : E: serde::de::Error,
57 9930667 : {
58 9930667 : Ok(Lsn(v))
59 9930667 : }
60 9937681 :
61 9937681 : fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
62 7012 : where
63 7012 : E: serde::de::Error,
64 7012 : {
65 7012 : Lsn::from_str(v).map_err(|e| E::custom(e))
66 7012 : }
67 9937681 : }
68 9937681 :
69 9937681 : if deserializer.is_human_readable() {
70 7013 : deserializer.deserialize_str(LsnVisitor {
71 7013 : is_human_readable_deserializer: true,
72 7013 : })
73 : } else {
74 9930668 : deserializer.deserialize_u64(LsnVisitor {
75 9930668 : is_human_readable_deserializer: false,
76 9930668 : })
77 : }
78 9937681 : }
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 UBC 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 CBC 9 : pub fn deserialize<'de, D: serde::Deserializer<'de>>(deserializer: D) -> Result<Lsn, D::Error> {
119 9 : use serde::Deserialize;
120 9 : u64::deserialize(deserializer).map(Lsn)
121 9 : }
122 : }
123 :
124 : /// We tried to parse an LSN from a string, but failed
125 1 : #[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 2042709 : pub fn checked_sub<T: Into<u64>>(self, other: T) -> Option<Lsn> {
138 2042709 : let other: u64 = other.into();
139 2042709 : self.0.checked_sub(other).map(Lsn)
140 2042709 : }
141 :
142 : /// Subtract a number, returning the difference as i128 to avoid overflow.
143 565118 : pub fn widening_sub<T: Into<u64>>(self, other: T) -> i128 {
144 565118 : let other: u64 = other.into();
145 565118 : i128::from(self.0) - i128::from(other)
146 565118 : }
147 :
148 : /// Parse an LSN from a filename in the form `0000000000000000`
149 UBC 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 CBC 138125 : pub fn from_hex<S>(s: S) -> Result<Self, LsnParseError>
158 138125 : where
159 138125 : S: AsRef<str>,
160 138125 : {
161 138125 : let s: &str = s.as_ref();
162 138125 : let n = u64::from_str_radix(s, 16).or(Err(LsnParseError))?;
163 107583 : Ok(Lsn(n))
164 138125 : }
165 :
166 : /// Compute the offset into a segment
167 : #[inline]
168 133502477 : pub fn segment_offset(self, seg_sz: usize) -> usize {
169 133502477 : (self.0 % seg_sz as u64) as usize
170 133502477 : }
171 :
172 : /// Compute LSN of the segment start.
173 : #[inline]
174 1408 : pub fn segment_lsn(self, seg_sz: usize) -> Lsn {
175 1408 : Lsn(self.0 - (self.0 % seg_sz as u64))
176 1408 : }
177 :
178 : /// Compute the segment number
179 : #[inline]
180 1246728 : pub fn segment_number(self, seg_sz: usize) -> u64 {
181 1246728 : self.0 / seg_sz as u64
182 1246728 : }
183 :
184 : /// Compute the offset into a block
185 : #[inline]
186 131194913 : pub fn block_offset(self) -> u64 {
187 131194913 : const BLCKSZ: u64 = XLOG_BLCKSZ as u64;
188 131194913 : self.0 % BLCKSZ
189 131194913 : }
190 :
191 : /// Compute the block offset of the first byte of this Lsn within this
192 : /// segment
193 : #[inline]
194 559 : pub fn page_lsn(self) -> Lsn {
195 559 : Lsn(self.0 - self.block_offset())
196 559 : }
197 :
198 : /// Compute the block offset of the first byte of this Lsn within this
199 : /// segment
200 : #[inline]
201 559 : pub fn page_offset_in_segment(self, seg_sz: usize) -> u64 {
202 559 : (self.0 - self.block_offset()) - self.segment_lsn(seg_sz).0
203 559 : }
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 129360538 : pub fn remaining_in_block(self) -> u64 {
210 129360538 : const BLCKSZ: u64 = XLOG_BLCKSZ as u64;
211 129360538 : BLCKSZ - (self.0 % BLCKSZ)
212 129360538 : }
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 730 : pub fn calc_padding<T: Into<u64>>(self, sz: T) -> u64 {
218 730 : let sz: u64 = sz.into();
219 730 : // By using wrapping_sub, we can subtract first and then mod second.
220 730 : // If it's done the other way around, then we would return a full
221 730 : // chunk size if we're already at the chunk boundary.
222 730 : // (Regular subtraction will panic on overflow in debug builds.)
223 730 : (sz.wrapping_sub(self.0)) % sz
224 730 : }
225 :
226 : /// Align LSN on 8-byte boundary (alignment of WAL records).
227 222392268 : pub fn align(&self) -> Lsn {
228 222392268 : Lsn((self.0 + 7) & !7)
229 222392268 : }
230 :
231 : /// Align LSN on 8-byte boundary (alignment of WAL records).
232 98494262 : pub fn is_aligned(&self) -> bool {
233 98494262 : *self == self.align()
234 98494262 : }
235 :
236 : /// Return if the LSN is valid
237 : /// mimics postgres XLogRecPtrIsInvalid macro
238 12983166 : pub fn is_valid(self) -> bool {
239 12983166 : self != Lsn::INVALID
240 12983166 : }
241 : }
242 :
243 : impl From<u64> for Lsn {
244 5338272 : fn from(n: u64) -> Self {
245 5338272 : Lsn(n)
246 5338272 : }
247 : }
248 :
249 : impl From<Lsn> for u64 {
250 7462645 : fn from(lsn: Lsn) -> u64 {
251 7462645 : lsn.0
252 7462645 : }
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 9463 : fn from_str(s: &str) -> Result<Self, Self::Err> {
262 9463 : let mut splitter = s.trim().split('/');
263 9463 : if let (Some(left), Some(right), None) = (splitter.next(), splitter.next(), splitter.next())
264 : {
265 9463 : let left_num = u32::from_str_radix(left, 16).map_err(|_| LsnParseError)?;
266 9460 : let right_num = u32::from_str_radix(right, 16).map_err(|_| LsnParseError)?;
267 9458 : Ok(Lsn((left_num as u64) << 32 | right_num as u64))
268 : } else {
269 UBC 0 : Err(LsnParseError)
270 : }
271 CBC 9463 : }
272 : }
273 :
274 : impl fmt::Display for Lsn {
275 4628681 : fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
276 4628681 : write!(f, "{:X}/{:X}", self.0 >> 32, self.0 & 0xffffffff)
277 4628681 : }
278 : }
279 :
280 : impl fmt::Debug for Lsn {
281 17098 : fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
282 17098 : write!(f, "{:X}/{:X}", self.0 >> 32, self.0 & 0xffffffff)
283 17098 : }
284 : }
285 :
286 : impl Add<u64> for Lsn {
287 : type Output = Lsn;
288 :
289 53293076 : fn add(self, other: u64) -> Self::Output {
290 53293076 : // panic if the addition overflows.
291 53293076 : Lsn(self.0.checked_add(other).unwrap())
292 53293076 : }
293 : }
294 :
295 : impl AddAssign<u64> for Lsn {
296 255410462 : fn add_assign(&mut self, other: u64) {
297 255410462 : // panic if the addition overflows.
298 255410462 : self.0 = self.0.checked_add(other).unwrap();
299 255410462 : }
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 4453 : pub fn new(val: u64) -> Self {
310 4453 : AtomicLsn {
311 4453 : inner: AtomicU64::new(val),
312 4453 : }
313 4453 : }
314 :
315 : /// Atomically retrieve the `Lsn` value from memory.
316 1735944 : pub fn load(&self) -> Lsn {
317 1735944 : Lsn(self.inner.load(Ordering::Acquire))
318 1735944 : }
319 :
320 : /// Atomically store a new `Lsn` value to memory.
321 12686 : pub fn store(&self, lsn: Lsn) {
322 12686 : self.inner.store(lsn.0, Ordering::Release);
323 12686 : }
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 577773 : pub fn fetch_max(&self, lsn: Lsn) -> Lsn {
336 577773 : let prev = self.inner.fetch_max(lsn.0, Ordering::AcqRel);
337 577773 : Lsn(prev)
338 577773 : }
339 : }
340 :
341 : impl From<Lsn> for AtomicLsn {
342 951 : fn from(lsn: Lsn) -> Self {
343 951 : Self::new(lsn.0)
344 951 : }
345 : }
346 :
347 : /// Pair of LSN's pointing to the end of the last valid record and previous one
348 UBC 0 : #[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 CBC 48222384 : fn cnt_advance(&mut self, lsn: Lsn) {
359 48222384 : assert!(self.last <= lsn);
360 48222384 : let new_prev = self.last;
361 48222384 : self.last = lsn;
362 48222384 : self.prev = new_prev;
363 48222384 : }
364 50782237 : fn cnt_value(&self) -> Lsn {
365 50782237 : self.last
366 50782237 : }
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 UBC 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::ser::Serialize;
419 : use serde_assert::{Deserializer, Serializer, Token, Tokens};
420 :
421 CBC 1 : #[test]
422 1 : fn test_lsn_strings() {
423 1 : assert_eq!("12345678/AAAA5555".parse(), Ok(Lsn(0x12345678AAAA5555)));
424 1 : assert_eq!("aaaa/bbbb".parse(), Ok(Lsn(0x0000AAAA0000BBBB)));
425 1 : assert_eq!("1/A".parse(), Ok(Lsn(0x000000010000000A)));
426 1 : assert_eq!("0/0".parse(), Ok(Lsn(0)));
427 1 : "ABCDEFG/12345678".parse::<Lsn>().unwrap_err();
428 1 : "123456789/AAAA5555".parse::<Lsn>().unwrap_err();
429 1 : "12345678/AAAA55550".parse::<Lsn>().unwrap_err();
430 1 : "-1/0".parse::<Lsn>().unwrap_err();
431 1 : "1/-1".parse::<Lsn>().unwrap_err();
432 1 :
433 1 : assert_eq!(format!("{}", Lsn(0x12345678AAAA5555)), "12345678/AAAA5555");
434 1 : assert_eq!(format!("{}", Lsn(0x000000010000000A)), "1/A");
435 :
436 1 : assert_eq!(
437 1 : Lsn::from_hex("12345678AAAA5555"),
438 1 : Ok(Lsn(0x12345678AAAA5555))
439 1 : );
440 1 : assert_eq!(Lsn::from_hex("0"), Ok(Lsn(0)));
441 1 : assert_eq!(Lsn::from_hex("F12345678AAAA5555"), Err(LsnParseError));
442 :
443 1 : let expected_lsn = Lsn(0x3C490F8);
444 1 : assert_eq!(" 0/3C490F8".parse(), Ok(expected_lsn));
445 1 : assert_eq!("0/3C490F8 ".parse(), Ok(expected_lsn));
446 1 : assert_eq!(" 0/3C490F8 ".parse(), Ok(expected_lsn));
447 1 : }
448 :
449 1 : #[test]
450 1 : fn test_lsn_math() {
451 1 : assert_eq!(Lsn(1234) + 11u64, Lsn(1245));
452 :
453 1 : assert_eq!(
454 1 : {
455 1 : let mut lsn = Lsn(1234);
456 1 : lsn += 11u64;
457 1 : lsn
458 1 : },
459 1 : Lsn(1245)
460 1 : );
461 :
462 1 : assert_eq!(Lsn(1234).checked_sub(1233u64), Some(Lsn(1)));
463 1 : assert_eq!(Lsn(1234).checked_sub(1235u64), None);
464 :
465 1 : assert_eq!(Lsn(1235).widening_sub(1234u64), 1);
466 1 : assert_eq!(Lsn(1234).widening_sub(1235u64), -1);
467 1 : assert_eq!(Lsn(u64::MAX).widening_sub(0u64), i128::from(u64::MAX));
468 1 : assert_eq!(Lsn(0).widening_sub(u64::MAX), -i128::from(u64::MAX));
469 :
470 1 : let seg_sz: usize = 16 * 1024 * 1024;
471 1 : assert_eq!(Lsn(0x1000007).segment_offset(seg_sz), 7);
472 1 : assert_eq!(Lsn(0x1000007).segment_number(seg_sz), 1u64);
473 :
474 1 : assert_eq!(Lsn(0x4007).block_offset(), 7u64);
475 1 : assert_eq!(Lsn(0x4000).block_offset(), 0u64);
476 1 : assert_eq!(Lsn(0x4007).remaining_in_block(), 8185u64);
477 1 : assert_eq!(Lsn(0x4000).remaining_in_block(), 8192u64);
478 :
479 1 : assert_eq!(Lsn(0xffff01).calc_padding(seg_sz as u64), 255u64);
480 1 : assert_eq!(Lsn(0x2000000).calc_padding(seg_sz as u64), 0u64);
481 1 : assert_eq!(Lsn(0xffff01).calc_padding(8u32), 7u64);
482 1 : assert_eq!(Lsn(0xffff00).calc_padding(8u32), 0u64);
483 1 : }
484 :
485 1 : #[test]
486 1 : fn test_atomic_lsn() {
487 1 : let lsn = AtomicLsn::new(0);
488 1 : assert_eq!(lsn.fetch_add(1234), Lsn(0));
489 1 : assert_eq!(lsn.load(), Lsn(1234));
490 1 : lsn.store(Lsn(5678));
491 1 : assert_eq!(lsn.load(), Lsn(5678));
492 :
493 1 : assert_eq!(lsn.fetch_max(Lsn(6000)), Lsn(5678));
494 1 : assert_eq!(lsn.fetch_max(Lsn(5000)), Lsn(6000));
495 1 : }
496 :
497 1 : #[test]
498 1 : fn test_lsn_serde() {
499 1 : let original_lsn = Lsn(0x0123456789abcdef);
500 1 : let expected_readable_tokens = Tokens(vec![Token::U64(0x0123456789abcdef)]);
501 1 : let expected_non_readable_tokens =
502 1 : Tokens(vec![Token::Str(String::from("1234567/89ABCDEF"))]);
503 1 :
504 1 : // Testing human_readable ser/de
505 1 : let serializer = Serializer::builder().is_human_readable(false).build();
506 1 : let readable_ser_tokens = original_lsn.serialize(&serializer).unwrap();
507 1 : assert_eq!(readable_ser_tokens, expected_readable_tokens);
508 :
509 1 : let mut deserializer = Deserializer::builder()
510 1 : .is_human_readable(false)
511 1 : .tokens(readable_ser_tokens)
512 1 : .build();
513 1 : let des_lsn = Lsn::deserialize(&mut deserializer).unwrap();
514 1 : assert_eq!(des_lsn, original_lsn);
515 :
516 : // Testing NON human_readable ser/de
517 1 : let serializer = Serializer::builder().is_human_readable(true).build();
518 1 : let non_readable_ser_tokens = original_lsn.serialize(&serializer).unwrap();
519 1 : assert_eq!(non_readable_ser_tokens, expected_non_readable_tokens);
520 :
521 1 : let mut deserializer = Deserializer::builder()
522 1 : .is_human_readable(true)
523 1 : .tokens(non_readable_ser_tokens)
524 1 : .build();
525 1 : let des_lsn = Lsn::deserialize(&mut deserializer).unwrap();
526 1 : assert_eq!(des_lsn, original_lsn);
527 :
528 : // Testing mismatching ser/de
529 1 : let serializer = Serializer::builder().is_human_readable(false).build();
530 1 : let non_readable_ser_tokens = original_lsn.serialize(&serializer).unwrap();
531 1 :
532 1 : let mut deserializer = Deserializer::builder()
533 1 : .is_human_readable(true)
534 1 : .tokens(non_readable_ser_tokens)
535 1 : .build();
536 1 : Lsn::deserialize(&mut deserializer).unwrap_err();
537 1 :
538 1 : let serializer = Serializer::builder().is_human_readable(true).build();
539 1 : let readable_ser_tokens = original_lsn.serialize(&serializer).unwrap();
540 1 :
541 1 : let mut deserializer = Deserializer::builder()
542 1 : .is_human_readable(false)
543 1 : .tokens(readable_ser_tokens)
544 1 : .build();
545 1 : Lsn::deserialize(&mut deserializer).unwrap_err();
546 1 : }
547 :
548 1 : #[test]
549 1 : fn test_lsn_ensure_roundtrip() {
550 1 : let original_lsn = Lsn(0xaaaabbbb);
551 1 :
552 1 : let serializer = Serializer::builder().is_human_readable(false).build();
553 1 : let ser_tokens = original_lsn.serialize(&serializer).unwrap();
554 1 :
555 1 : let mut deserializer = Deserializer::builder()
556 1 : .is_human_readable(false)
557 1 : .tokens(ser_tokens)
558 1 : .build();
559 1 :
560 1 : let des_lsn = Lsn::deserialize(&mut deserializer).unwrap();
561 1 : assert_eq!(des_lsn, original_lsn);
562 1 : }
563 :
564 1 : #[test]
565 1 : fn test_lsn_bincode_serde() {
566 1 : let lsn = Lsn(0x0123456789abcdef);
567 1 : let expected_bytes = [0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef];
568 1 :
569 1 : let ser_bytes = lsn.ser().unwrap();
570 1 : assert_eq!(ser_bytes, expected_bytes);
571 :
572 1 : let des_lsn = Lsn::des(&ser_bytes).unwrap();
573 1 : assert_eq!(des_lsn, lsn);
574 1 : }
575 :
576 1 : #[test]
577 1 : fn test_lsn_bincode_ensure_roundtrip() {
578 1 : let original_lsn = Lsn(0x01_02_03_04_05_06_07_08);
579 1 : let expected_bytes = vec![0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08];
580 1 :
581 1 : let ser_bytes = original_lsn.ser().unwrap();
582 1 : assert_eq!(ser_bytes, expected_bytes);
583 :
584 1 : let des_lsn = Lsn::des(&ser_bytes).unwrap();
585 1 : assert_eq!(des_lsn, original_lsn);
586 1 : }
587 : }
|