rust_leb128/
io.rs

1#![cfg(feature = "std")]
2#![cfg_attr(docsrs, doc(cfg(feature = "std")))]
3
4use std::io::{Bytes, Error, Read, Result, Write};
5
6use super::{Overflow, Varint};
7
8macro_rules! write_impl {
9    ($type:ty, $name:ident) => {
10        #[doc = "Writes a LEB128-encoded `"]
11        #[doc = stringify!($type)]
12        #[doc = "` and returns the number of bytes written."]
13        fn $name(&mut self, x: $type) -> Result<usize> {
14            self.write_int(x)
15        }
16    };
17}
18
19/// Extends [`Write`] with methods for reading LEB128-encoded
20/// integers.
21pub trait WriteVarint: Write {
22    /// Writes a LEB128-encoded integer and returns the number of
23    /// bytes written.
24    fn write_int<T: Varint>(&mut self, x: T) -> Result<usize> {
25        let mut buf = T::Buf::default();
26        let encoded = x.write(&mut buf);
27        self.write_all(encoded)?;
28        Ok(encoded.len())
29    }
30
31    write_impl!(u8, write_u8);
32    write_impl!(u16, write_u16);
33    write_impl!(u32, write_u32);
34    write_impl!(u64, write_u64);
35    write_impl!(u128, write_u128);
36    write_impl!(usize, write_usize);
37
38    write_impl!(i8, write_i8);
39    write_impl!(i16, write_i16);
40    write_impl!(i32, write_i32);
41    write_impl!(i64, write_i64);
42    write_impl!(i128, write_i128);
43    write_impl!(isize, write_isize);
44}
45
46macro_rules! read_impl {
47    ($type:ty, $name:ident) => {
48        #[doc = "Reads a LEB128-encoded `"]
49        #[doc = stringify!($type)]
50        #[doc = "`."]
51        fn $name(&mut self) -> Result<$type> {
52            self.read_int()
53        }
54    };
55}
56
57impl<W: Write + ?Sized> WriteVarint for W {}
58
59/// Extends [`Read`] with methods for reading LEB128-encoded
60/// integers.
61pub trait ReadVarint: Read {
62    /// Reads a LEB128-encoded integer.
63    fn read_int<T: Varint>(&mut self) -> Result<T> {
64        let mut iter = Iter::new(self.bytes());
65        let (v, _) = T::read_iter(&mut iter).map_err(Error::other)?;
66        if let Some(err) = iter.err {
67            Err(err)
68        } else {
69            Ok(v)
70        }
71    }
72
73    read_impl!(u8, read_u8);
74    read_impl!(u16, read_u16);
75    read_impl!(u32, read_u32);
76    read_impl!(u64, read_u64);
77    read_impl!(u128, read_u128);
78    read_impl!(usize, read_usize);
79
80    read_impl!(i8, read_i8);
81    read_impl!(i16, read_i16);
82    read_impl!(i32, read_i32);
83    read_impl!(i64, read_i64);
84    read_impl!(i128, read_i128);
85    read_impl!(isize, read_isize);
86}
87
88impl<R: Read + ?Sized> ReadVarint for R {}
89
90impl From<Overflow> for Error {
91    fn from(err: Overflow) -> Self {
92        Error::other(err)
93    }
94}
95
96struct Iter<R> {
97    inner: Bytes<R>,
98    err: Option<Error>,
99}
100
101impl<R> Iter<R> {
102    const fn new(inner: Bytes<R>) -> Self {
103        Self { inner, err: None }
104    }
105}
106
107impl<R: Read> Iterator for Iter<R> {
108    type Item = u8;
109
110    fn next(&mut self) -> Option<Self::Item> {
111        match self.err {
112            Some(_) => None,
113            None => match self.inner.next()? {
114                Ok(v) => Some(v),
115                Err(err) => {
116                    self.err = Some(err);
117                    None
118                }
119            },
120        }
121    }
122}
123
124#[cfg(test)]
125mod tests {
126    use super::*;
127
128    const TESTS: &[i128] = &[
129        -1 << 127,
130        (-1 << 127) + 1,
131        -1 << 63,
132        (-1 << 63) + 1,
133        -1,
134        0,
135        1,
136        2,
137        10,
138        20,
139        63,
140        64,
141        65,
142        127,
143        128,
144        129,
145        255,
146        256,
147        257,
148        (1 << 63) - 1,
149        i128::MAX,
150    ];
151
152    macro_rules! test_impl {
153        ($name:ident, $type:ty, $write:ident, $read:ident) => {
154            #[test]
155            fn $name() {
156                fn test<F>(buf: &mut [u8], want: $type, name: &str, mut f: F)
157                where
158                    F: FnMut(&mut [u8], $type) -> Result<usize>,
159                {
160                    buf.fill(0xff);
161
162                    let got = f(buf, want).unwrap_or_else(|_| {
163                        panic!("`{name}({want}{})` should not fail", stringify!($type))
164                    });
165                    assert_eq!(
166                        got,
167                        want.encoded_len(),
168                        "`{name}({want})` != encoded_len({want})"
169                    );
170
171                    let mut tmp = (&*buf);
172                    let got = tmp
173                        .$read()
174                        .unwrap_or_else(|_| panic!("`{}` should not fail", stringify!($read)));
175                    assert_eq!(got, want, "`{}`", stringify!($read));
176
177                    let got = (&*buf).read_int::<$type>().unwrap_or_else(|_| {
178                        panic!(
179                            "`read_int::<{}>({want})` should not fail",
180                            stringify!($type)
181                        )
182                    });
183                    assert_eq!(got, want, "`read_int::<{}>`", stringify!($type));
184                }
185
186                let mut buf = vec![0x80u8; 100];
187                for &x in TESTS {
188                    let Ok(want) = x.try_into() else {
189                        continue;
190                    };
191                    test(&mut buf, want, stringify!($write), |mut buf, want| {
192                        buf.$write(want)
193                    });
194                    test(&mut buf, want, stringify!("write_int"), |mut buf, want| {
195                        buf.write_int(want)
196                    });
197                }
198            }
199        };
200    }
201    test_impl!(test_io_u8, u8, write_u8, read_u8);
202    test_impl!(test_io_u16, u16, write_u16, read_u16);
203    test_impl!(test_io_u32, u32, write_u32, read_u32);
204    test_impl!(test_io_u64, u64, write_u64, read_u64);
205    test_impl!(test_io_u128, u128, write_u128, read_u128);
206    test_impl!(test_io_usize, usize, write_usize, read_usize);
207
208    test_impl!(test_io_i8, i8, write_i8, read_i8);
209    test_impl!(test_io_i16, i16, write_i16, read_i16);
210    test_impl!(test_io_i32, i32, write_i32, read_i32);
211    test_impl!(test_io_i64, i64, write_i64, read_i64);
212    test_impl!(test_io_i128, i128, write_i128, read_i128);
213    test_impl!(test_io_isize, isize, write_isize, read_isize);
214}