Skip to main content

qubit_io/ext/
zig_zag_read_ext.rs

1/*******************************************************************************
2 *
3 *    Copyright (c) 2026 Haixing Hu.
4 *
5 *    SPDX-License-Identifier: Apache-2.0
6 *
7 *    Licensed under the Apache License, Version 2.0.
8 *
9 ******************************************************************************/
10
11use std::io::{
12    Read,
13    Result,
14};
15
16use crate::codec::{
17    NonStrict,
18    Strict,
19    ZigZagCodec,
20};
21use crate::util::read_leb128_payload;
22
23macro_rules! read_zig_zag_value {
24    ($reader:expr, $ty:ty, $policy:ty) => {
25        read_leb128_payload::<{ ZigZagCodec::<$ty, $policy>::REQUIRED_MIN_BUFFER_LEN }, _, _, _>($reader, |bytes| {
26            // SAFETY: The local buffer is exactly the codec's minimum buffer length,
27            // or it contains an earlier terminating byte before decoding.
28            unsafe { ZigZagCodec::<$ty, $policy>::read_unchecked(bytes, 0) }
29        })
30    };
31}
32
33/// Extension methods for reading ZigZag + unsigned LEB128 integers.
34///
35/// # Target-width integers
36///
37/// `isize` methods use the current Rust target's pointer width. Prefer
38/// fixed-width integer methods such as [`Self::read_zig_zag_i64`] for
39/// persistent files and cross-platform protocols.
40pub trait ZigZagReadExt: Read {
41    /// Reads a non-strict ZigZag `i8`.
42    #[inline]
43    fn read_zig_zag_i8(&mut self) -> Result<i8> {
44        read_zig_zag_value!(self, i8, NonStrict)
45    }
46
47    /// Reads a strict ZigZag `i8`.
48    #[inline]
49    fn read_zig_zag_i8_strict(&mut self) -> Result<i8> {
50        read_zig_zag_value!(self, i8, Strict)
51    }
52
53    /// Reads a non-strict ZigZag `i16`.
54    #[inline]
55    fn read_zig_zag_i16(&mut self) -> Result<i16> {
56        read_zig_zag_value!(self, i16, NonStrict)
57    }
58
59    /// Reads a strict ZigZag `i16`.
60    #[inline]
61    fn read_zig_zag_i16_strict(&mut self) -> Result<i16> {
62        read_zig_zag_value!(self, i16, Strict)
63    }
64
65    /// Reads a non-strict ZigZag `i32`.
66    #[inline]
67    fn read_zig_zag_i32(&mut self) -> Result<i32> {
68        read_zig_zag_value!(self, i32, NonStrict)
69    }
70
71    /// Reads a strict ZigZag `i32`.
72    #[inline]
73    fn read_zig_zag_i32_strict(&mut self) -> Result<i32> {
74        read_zig_zag_value!(self, i32, Strict)
75    }
76
77    /// Reads a non-strict ZigZag `i64`.
78    #[inline]
79    fn read_zig_zag_i64(&mut self) -> Result<i64> {
80        read_zig_zag_value!(self, i64, NonStrict)
81    }
82
83    /// Reads a strict ZigZag `i64`.
84    #[inline]
85    fn read_zig_zag_i64_strict(&mut self) -> Result<i64> {
86        read_zig_zag_value!(self, i64, Strict)
87    }
88
89    /// Reads a non-strict ZigZag `i128`.
90    #[inline]
91    fn read_zig_zag_i128(&mut self) -> Result<i128> {
92        read_zig_zag_value!(self, i128, NonStrict)
93    }
94
95    /// Reads a strict ZigZag `i128`.
96    #[inline]
97    fn read_zig_zag_i128_strict(&mut self) -> Result<i128> {
98        read_zig_zag_value!(self, i128, Strict)
99    }
100
101    /// Reads a non-strict ZigZag `isize`.
102    #[inline]
103    fn read_zig_zag_isize(&mut self) -> Result<isize> {
104        read_zig_zag_value!(self, isize, NonStrict)
105    }
106
107    /// Reads a strict ZigZag `isize`.
108    #[inline]
109    fn read_zig_zag_isize_strict(&mut self) -> Result<isize> {
110        read_zig_zag_value!(self, isize, Strict)
111    }
112}
113
114impl<R> ZigZagReadExt for R where R: Read + ?Sized {}