xref: /aosp_15_r20/external/pigweed/pw_varint/rust/pw_varint.rs (revision 61c4878ac05f98d0ceed94b57d316916de578985)
1*61c4878aSAndroid Build Coastguard Worker // Copyright 2023 The Pigweed Authors
2*61c4878aSAndroid Build Coastguard Worker //
3*61c4878aSAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License"); you may not
4*61c4878aSAndroid Build Coastguard Worker // use this file except in compliance with the License. You may obtain a copy of
5*61c4878aSAndroid Build Coastguard Worker // the License at
6*61c4878aSAndroid Build Coastguard Worker //
7*61c4878aSAndroid Build Coastguard Worker //     https://www.apache.org/licenses/LICENSE-2.0
8*61c4878aSAndroid Build Coastguard Worker //
9*61c4878aSAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
10*61c4878aSAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11*61c4878aSAndroid Build Coastguard Worker // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12*61c4878aSAndroid Build Coastguard Worker // License for the specific language governing permissions and limitations under
13*61c4878aSAndroid Build Coastguard Worker // the License.
14*61c4878aSAndroid Build Coastguard Worker 
15*61c4878aSAndroid Build Coastguard Worker //! # pw_varint
16*61c4878aSAndroid Build Coastguard Worker //!
17*61c4878aSAndroid Build Coastguard Worker //! `pw_varint` provides support for encoding and decoding variable length
18*61c4878aSAndroid Build Coastguard Worker //! integers.  Small values require less memory than they do with fixed
19*61c4878aSAndroid Build Coastguard Worker //! encoding.  Signed integers are first zig-zag encoded to allow small
20*61c4878aSAndroid Build Coastguard Worker //! negative numbers to realize the memory savings.  For more information see
21*61c4878aSAndroid Build Coastguard Worker //! [Pigweed's pw_varint documentation](https://pigweed.dev/pw_varint).
22*61c4878aSAndroid Build Coastguard Worker //!
23*61c4878aSAndroid Build Coastguard Worker //! The encoding format used is compatible with
24*61c4878aSAndroid Build Coastguard Worker //! [Protocol Buffers](https://developers.google.com/protocol-buffers/docs/encoding#varints).
25*61c4878aSAndroid Build Coastguard Worker //!
26*61c4878aSAndroid Build Coastguard Worker //! Encoding and decoding is provided through the [VarintEncode] and
27*61c4878aSAndroid Build Coastguard Worker //! [VarintDecode] traits.
28*61c4878aSAndroid Build Coastguard Worker //!
29*61c4878aSAndroid Build Coastguard Worker //! # Example
30*61c4878aSAndroid Build Coastguard Worker //!
31*61c4878aSAndroid Build Coastguard Worker //! ```
32*61c4878aSAndroid Build Coastguard Worker //! use pw_varint::{VarintEncode, VarintDecode};
33*61c4878aSAndroid Build Coastguard Worker //!
34*61c4878aSAndroid Build Coastguard Worker //! let mut buffer = [0u8; 64];
35*61c4878aSAndroid Build Coastguard Worker //!
36*61c4878aSAndroid Build Coastguard Worker //! let encoded_len = (-1i64).varint_encode(&mut buffer).unwrap();
37*61c4878aSAndroid Build Coastguard Worker //!
38*61c4878aSAndroid Build Coastguard Worker //! let (decoded_len, val) = i64::varint_decode(&buffer ).unwrap();
39*61c4878aSAndroid Build Coastguard Worker //! ```
40*61c4878aSAndroid Build Coastguard Worker 
41*61c4878aSAndroid Build Coastguard Worker #![cfg_attr(not(feature = "std"), no_std)]
42*61c4878aSAndroid Build Coastguard Worker 
43*61c4878aSAndroid Build Coastguard Worker use core::num::Wrapping;
44*61c4878aSAndroid Build Coastguard Worker 
45*61c4878aSAndroid Build Coastguard Worker use pw_status::{Error, Result};
46*61c4878aSAndroid Build Coastguard Worker 
47*61c4878aSAndroid Build Coastguard Worker /// A trait for objects than can be decoded from a varint.
48*61c4878aSAndroid Build Coastguard Worker ///
49*61c4878aSAndroid Build Coastguard Worker /// `pw_varint` provides implementations for [i16], [u16], [i32], [u32],
50*61c4878aSAndroid Build Coastguard Worker /// [i64], and [u64].
51*61c4878aSAndroid Build Coastguard Worker pub trait VarintDecode: Sized {
52*61c4878aSAndroid Build Coastguard Worker     /// Decode a type from a varint encoded series of bytes.
53*61c4878aSAndroid Build Coastguard Worker     ///
54*61c4878aSAndroid Build Coastguard Worker     /// Signed values will be implicitly zig-zag decoded.
varint_decode(data: &[u8]) -> Result<(usize, Self)>55*61c4878aSAndroid Build Coastguard Worker     fn varint_decode(data: &[u8]) -> Result<(usize, Self)>;
56*61c4878aSAndroid Build Coastguard Worker }
57*61c4878aSAndroid Build Coastguard Worker 
58*61c4878aSAndroid Build Coastguard Worker /// A trait for objects than can be encoded into a varint.
59*61c4878aSAndroid Build Coastguard Worker ///
60*61c4878aSAndroid Build Coastguard Worker /// `pw_varint` provides implementations for [i16], [u16], [i32], [u32],
61*61c4878aSAndroid Build Coastguard Worker /// [i64], and [u64].
62*61c4878aSAndroid Build Coastguard Worker pub trait VarintEncode: Sized {
63*61c4878aSAndroid Build Coastguard Worker     /// Encode a type into a varint encoded series of bytes.
64*61c4878aSAndroid Build Coastguard Worker     ///
65*61c4878aSAndroid Build Coastguard Worker     /// Signed values will be implicitly zig-zag encoded.
varint_encode(self, data: &mut [u8]) -> Result<usize>66*61c4878aSAndroid Build Coastguard Worker     fn varint_encode(self, data: &mut [u8]) -> Result<usize>;
67*61c4878aSAndroid Build Coastguard Worker }
68*61c4878aSAndroid Build Coastguard Worker 
69*61c4878aSAndroid Build Coastguard Worker macro_rules! unsigned_varint_impl {
70*61c4878aSAndroid Build Coastguard Worker     ($t:ty) => {
71*61c4878aSAndroid Build Coastguard Worker         impl VarintDecode for $t {
72*61c4878aSAndroid Build Coastguard Worker             fn varint_decode(data: &[u8]) -> Result<(usize, Self)> {
73*61c4878aSAndroid Build Coastguard Worker                 let (data, val) = decode_u64(data)?;
74*61c4878aSAndroid Build Coastguard Worker                 Ok((data, val as Self))
75*61c4878aSAndroid Build Coastguard Worker             }
76*61c4878aSAndroid Build Coastguard Worker         }
77*61c4878aSAndroid Build Coastguard Worker 
78*61c4878aSAndroid Build Coastguard Worker         impl VarintEncode for $t {
79*61c4878aSAndroid Build Coastguard Worker             fn varint_encode(self, data: &mut [u8]) -> Result<usize> {
80*61c4878aSAndroid Build Coastguard Worker                 encode_u64(data, self as u64)
81*61c4878aSAndroid Build Coastguard Worker             }
82*61c4878aSAndroid Build Coastguard Worker         }
83*61c4878aSAndroid Build Coastguard Worker     };
84*61c4878aSAndroid Build Coastguard Worker }
85*61c4878aSAndroid Build Coastguard Worker 
86*61c4878aSAndroid Build Coastguard Worker macro_rules! signed_varint_impl {
87*61c4878aSAndroid Build Coastguard Worker     ($t:ty) => {
88*61c4878aSAndroid Build Coastguard Worker         impl VarintDecode for $t {
89*61c4878aSAndroid Build Coastguard Worker             fn varint_decode(data: &[u8]) -> Result<(usize, Self)> {
90*61c4878aSAndroid Build Coastguard Worker                 let (data, val) = decode_u64(data)?;
91*61c4878aSAndroid Build Coastguard Worker                 Ok((data, zig_zag_decode(val) as Self))
92*61c4878aSAndroid Build Coastguard Worker             }
93*61c4878aSAndroid Build Coastguard Worker         }
94*61c4878aSAndroid Build Coastguard Worker 
95*61c4878aSAndroid Build Coastguard Worker         impl VarintEncode for $t {
96*61c4878aSAndroid Build Coastguard Worker             fn varint_encode(self, data: &mut [u8]) -> Result<usize> {
97*61c4878aSAndroid Build Coastguard Worker                 encode_u64(data, zig_zag_encode(self as i64))
98*61c4878aSAndroid Build Coastguard Worker             }
99*61c4878aSAndroid Build Coastguard Worker         }
100*61c4878aSAndroid Build Coastguard Worker     };
101*61c4878aSAndroid Build Coastguard Worker }
102*61c4878aSAndroid Build Coastguard Worker 
103*61c4878aSAndroid Build Coastguard Worker unsigned_varint_impl!(u8);
104*61c4878aSAndroid Build Coastguard Worker unsigned_varint_impl!(u16);
105*61c4878aSAndroid Build Coastguard Worker unsigned_varint_impl!(u32);
106*61c4878aSAndroid Build Coastguard Worker unsigned_varint_impl!(u64);
107*61c4878aSAndroid Build Coastguard Worker 
108*61c4878aSAndroid Build Coastguard Worker signed_varint_impl!(i8);
109*61c4878aSAndroid Build Coastguard Worker signed_varint_impl!(i16);
110*61c4878aSAndroid Build Coastguard Worker signed_varint_impl!(i32);
111*61c4878aSAndroid Build Coastguard Worker signed_varint_impl!(i64);
112*61c4878aSAndroid Build Coastguard Worker 
decode_u64(data: &[u8]) -> Result<(usize, u64)>113*61c4878aSAndroid Build Coastguard Worker fn decode_u64(data: &[u8]) -> Result<(usize, u64)> {
114*61c4878aSAndroid Build Coastguard Worker     let mut value: u64 = 0;
115*61c4878aSAndroid Build Coastguard Worker     for (i, d) in data.iter().enumerate() {
116*61c4878aSAndroid Build Coastguard Worker         value |= (*d as u64 & 0x7f) << (i * 7);
117*61c4878aSAndroid Build Coastguard Worker 
118*61c4878aSAndroid Build Coastguard Worker         if (*d & 0x80) == 0 {
119*61c4878aSAndroid Build Coastguard Worker             return Ok((i + 1, value));
120*61c4878aSAndroid Build Coastguard Worker         }
121*61c4878aSAndroid Build Coastguard Worker     }
122*61c4878aSAndroid Build Coastguard Worker     Err(Error::OutOfRange)
123*61c4878aSAndroid Build Coastguard Worker }
124*61c4878aSAndroid Build Coastguard Worker 
encode_u64(data: &mut [u8], value: u64) -> Result<usize>125*61c4878aSAndroid Build Coastguard Worker fn encode_u64(data: &mut [u8], value: u64) -> Result<usize> {
126*61c4878aSAndroid Build Coastguard Worker     let mut value = value;
127*61c4878aSAndroid Build Coastguard Worker     for (i, d) in data.iter_mut().enumerate() {
128*61c4878aSAndroid Build Coastguard Worker         let mut byte: u8 = (value & 0x7f) as u8;
129*61c4878aSAndroid Build Coastguard Worker         value >>= 7;
130*61c4878aSAndroid Build Coastguard Worker         if value > 0 {
131*61c4878aSAndroid Build Coastguard Worker             byte |= 0x80;
132*61c4878aSAndroid Build Coastguard Worker         }
133*61c4878aSAndroid Build Coastguard Worker         *d = byte;
134*61c4878aSAndroid Build Coastguard Worker         if value == 0 {
135*61c4878aSAndroid Build Coastguard Worker             return Ok(i + 1);
136*61c4878aSAndroid Build Coastguard Worker         }
137*61c4878aSAndroid Build Coastguard Worker     }
138*61c4878aSAndroid Build Coastguard Worker     Err(Error::OutOfRange)
139*61c4878aSAndroid Build Coastguard Worker }
140*61c4878aSAndroid Build Coastguard Worker 
141*61c4878aSAndroid Build Coastguard Worker // ZigZag encodes a signed integer. This maps small negative numbers to small,
142*61c4878aSAndroid Build Coastguard Worker // unsigned positive numbers, which improves their density for LEB128 encoding.
143*61c4878aSAndroid Build Coastguard Worker //
144*61c4878aSAndroid Build Coastguard Worker // ZigZag encoding works by moving the sign bit from the most-significant bit to
145*61c4878aSAndroid Build Coastguard Worker // the least-significant bit. For the signed k-bit integer n, the formula is
146*61c4878aSAndroid Build Coastguard Worker //
147*61c4878aSAndroid Build Coastguard Worker //   (n << 1) ^ (n >> (k - 1))
148*61c4878aSAndroid Build Coastguard Worker //
149*61c4878aSAndroid Build Coastguard Worker // See the following for a description of ZigZag encoding:
150*61c4878aSAndroid Build Coastguard Worker //   https://protobuf.dev/programming-guides/encoding/#signed-ints
zig_zag_encode(value: i64) -> u64151*61c4878aSAndroid Build Coastguard Worker fn zig_zag_encode(value: i64) -> u64 {
152*61c4878aSAndroid Build Coastguard Worker     ((value as u64) << 1) ^ ((value >> (i64::BITS - 1)) as u64)
153*61c4878aSAndroid Build Coastguard Worker }
154*61c4878aSAndroid Build Coastguard Worker 
zig_zag_decode(value: u64) -> i64155*61c4878aSAndroid Build Coastguard Worker fn zig_zag_decode(value: u64) -> i64 {
156*61c4878aSAndroid Build Coastguard Worker     let value = Wrapping(value);
157*61c4878aSAndroid Build Coastguard Worker     ((value >> 1) ^ (!(value & Wrapping(1)) + Wrapping(1))).0 as i64
158*61c4878aSAndroid Build Coastguard Worker }
159*61c4878aSAndroid Build Coastguard Worker 
160*61c4878aSAndroid Build Coastguard Worker #[cfg(test)]
161*61c4878aSAndroid Build Coastguard Worker mod test {
162*61c4878aSAndroid Build Coastguard Worker     use super::*;
163*61c4878aSAndroid Build Coastguard Worker 
success_cases_u8<T>() -> Vec<(Vec<u8>, T)> where T: From<u8>,164*61c4878aSAndroid Build Coastguard Worker     fn success_cases_u8<T>() -> Vec<(Vec<u8>, T)>
165*61c4878aSAndroid Build Coastguard Worker     where
166*61c4878aSAndroid Build Coastguard Worker         T: From<u8>,
167*61c4878aSAndroid Build Coastguard Worker     {
168*61c4878aSAndroid Build Coastguard Worker         vec![
169*61c4878aSAndroid Build Coastguard Worker             // From varint_test.cc EncodeSizeUnsigned32_SmallSingleByte.
170*61c4878aSAndroid Build Coastguard Worker             (vec![0x00], 0x00.into()),
171*61c4878aSAndroid Build Coastguard Worker             (vec![0x01], 0x01.into()),
172*61c4878aSAndroid Build Coastguard Worker             (vec![0x02], 0x02.into()),
173*61c4878aSAndroid Build Coastguard Worker             // From varint_test.cc EncodeSizeUnsigned32_LargeSingleByte.
174*61c4878aSAndroid Build Coastguard Worker             (vec![0x3f], 0x3f.into()),
175*61c4878aSAndroid Build Coastguard Worker             (vec![0x40], 0x40.into()),
176*61c4878aSAndroid Build Coastguard Worker             (vec![0x7e], 0x7e.into()),
177*61c4878aSAndroid Build Coastguard Worker             (vec![0x7f], 0x7f.into()),
178*61c4878aSAndroid Build Coastguard Worker             // From varint_test.cc EncodeSizeUnsigned32_MultiByte.
179*61c4878aSAndroid Build Coastguard Worker             (vec![0x80, 0x01], 128.into()),
180*61c4878aSAndroid Build Coastguard Worker             (vec![0x81, 0x01], 129.into()),
181*61c4878aSAndroid Build Coastguard Worker             // From https://protobuf.dev/programming-guides/encoding/.
182*61c4878aSAndroid Build Coastguard Worker             (vec![0x96, 0x01], 150.into()),
183*61c4878aSAndroid Build Coastguard Worker         ]
184*61c4878aSAndroid Build Coastguard Worker     }
185*61c4878aSAndroid Build Coastguard Worker 
success_cases_i8<T>() -> Vec<(Vec<u8>, T)> where T: From<i8>,186*61c4878aSAndroid Build Coastguard Worker     fn success_cases_i8<T>() -> Vec<(Vec<u8>, T)>
187*61c4878aSAndroid Build Coastguard Worker     where
188*61c4878aSAndroid Build Coastguard Worker         T: From<i8>,
189*61c4878aSAndroid Build Coastguard Worker     {
190*61c4878aSAndroid Build Coastguard Worker         vec![
191*61c4878aSAndroid Build Coastguard Worker             // From varint_test.cc EncodeSizeSigned32_SmallSingleByte.
192*61c4878aSAndroid Build Coastguard Worker             (vec![0x00], 0i8.into()),
193*61c4878aSAndroid Build Coastguard Worker             (vec![0x01], (-1i8).into()),
194*61c4878aSAndroid Build Coastguard Worker             (vec![0x02], 1i8.into()),
195*61c4878aSAndroid Build Coastguard Worker             (vec![0x03], (-2i8).into()),
196*61c4878aSAndroid Build Coastguard Worker             (vec![0x04], 2i8.into()),
197*61c4878aSAndroid Build Coastguard Worker             // From varint_test.cc EncodeSizeSigned32_LargeSingleByte.
198*61c4878aSAndroid Build Coastguard Worker             (vec![125], (-63i8).into()),
199*61c4878aSAndroid Build Coastguard Worker             (vec![126], (63i8).into()),
200*61c4878aSAndroid Build Coastguard Worker             (vec![127], (-64i8).into()),
201*61c4878aSAndroid Build Coastguard Worker             // From varint_test.cc EncodeSizeSigned32_MultiByte.
202*61c4878aSAndroid Build Coastguard Worker             (vec![0x80, 0x1], 64i8.into()),
203*61c4878aSAndroid Build Coastguard Worker             (vec![0x81, 0x1], (-65i8).into()),
204*61c4878aSAndroid Build Coastguard Worker             (vec![0x82, 0x1], 65i8.into()),
205*61c4878aSAndroid Build Coastguard Worker         ]
206*61c4878aSAndroid Build Coastguard Worker     }
207*61c4878aSAndroid Build Coastguard Worker 
success_cases_u32<T>() -> Vec<(Vec<u8>, T)> where T: From<u32>,208*61c4878aSAndroid Build Coastguard Worker     fn success_cases_u32<T>() -> Vec<(Vec<u8>, T)>
209*61c4878aSAndroid Build Coastguard Worker     where
210*61c4878aSAndroid Build Coastguard Worker         T: From<u32>,
211*61c4878aSAndroid Build Coastguard Worker     {
212*61c4878aSAndroid Build Coastguard Worker         vec![
213*61c4878aSAndroid Build Coastguard Worker             // From varint_test.cc EncodeSizeUnsigned32_MultiByte.
214*61c4878aSAndroid Build Coastguard Worker             (vec![0xfe, 0xff, 0xff, 0xff, 0x0f], 0xffff_fffe.into()),
215*61c4878aSAndroid Build Coastguard Worker             (vec![0xff, 0xff, 0xff, 0xff, 0x0f], 0xffff_ffff.into()),
216*61c4878aSAndroid Build Coastguard Worker         ]
217*61c4878aSAndroid Build Coastguard Worker     }
218*61c4878aSAndroid Build Coastguard Worker 
success_cases_i32<T>() -> Vec<(Vec<u8>, T)> where T: From<i32>,219*61c4878aSAndroid Build Coastguard Worker     fn success_cases_i32<T>() -> Vec<(Vec<u8>, T)>
220*61c4878aSAndroid Build Coastguard Worker     where
221*61c4878aSAndroid Build Coastguard Worker         T: From<i32>,
222*61c4878aSAndroid Build Coastguard Worker     {
223*61c4878aSAndroid Build Coastguard Worker         vec![
224*61c4878aSAndroid Build Coastguard Worker             // From varint_test.cc EncodeSizeSigned32_MultiByte.
225*61c4878aSAndroid Build Coastguard Worker             (vec![0xff, 0xff, 0xff, 0xff, 0x0f], i32::MIN.into()),
226*61c4878aSAndroid Build Coastguard Worker             (vec![0xfe, 0xff, 0xff, 0xff, 0x0f], i32::MAX.into()),
227*61c4878aSAndroid Build Coastguard Worker         ]
228*61c4878aSAndroid Build Coastguard Worker     }
229*61c4878aSAndroid Build Coastguard Worker 
230*61c4878aSAndroid Build Coastguard Worker     #[test]
decode_test_u16()231*61c4878aSAndroid Build Coastguard Worker     fn decode_test_u16() {
232*61c4878aSAndroid Build Coastguard Worker         for case in success_cases_u8::<u16>() {
233*61c4878aSAndroid Build Coastguard Worker             assert_eq!(u16::varint_decode(&case.0), Ok((case.0.len(), case.1)));
234*61c4878aSAndroid Build Coastguard Worker         }
235*61c4878aSAndroid Build Coastguard Worker 
236*61c4878aSAndroid Build Coastguard Worker         assert_eq!(u16::varint_decode(&[0x96]), Err(Error::OutOfRange));
237*61c4878aSAndroid Build Coastguard Worker     }
238*61c4878aSAndroid Build Coastguard Worker 
239*61c4878aSAndroid Build Coastguard Worker     #[test]
decode_test_i16()240*61c4878aSAndroid Build Coastguard Worker     fn decode_test_i16() {
241*61c4878aSAndroid Build Coastguard Worker         for case in success_cases_i8::<i16>() {
242*61c4878aSAndroid Build Coastguard Worker             assert_eq!(i16::varint_decode(&case.0), Ok((case.0.len(), case.1)));
243*61c4878aSAndroid Build Coastguard Worker         }
244*61c4878aSAndroid Build Coastguard Worker 
245*61c4878aSAndroid Build Coastguard Worker         assert_eq!(i16::varint_decode(&[0x96]), Err(Error::OutOfRange));
246*61c4878aSAndroid Build Coastguard Worker     }
247*61c4878aSAndroid Build Coastguard Worker 
248*61c4878aSAndroid Build Coastguard Worker     #[test]
decode_test_u32()249*61c4878aSAndroid Build Coastguard Worker     fn decode_test_u32() {
250*61c4878aSAndroid Build Coastguard Worker         for case in success_cases_u8::<u32>()
251*61c4878aSAndroid Build Coastguard Worker             .into_iter()
252*61c4878aSAndroid Build Coastguard Worker             .chain(success_cases_u32::<u32>())
253*61c4878aSAndroid Build Coastguard Worker         {
254*61c4878aSAndroid Build Coastguard Worker             assert_eq!(u32::varint_decode(&case.0), Ok((case.0.len(), case.1)));
255*61c4878aSAndroid Build Coastguard Worker         }
256*61c4878aSAndroid Build Coastguard Worker 
257*61c4878aSAndroid Build Coastguard Worker         assert_eq!(u32::varint_decode(&[0x96]), Err(Error::OutOfRange));
258*61c4878aSAndroid Build Coastguard Worker     }
259*61c4878aSAndroid Build Coastguard Worker 
260*61c4878aSAndroid Build Coastguard Worker     #[test]
decode_test_i32()261*61c4878aSAndroid Build Coastguard Worker     fn decode_test_i32() {
262*61c4878aSAndroid Build Coastguard Worker         for case in success_cases_i8::<i32>()
263*61c4878aSAndroid Build Coastguard Worker             .into_iter()
264*61c4878aSAndroid Build Coastguard Worker             .chain(success_cases_i32::<i32>())
265*61c4878aSAndroid Build Coastguard Worker         {
266*61c4878aSAndroid Build Coastguard Worker             assert_eq!(i32::varint_decode(&case.0), Ok((case.0.len(), case.1)));
267*61c4878aSAndroid Build Coastguard Worker         }
268*61c4878aSAndroid Build Coastguard Worker 
269*61c4878aSAndroid Build Coastguard Worker         assert_eq!(i32::varint_decode(&[0x96]), Err(Error::OutOfRange));
270*61c4878aSAndroid Build Coastguard Worker     }
271*61c4878aSAndroid Build Coastguard Worker 
272*61c4878aSAndroid Build Coastguard Worker     #[test]
decode_test_u64()273*61c4878aSAndroid Build Coastguard Worker     fn decode_test_u64() {
274*61c4878aSAndroid Build Coastguard Worker         for case in success_cases_u8::<u64>()
275*61c4878aSAndroid Build Coastguard Worker             .into_iter()
276*61c4878aSAndroid Build Coastguard Worker             .chain(success_cases_u32::<u64>())
277*61c4878aSAndroid Build Coastguard Worker         {
278*61c4878aSAndroid Build Coastguard Worker             assert_eq!(u64::varint_decode(&case.0), Ok((case.0.len(), case.1)));
279*61c4878aSAndroid Build Coastguard Worker         }
280*61c4878aSAndroid Build Coastguard Worker 
281*61c4878aSAndroid Build Coastguard Worker         assert_eq!(u64::varint_decode(&[0x96]), Err(Error::OutOfRange));
282*61c4878aSAndroid Build Coastguard Worker     }
283*61c4878aSAndroid Build Coastguard Worker 
284*61c4878aSAndroid Build Coastguard Worker     #[test]
decode_test_i64()285*61c4878aSAndroid Build Coastguard Worker     fn decode_test_i64() {
286*61c4878aSAndroid Build Coastguard Worker         for case in success_cases_i8::<i64>()
287*61c4878aSAndroid Build Coastguard Worker             .into_iter()
288*61c4878aSAndroid Build Coastguard Worker             .chain(success_cases_i32::<i64>())
289*61c4878aSAndroid Build Coastguard Worker         {
290*61c4878aSAndroid Build Coastguard Worker             assert_eq!(i64::varint_decode(&case.0), Ok((case.0.len(), case.1)));
291*61c4878aSAndroid Build Coastguard Worker         }
292*61c4878aSAndroid Build Coastguard Worker 
293*61c4878aSAndroid Build Coastguard Worker         assert_eq!(i64::varint_decode(&[0x96]), Err(Error::OutOfRange));
294*61c4878aSAndroid Build Coastguard Worker     }
295*61c4878aSAndroid Build Coastguard Worker 
296*61c4878aSAndroid Build Coastguard Worker     #[test]
encode_test_u16()297*61c4878aSAndroid Build Coastguard Worker     fn encode_test_u16() {
298*61c4878aSAndroid Build Coastguard Worker         for case in success_cases_u8::<u16>() {
299*61c4878aSAndroid Build Coastguard Worker             let mut buffer = [0u8; 64];
300*61c4878aSAndroid Build Coastguard Worker             let len = case.1.varint_encode(&mut buffer).unwrap();
301*61c4878aSAndroid Build Coastguard Worker             assert_eq!(len, case.0.len());
302*61c4878aSAndroid Build Coastguard Worker             assert_eq!(&buffer[0..len], case.0);
303*61c4878aSAndroid Build Coastguard Worker         }
304*61c4878aSAndroid Build Coastguard Worker     }
305*61c4878aSAndroid Build Coastguard Worker 
306*61c4878aSAndroid Build Coastguard Worker     #[test]
encode_test_i16()307*61c4878aSAndroid Build Coastguard Worker     fn encode_test_i16() {
308*61c4878aSAndroid Build Coastguard Worker         for case in success_cases_i8::<i16>() {
309*61c4878aSAndroid Build Coastguard Worker             let mut buffer = [0u8; 64];
310*61c4878aSAndroid Build Coastguard Worker             let len = case.1.varint_encode(&mut buffer).unwrap();
311*61c4878aSAndroid Build Coastguard Worker             assert_eq!(len, case.0.len());
312*61c4878aSAndroid Build Coastguard Worker             assert_eq!(&buffer[0..len], case.0);
313*61c4878aSAndroid Build Coastguard Worker         }
314*61c4878aSAndroid Build Coastguard Worker     }
315*61c4878aSAndroid Build Coastguard Worker 
316*61c4878aSAndroid Build Coastguard Worker     #[test]
encode_test_u32()317*61c4878aSAndroid Build Coastguard Worker     fn encode_test_u32() {
318*61c4878aSAndroid Build Coastguard Worker         for case in success_cases_u8::<u32>()
319*61c4878aSAndroid Build Coastguard Worker             .into_iter()
320*61c4878aSAndroid Build Coastguard Worker             .chain(success_cases_u32::<u32>())
321*61c4878aSAndroid Build Coastguard Worker         {
322*61c4878aSAndroid Build Coastguard Worker             let mut buffer = [0u8; 64];
323*61c4878aSAndroid Build Coastguard Worker             let len = case.1.varint_encode(&mut buffer).unwrap();
324*61c4878aSAndroid Build Coastguard Worker             assert_eq!(len, case.0.len());
325*61c4878aSAndroid Build Coastguard Worker             assert_eq!(&buffer[0..len], case.0);
326*61c4878aSAndroid Build Coastguard Worker         }
327*61c4878aSAndroid Build Coastguard Worker     }
328*61c4878aSAndroid Build Coastguard Worker 
329*61c4878aSAndroid Build Coastguard Worker     #[test]
encode_test_i32()330*61c4878aSAndroid Build Coastguard Worker     fn encode_test_i32() {
331*61c4878aSAndroid Build Coastguard Worker         for case in success_cases_i8::<i32>()
332*61c4878aSAndroid Build Coastguard Worker             .into_iter()
333*61c4878aSAndroid Build Coastguard Worker             .chain(success_cases_i32::<i32>())
334*61c4878aSAndroid Build Coastguard Worker         {
335*61c4878aSAndroid Build Coastguard Worker             let mut buffer = [0u8; 64];
336*61c4878aSAndroid Build Coastguard Worker             let len = case.1.varint_encode(&mut buffer).unwrap();
337*61c4878aSAndroid Build Coastguard Worker             assert_eq!(len, len);
338*61c4878aSAndroid Build Coastguard Worker             assert_eq!(&buffer[0..len], case.0);
339*61c4878aSAndroid Build Coastguard Worker         }
340*61c4878aSAndroid Build Coastguard Worker     }
341*61c4878aSAndroid Build Coastguard Worker 
342*61c4878aSAndroid Build Coastguard Worker     #[test]
encode_test_u64()343*61c4878aSAndroid Build Coastguard Worker     fn encode_test_u64() {
344*61c4878aSAndroid Build Coastguard Worker         for case in success_cases_u8::<u64>()
345*61c4878aSAndroid Build Coastguard Worker             .into_iter()
346*61c4878aSAndroid Build Coastguard Worker             .chain(success_cases_u32::<u64>())
347*61c4878aSAndroid Build Coastguard Worker         {
348*61c4878aSAndroid Build Coastguard Worker             let mut buffer = [0u8; 64];
349*61c4878aSAndroid Build Coastguard Worker             let len = case.1.varint_encode(&mut buffer).unwrap();
350*61c4878aSAndroid Build Coastguard Worker             assert_eq!(len, case.0.len());
351*61c4878aSAndroid Build Coastguard Worker             assert_eq!(&buffer[0..len], case.0);
352*61c4878aSAndroid Build Coastguard Worker         }
353*61c4878aSAndroid Build Coastguard Worker     }
354*61c4878aSAndroid Build Coastguard Worker 
355*61c4878aSAndroid Build Coastguard Worker     #[test]
encode_test_i64()356*61c4878aSAndroid Build Coastguard Worker     fn encode_test_i64() {
357*61c4878aSAndroid Build Coastguard Worker         for case in success_cases_i8::<i64>()
358*61c4878aSAndroid Build Coastguard Worker             .into_iter()
359*61c4878aSAndroid Build Coastguard Worker             .chain(success_cases_i32::<i64>())
360*61c4878aSAndroid Build Coastguard Worker         {
361*61c4878aSAndroid Build Coastguard Worker             let mut buffer = [0u8; 64];
362*61c4878aSAndroid Build Coastguard Worker             let len = case.1.varint_encode(&mut buffer).unwrap();
363*61c4878aSAndroid Build Coastguard Worker             assert_eq!(len, case.0.len());
364*61c4878aSAndroid Build Coastguard Worker             assert_eq!(&buffer[0..len], case.0);
365*61c4878aSAndroid Build Coastguard Worker         }
366*61c4878aSAndroid Build Coastguard Worker     }
367*61c4878aSAndroid Build Coastguard Worker }
368