1use crate::buf::ReverseBuf;
2use crate::encoding::{
3 encode_varint, encoded_len_varint, encoding_implemented_via_value_encoding,
4 encoding_uses_base_empty_state, prepend_varint, Buf, BufMut, Canonicity, Capped, DecodeContext,
5 DistinguishedValueDecoder, RestrictedDecodeContext, ValueDecoder, ValueEncoder, WireType,
6 Wiretyped,
7};
8use crate::DecodeError;
9use crate::DecodeErrorKind::{InvalidValue, OutOfDomainValue};
10
11pub struct Varint;
12
13encoding_uses_base_empty_state!(Varint);
14encoding_implemented_via_value_encoding!(Varint);
15
16#[inline]
19fn i8_to_unsigned(value: i8) -> u8 {
20 ((value << 1) ^ (value >> 7)) as u8
21}
22
23#[inline]
24fn u8_to_signed(value: u8) -> i8 {
25 ((value >> 1) as i8) ^ (-((value & 1) as i8))
26}
27
28#[inline]
29fn i16_to_unsigned(value: i16) -> u16 {
30 ((value << 1) ^ (value >> 15)) as u16
31}
32
33#[inline]
34fn u16_to_signed(value: u16) -> i16 {
35 ((value >> 1) as i16) ^ (-((value & 1) as i16))
36}
37
38#[inline]
39fn i32_to_unsigned(value: i32) -> u32 {
40 ((value << 1) ^ (value >> 31)) as u32
41}
42
43#[inline]
44fn u32_to_signed(value: u32) -> i32 {
45 ((value >> 1) as i32) ^ (-((value & 1) as i32))
46}
47
48#[inline]
49pub(crate) fn i64_to_unsigned(value: i64) -> u64 {
50 ((value << 1) ^ (value >> 63)) as u64
51}
52
53#[inline]
54pub(crate) fn u64_to_signed(value: u64) -> i64 {
55 ((value >> 1) as i64) ^ (-((value & 1) as i64))
56}
57
58macro_rules! varint {
60 (
61 $name:ident,
62 $ty:ty,
63 to_uint64($to_uint64_value:ident) $to_uint64:expr,
64 from_uint64($from_uint64_value:ident) $from_uint64:expr
65 $(, $($avoid_no_empty_state:tt)*)?
66 ) => {
67 impl Wiretyped<Varint, $ty> for () {
68 const WIRE_TYPE: WireType = WireType::Varint;
69 }
70
71 impl ValueEncoder<Varint, $ty> for () {
72 #[inline(always)]
73 fn encode_value<B: BufMut + ?Sized>($to_uint64_value: &$ty, buf: &mut B) {
74 encode_varint($to_uint64, buf);
75 }
76
77 #[inline(always)]
78 fn prepend_value<B: ReverseBuf + ?Sized>($to_uint64_value: &$ty, buf: &mut B) {
79 prepend_varint($to_uint64, buf);
80 }
81
82 #[inline(always)]
83 fn value_encoded_len($to_uint64_value: &$ty) -> usize {
84 encoded_len_varint($to_uint64)
85 }
86 }
87
88 impl ValueDecoder<Varint, $ty> for () {
89 #[inline(always)]
90 fn decode_value<B: Buf + ?Sized>(
91 __value: &mut $ty,
92 mut buf: Capped<B>,
93 _ctx: DecodeContext,
94 ) -> Result<(), DecodeError> {
95 let $from_uint64_value = buf.decode_varint()?;
96 *__value = $from_uint64;
97 Ok(())
98 }
99 }
100
101 impl DistinguishedValueDecoder<Varint, $ty> for () {
102 const CHECKS_EMPTY: bool = false;
103
104 #[inline]
105 fn decode_value_distinguished<const ALLOW_EMPTY: bool>(
106 value: &mut $ty,
107 buf: Capped<impl Buf + ?Sized>,
108 ctx: RestrictedDecodeContext,
109 ) -> Result<Canonicity, DecodeError> {
110 <() as ValueDecoder::<Varint, _>>::decode_value(value, buf, ctx.into_inner())?;
111 Ok(Canonicity::Canonical)
112 }
113 }
114
115 crate::encoding::delegate_value_encoding!(
116 encoding (Varint) borrows type ($ty) as owned including distinguished
117 );
118
119 #[cfg(test)]
120 mod $name {
121 use crate::encoding::Varint;
122 crate::encoding::test::check_type_test!(
123 Varint,
124 relaxed,
125 $ty,
126 WireType::Varint
127 $(, $($avoid_no_empty_state)*)?
128 );
129 crate::encoding::test::check_type_test!(
130 Varint,
131 distinguished,
132 $ty,
133 WireType::Varint
134 $(, $($avoid_no_empty_state)*)?
135 );
136 }
137 };
138}
139
140varint!(varint_bool, bool,
141to_uint64(value) {
142 u64::from(*value)
143},
144from_uint64(value) {
145 match value {
146 0 => false,
147 1 => true,
148 _ => return Err(DecodeError::new(OutOfDomainValue))
149 }
150});
151
152varint!(varint_u8, u8,
153to_uint64(value) {
154 *value as u64
155},
156from_uint64(value) {
157 u8::try_from(value).map_err(|_| DecodeError::new(OutOfDomainValue))?
158});
159
160varint!(varint_nonzerou8, core::num::NonZeroU8,
161to_uint64(value) {
162 value.get() as u64
163},
164from_uint64(value) {
165 core::num::NonZeroU8::new(
166 u8::try_from(value).map_err(|_| DecodeError::new(OutOfDomainValue))?
167 ).ok_or_else(|| DecodeError::new(InvalidValue))?
168}, has no empty state);
169
170varint!(varint_u16, u16,
171to_uint64(value) {
172 *value as u64
173},
174from_uint64(value) {
175 u16::try_from(value).map_err(|_| DecodeError::new(OutOfDomainValue))?
176});
177
178varint!(varint_nonzerou16, core::num::NonZeroU16,
179to_uint64(value) {
180 value.get() as u64
181},
182from_uint64(value) {
183 core::num::NonZeroU16::new(
184 u16::try_from(value).map_err(|_| DecodeError::new(OutOfDomainValue))?
185 ).ok_or_else(|| DecodeError::new(InvalidValue))?
186}, has no empty state);
187
188varint!(varint_u32, u32,
189to_uint64(value) {
190 *value as u64
191},
192from_uint64(value) {
193 u32::try_from(value).map_err(|_| DecodeError::new(OutOfDomainValue))?
194});
195
196varint!(varint_nonzerou32, core::num::NonZeroU32,
197to_uint64(value) {
198 value.get() as u64
199},
200from_uint64(value) {
201 core::num::NonZeroU32::new(
202 u32::try_from(value).map_err(|_| DecodeError::new(OutOfDomainValue))?
203 ).ok_or_else(|| DecodeError::new(InvalidValue))?
204}, has no empty state);
205
206varint!(varint_u64, u64,
207to_uint64(value) {
208 *value
209},
210from_uint64(value) {
211 value
212});
213
214varint!(varint_nonzerou64, core::num::NonZeroU64,
215to_uint64(value) {
216 value.get()
217},
218from_uint64(value) {
219 core::num::NonZeroU64::new(value).ok_or_else(|| DecodeError::new(InvalidValue))?
220}, has no empty state);
221
222varint!(varint_usize, usize,
223to_uint64(value) {
224 *value as u64
225},
226from_uint64(value) {
227 usize::try_from(value).map_err(|_| DecodeError::new(OutOfDomainValue))?
228});
229
230varint!(varint_nonzerousize, core::num::NonZeroUsize,
231to_uint64(value) {
232 value.get() as u64
233},
234from_uint64(value) {
235 core::num::NonZeroUsize::new(
236 usize::try_from(value).map_err(|_| DecodeError::new(OutOfDomainValue))?
237 ).ok_or_else(|| DecodeError::new(InvalidValue))?
238}, has no empty state);
239
240varint!(varint_i8, i8,
241to_uint64(value) {
242 i8_to_unsigned(*value) as u64
243},
244from_uint64(value) {
245 let value = u8::try_from(value)
246 .map_err(|_| DecodeError::new(OutOfDomainValue))?;
247 u8_to_signed(value)
248});
249
250varint!(varint_nonzeroi8, core::num::NonZeroI8,
251to_uint64(value) {
252 i8_to_unsigned(value.get()) as u64
253},
254from_uint64(value) {
255 let value = u8::try_from(value)
256 .map_err(|_| DecodeError::new(OutOfDomainValue))?;
257 core::num::NonZeroI8::new(u8_to_signed(value))
258 .ok_or_else(|| DecodeError::new(InvalidValue))?
259}, has no empty state);
260
261varint!(varint_i16, i16,
262to_uint64(value) {
263 i16_to_unsigned(*value) as u64
264},
265from_uint64(value) {
266 let value = u16::try_from(value)
267 .map_err(|_| DecodeError::new(OutOfDomainValue))?;
268 u16_to_signed(value)
269});
270
271varint!(varint_nonzeroi16, core::num::NonZeroI16,
272to_uint64(value) {
273 i16_to_unsigned(value.get()) as u64
274},
275from_uint64(value) {
276 let value = u16::try_from(value)
277 .map_err(|_| DecodeError::new(OutOfDomainValue))?;
278 core::num::NonZeroI16::new(u16_to_signed(value))
279 .ok_or_else(|| DecodeError::new(InvalidValue))?
280}, has no empty state);
281
282varint!(varint_i32, i32,
283to_uint64(value) {
284 i32_to_unsigned(*value) as u64
285},
286from_uint64(value) {
287 let value = u32::try_from(value)
288 .map_err(|_| DecodeError::new(OutOfDomainValue))?;
289 u32_to_signed(value)
290});
291
292varint!(varint_nonzeroi32, core::num::NonZeroI32,
293to_uint64(value) {
294 i32_to_unsigned(value.get()) as u64
295},
296from_uint64(value) {
297 let value = u32::try_from(value)
298 .map_err(|_| DecodeError::new(OutOfDomainValue))?;
299 core::num::NonZeroI32::new(u32_to_signed(value))
300 .ok_or_else(|| DecodeError::new(InvalidValue))?
301}, has no empty state);
302
303varint!(varint_i64, i64,
304to_uint64(value) {
305 i64_to_unsigned(*value)
306},
307from_uint64(value) {
308 u64_to_signed(value)
309});
310
311varint!(varint_nonzero648, core::num::NonZeroI64,
312to_uint64(value) {
313 i64_to_unsigned(value.get())
314},
315from_uint64(value) {
316 core::num::NonZeroI64::new(u64_to_signed(value))
317 .ok_or_else(|| DecodeError::new(InvalidValue))?
318}, has no empty state);
319
320varint!(varint_isize, isize,
321to_uint64(value) {
322 i64_to_unsigned(*value as i64)
323},
324from_uint64(value) {
325 isize::try_from(u64_to_signed(value))
326 .map_err(|_| DecodeError::new(OutOfDomainValue))?
327});
328
329varint!(varint_nonzeroisize, core::num::NonZeroIsize,
330to_uint64(value) {
331 i64_to_unsigned(value.get() as i64)
332},
333from_uint64(value) {
334 let value = isize::try_from(u64_to_signed(value))
335 .map_err(|_| DecodeError::new(OutOfDomainValue))?;
336 core::num::NonZeroIsize::new(value)
337 .ok_or_else(|| DecodeError::new(InvalidValue))?
338}, has no empty state);