qubit_io/stream/
zig_zag_reader.rs1use core::marker::PhantomData;
12use std::io::{
13 Error,
14 ErrorKind,
15 Read,
16 Result,
17 Seek,
18 SeekFrom,
19};
20
21use crate::ReadExt;
22use crate::codec::{
23 DecodePolicy,
24 Leb128DecodeError,
25 NonStrict,
26 Strict,
27 ZigZagCodec,
28};
29
30pub struct ZigZagReader<R, P = NonStrict> {
38 inner: R,
39 buffer: [u8; 19],
40 marker: PhantomData<fn() -> P>,
41}
42
43impl<R, P> ZigZagReader<R, P>
44where
45 P: DecodePolicy,
46{
47 #[must_use]
49 #[inline]
50 pub const fn new(inner: R) -> Self {
51 Self {
52 inner,
53 buffer: [0; 19],
54 marker: PhantomData,
55 }
56 }
57
58 #[must_use]
60 #[inline]
61 pub const fn is_strict(&self) -> bool {
62 P::STRICT
63 }
64
65 #[must_use]
67 #[inline]
68 pub const fn get_ref(&self) -> &R {
69 &self.inner
70 }
71
72 #[must_use]
74 #[inline]
75 pub fn get_mut(&mut self) -> &mut R {
76 &mut self.inner
77 }
78
79 #[must_use]
81 #[inline]
82 pub fn into_inner(self) -> R {
83 self.inner
84 }
85}
86
87macro_rules! impl_read_value {
88 ($policy:ty, $method:ident, $ty:ty, $doc:literal) => {
89 #[doc = $doc]
90 #[inline]
91 pub fn $method(&mut self) -> Result<$ty> {
92 type Codec = ZigZagCodec<$ty, $policy>;
93
94 self.read_leb128::<$ty, { Codec::REQUIRED_MIN_BUFFER_LEN }, _>(|bytes| unsafe {
95 Codec::read_unchecked(bytes, 0)
96 })
97 }
98 };
99}
100
101macro_rules! impl_for_policy {
102 ($policy:ty) => {
103 impl<R> ZigZagReader<R, $policy>
104 where
105 R: Read,
106 {
107 impl_read_value!($policy, read_i8, i8, "Reads a ZigZag `i8`.");
108 impl_read_value!($policy, read_i16, i16, "Reads a ZigZag `i16`.");
109 impl_read_value!($policy, read_i32, i32, "Reads a ZigZag `i32`.");
110 impl_read_value!($policy, read_i64, i64, "Reads a ZigZag `i64`.");
111 impl_read_value!($policy, read_i128, i128, "Reads a ZigZag `i128`.");
112 impl_read_value!($policy, read_isize, isize, "Reads a ZigZag `isize`.");
113 }
114 };
115}
116
117impl<R, P> ZigZagReader<R, P>
118where
119 R: Read,
120 P: DecodePolicy,
121{
122 #[inline]
123 fn read_leb128<T, const N: usize, F>(&mut self, decode: F) -> Result<T>
124 where
125 F: FnOnce(&[u8; 19]) -> std::result::Result<(T, usize), Leb128DecodeError>,
126 {
127 debug_assert!(N <= self.buffer.len(), "ZigZag read length exceeds internal buffer");
128 for index in 0..N {
129 unsafe {
132 self.inner.read_exact_unchecked(&mut self.buffer, index, 1)?;
133 }
134 if read_byte(&self.buffer, index) & 0x80 == 0 {
135 return decode(&self.buffer)
136 .map(|(value, _)| value)
137 .map_err(map_leb128_decode_error);
138 }
139 }
140 decode(&self.buffer)
141 .map(|(value, _)| value)
142 .map_err(map_leb128_decode_error)
143 }
144}
145
146impl_for_policy!(NonStrict);
147impl_for_policy!(Strict);
148
149impl<R, P> Read for ZigZagReader<R, P>
150where
151 R: Read,
152{
153 #[inline]
167 fn read(&mut self, buffer: &mut [u8]) -> Result<usize> {
168 self.inner.read(buffer)
169 }
170}
171
172impl<R, P> Seek for ZigZagReader<R, P>
173where
174 R: Seek,
175{
176 #[inline]
190 fn seek(&mut self, position: SeekFrom) -> Result<u64> {
191 self.inner.seek(position)
192 }
193}
194
195#[inline]
196fn map_leb128_decode_error(error: Leb128DecodeError) -> Error {
197 Error::new(ErrorKind::InvalidData, error)
198}
199
200#[inline(always)]
202fn read_byte(buffer: &[u8; 19], index: usize) -> u8 {
203 debug_assert!(index < buffer.len(), "ZigZag read index exceeds internal buffer");
204 unsafe { *buffer.as_ptr().add(index) }
207}