1#![cfg_attr(not(feature = "std"), no_std)]
42
43use pw_status::{Error, Result};
44
45pub const MAX_VARINT_SIZE_BYTES: usize = 10;
47
48pub trait VarintDecode: Sized {
53 fn varint_decode(data: &[u8]) -> Result<(usize, Self)>;
62}
63
64pub trait VarintEncode: Sized {
69 fn varint_encode(self, data: &mut [u8]) -> Result<usize>;
78}
79
80#[inline]
91#[must_use]
92pub const fn zig_zag_encode(value: i64) -> u64 {
93 (value.cast_unsigned() << 1) ^ (value >> (i64::BITS - 1)).cast_unsigned()
94}
95
96#[inline]
98#[must_use]
99pub const fn zig_zag_decode(value: u64) -> i64 {
100 ((value >> 1) ^ (0u64.wrapping_sub(value & 1))).cast_signed()
101}
102
103macro_rules! unsigned_varint_impl {
104 ($t:ty) => {
105 impl VarintDecode for $t {
106 #[inline]
107 fn varint_decode(data: &[u8]) -> Result<(usize, Self)> {
108 let (decoded_len, val) = decode_u64(data)?;
109 let val = val.try_into().map_err(|_| Error::OutOfRange)?;
110 Ok((decoded_len, val))
111 }
112 }
113
114 impl VarintEncode for $t {
115 #[inline]
116 fn varint_encode(self, data: &mut [u8]) -> Result<usize> {
117 encode_u64(data, u64::from(self))
118 }
119 }
120 };
121}
122
123macro_rules! signed_varint_impl {
124 ($t:ty) => {
125 impl VarintDecode for $t {
126 #[inline]
127 fn varint_decode(data: &[u8]) -> Result<(usize, Self)> {
128 let (decoded_len, val) = decode_u64(data)?;
129 let val = zig_zag_decode(val)
130 .try_into()
131 .map_err(|_| Error::OutOfRange)?;
132 Ok((decoded_len, val))
133 }
134 }
135
136 impl VarintEncode for $t {
137 #[inline]
138 fn varint_encode(self, data: &mut [u8]) -> Result<usize> {
139 encode_u64(data, zig_zag_encode(i64::from(self)))
140 }
141 }
142 };
143}
144
145unsigned_varint_impl!(u8);
146unsigned_varint_impl!(u16);
147unsigned_varint_impl!(u32);
148unsigned_varint_impl!(u64);
149
150signed_varint_impl!(i8);
151signed_varint_impl!(i16);
152signed_varint_impl!(i32);
153signed_varint_impl!(i64);
154
155const CONTINUATION_BIT: u8 = 0x80;
157
158const VALUE_MASK: u8 = 0x7f;
160
161const BITS_PER_VARINT_BYTE: usize = 7;
163
164const TENTH_BYTE_VALUE_MASK: u8 = 0x01;
166
167const TENTH_BYTE_BIT_SHIFT: u32 = 63;
169
170#[inline]
173fn decode_u64(data: &[u8]) -> Result<(usize, u64)> {
174 let Some((&b0, tail)) = data.split_first() else {
175 return Err(Error::OutOfRange);
176 };
177 if (b0 & CONTINUATION_BIT) == 0 {
178 return Ok((1, u64::from(b0)));
179 }
180 let Some(&b1) = tail.first() else {
181 return Err(Error::OutOfRange);
182 };
183 if (b1 & CONTINUATION_BIT) == 0 {
184 let val = u64::from(b0 & VALUE_MASK) | (u64::from(b1) << BITS_PER_VARINT_BYTE);
185 return Ok((2, val));
186 }
187 decode_u64_slow(data)
188}
189
190#[inline(never)]
193fn decode_u64_slow(data: &[u8]) -> Result<(usize, u64)> {
194 let mut value: u64 = 0;
195 let (head, tail) = data.split_at(data.len().min(MAX_VARINT_SIZE_BYTES - 1));
196
197 for (i, &byte) in head.iter().enumerate() {
198 value |= u64::from(byte & VALUE_MASK) << (i * BITS_PER_VARINT_BYTE);
199
200 if (byte & CONTINUATION_BIT) == 0 {
201 return Ok((i + 1, value));
202 }
203 }
204
205 let Some(&byte) = tail.first() else {
206 return Err(Error::OutOfRange);
207 };
208
209 if (byte & !TENTH_BYTE_VALUE_MASK) != 0 {
213 return Err(Error::OutOfRange);
214 }
215
216 Ok((
217 MAX_VARINT_SIZE_BYTES,
218 value | u64::from(byte) << TENTH_BYTE_BIT_SHIFT,
219 ))
220}
221
222fn encode_u64(data: &mut [u8], mut value: u64) -> Result<usize> {
223 for (i, d) in data.iter_mut().enumerate() {
224 #[allow(clippy::cast_possible_truncation)]
226 let byte: u8 = (value as u8) & VALUE_MASK;
227 value >>= BITS_PER_VARINT_BYTE;
228 if value == 0 {
229 *d = byte;
230 return Ok(i + 1);
231 }
232 *d = byte | CONTINUATION_BIT;
233 }
234 Err(Error::OutOfRange)
235}
236
237#[cfg(test)]
238mod test {
239 use super::*;
240
241 fn success_cases_u8<T>() -> Vec<(Vec<u8>, T)>
242 where
243 T: From<u8>,
244 {
245 vec![
246 (vec![0x00], 0x00.into()),
248 (vec![0x01], 0x01.into()),
249 (vec![0x02], 0x02.into()),
250 (vec![0x3f], 0x3f.into()),
252 (vec![0x40], 0x40.into()),
253 (vec![0x7e], 0x7e.into()),
254 (vec![0x7f], 0x7f.into()),
255 (vec![0x80, 0x01], 128.into()),
257 (vec![0x81, 0x01], 129.into()),
258 (vec![0x96, 0x01], 150.into()),
260 ]
261 }
262
263 fn success_cases_i8<T>() -> Vec<(Vec<u8>, T)>
264 where
265 T: From<i8>,
266 {
267 vec![
268 (vec![0x00], 0i8.into()),
270 (vec![0x01], (-1i8).into()),
271 (vec![0x02], 1i8.into()),
272 (vec![0x03], (-2i8).into()),
273 (vec![0x04], 2i8.into()),
274 (vec![125], (-63i8).into()),
276 (vec![126], (63i8).into()),
277 (vec![127], (-64i8).into()),
278 (vec![0x80, 0x1], 64i8.into()),
280 (vec![0x81, 0x1], (-65i8).into()),
281 (vec![0x82, 0x1], 65i8.into()),
282 ]
283 }
284
285 fn success_cases_u32<T>() -> Vec<(Vec<u8>, T)>
286 where
287 T: From<u32>,
288 {
289 vec![
290 (vec![0xfe, 0xff, 0xff, 0xff, 0x0f], 0xffff_fffe.into()),
292 (vec![0xff, 0xff, 0xff, 0xff, 0x0f], 0xffff_ffff.into()),
293 ]
294 }
295
296 fn success_cases_i32<T>() -> Vec<(Vec<u8>, T)>
297 where
298 T: From<i32>,
299 {
300 vec![
301 (vec![0xff, 0xff, 0xff, 0xff, 0x0f], i32::MIN.into()),
303 (vec![0xfe, 0xff, 0xff, 0xff, 0x0f], i32::MAX.into()),
304 ]
305 }
306
307 #[test]
308 fn decode_test_u8() {
309 for case in success_cases_u8::<u8>() {
310 assert_eq!(u8::varint_decode(&case.0), Ok((case.0.len(), case.1)));
311 }
312
313 assert_eq!(u8::varint_decode(&[0x96]), Err(Error::OutOfRange));
315 assert_eq!(u8::varint_decode(&[0x80, 0x02]), Err(Error::OutOfRange));
317 }
318
319 #[test]
320 fn decode_test_i8() {
321 for case in success_cases_i8::<i8>() {
322 assert_eq!(i8::varint_decode(&case.0), Ok((case.0.len(), case.1)));
323 }
324
325 assert_eq!(i8::varint_decode(&[0x96]), Err(Error::OutOfRange));
327 assert_eq!(i8::varint_decode(&[0x80, 0x02]), Err(Error::OutOfRange));
329 assert_eq!(i8::varint_decode(&[0x81, 0x02]), Err(Error::OutOfRange));
330 }
331
332 #[test]
333 fn decode_test_u16() {
334 for case in success_cases_u8::<u16>() {
335 assert_eq!(u16::varint_decode(&case.0), Ok((case.0.len(), case.1)));
336 }
337
338 assert_eq!(u16::varint_decode(&[0x96]), Err(Error::OutOfRange));
339 }
340
341 #[test]
342 fn decode_test_i16() {
343 for case in success_cases_i8::<i16>() {
344 assert_eq!(i16::varint_decode(&case.0), Ok((case.0.len(), case.1)));
345 }
346
347 assert_eq!(i16::varint_decode(&[0x96]), Err(Error::OutOfRange));
348 }
349
350 #[test]
351 fn decode_test_u32() {
352 for case in success_cases_u8::<u32>()
353 .into_iter()
354 .chain(success_cases_u32::<u32>())
355 {
356 assert_eq!(u32::varint_decode(&case.0), Ok((case.0.len(), case.1)));
357 }
358
359 assert_eq!(u32::varint_decode(&[0x96]), Err(Error::OutOfRange));
360 }
361
362 #[test]
363 fn decode_test_i32() {
364 for case in success_cases_i8::<i32>()
365 .into_iter()
366 .chain(success_cases_i32::<i32>())
367 {
368 assert_eq!(i32::varint_decode(&case.0), Ok((case.0.len(), case.1)));
369 }
370
371 assert_eq!(i32::varint_decode(&[0x96]), Err(Error::OutOfRange));
372 }
373
374 #[test]
375 fn decode_test_u64() {
376 for case in success_cases_u8::<u64>()
377 .into_iter()
378 .chain(success_cases_u32::<u64>())
379 {
380 assert_eq!(u64::varint_decode(&case.0), Ok((case.0.len(), case.1)));
381 }
382
383 assert_eq!(u64::varint_decode(&[0x96]), Err(Error::OutOfRange));
384 }
385
386 #[test]
387 fn decode_test_i64() {
388 for case in success_cases_i8::<i64>()
389 .into_iter()
390 .chain(success_cases_i32::<i64>())
391 {
392 assert_eq!(i64::varint_decode(&case.0), Ok((case.0.len(), case.1)));
393 }
394
395 assert_eq!(i64::varint_decode(&[0x96]), Err(Error::OutOfRange));
396 }
397
398 #[test]
399 fn decode_u64_empty_and_truncated() {
400 assert_eq!(u64::varint_decode(&[]), Err(Error::OutOfRange));
401 assert_eq!(u64::varint_decode(&[0x80]), Err(Error::OutOfRange));
402 assert_eq!(u64::varint_decode(&[0x80, 0x80]), Err(Error::OutOfRange));
403 }
404
405 #[test]
406 fn decode_u64_10th_byte_valid_and_overflow() {
407 let mut valid_10th = [0x80u8; MAX_VARINT_SIZE_BYTES];
408 valid_10th[MAX_VARINT_SIZE_BYTES - 1] = 0x01;
409 assert_eq!(
410 u64::varint_decode(&valid_10th),
411 Ok((MAX_VARINT_SIZE_BYTES, 1u64 << 63))
412 );
413
414 let mut u64_max_bytes = [0xffu8; MAX_VARINT_SIZE_BYTES];
415 u64_max_bytes[MAX_VARINT_SIZE_BYTES - 1] = 0x01;
416 assert_eq!(
417 u64::varint_decode(&u64_max_bytes),
418 Ok((MAX_VARINT_SIZE_BYTES, u64::MAX))
419 );
420
421 assert_eq!(u64::varint_decode(&[0xff, 0x7f]), Ok((2, 0x3fff)));
423 assert_eq!(u64::varint_decode(&[0x80, 0x80, 0x01]), Ok((3, 0x4000)));
424
425 let mut overflow_bits = [0x80u8; MAX_VARINT_SIZE_BYTES];
426 overflow_bits[MAX_VARINT_SIZE_BYTES - 1] = 0x02;
427 assert_eq!(u64::varint_decode(&overflow_bits), Err(Error::OutOfRange));
428
429 let mut continuation_set = [0x80u8; MAX_VARINT_SIZE_BYTES];
430 continuation_set[MAX_VARINT_SIZE_BYTES - 1] = 0x81;
431 assert_eq!(
432 u64::varint_decode(&continuation_set),
433 Err(Error::OutOfRange)
434 );
435
436 let overlong = [0x80u8; 12];
437 assert_eq!(u64::varint_decode(&overlong), Err(Error::OutOfRange));
438 }
439
440 #[test]
441 fn encode_test_u8() {
442 for case in success_cases_u8::<u8>() {
443 let mut buffer = [0u8; 64];
444 let len = case.1.varint_encode(&mut buffer).unwrap();
445 assert_eq!(len, case.0.len());
446 assert_eq!(&buffer[0..len], case.0);
447 }
448 }
449
450 #[test]
451 fn encode_test_i8() {
452 for case in success_cases_i8::<i8>() {
453 let mut buffer = [0u8; 64];
454 let len = case.1.varint_encode(&mut buffer).unwrap();
455 assert_eq!(len, case.0.len());
456 assert_eq!(&buffer[0..len], case.0);
457 }
458 }
459
460 #[test]
461 fn encode_test_u16() {
462 for case in success_cases_u8::<u16>() {
463 let mut buffer = [0u8; 64];
464 let len = case.1.varint_encode(&mut buffer).unwrap();
465 assert_eq!(len, case.0.len());
466 assert_eq!(&buffer[0..len], case.0);
467 }
468 }
469
470 #[test]
471 fn encode_test_i16() {
472 for case in success_cases_i8::<i16>() {
473 let mut buffer = [0u8; 64];
474 let len = case.1.varint_encode(&mut buffer).unwrap();
475 assert_eq!(len, case.0.len());
476 assert_eq!(&buffer[0..len], case.0);
477 }
478 }
479
480 #[test]
481 fn encode_test_u32() {
482 for case in success_cases_u8::<u32>()
483 .into_iter()
484 .chain(success_cases_u32::<u32>())
485 {
486 let mut buffer = [0u8; 64];
487 let len = case.1.varint_encode(&mut buffer).unwrap();
488 assert_eq!(len, case.0.len());
489 assert_eq!(&buffer[0..len], case.0);
490 }
491 }
492
493 #[test]
494 fn encode_test_i32() {
495 for case in success_cases_i8::<i32>()
496 .into_iter()
497 .chain(success_cases_i32::<i32>())
498 {
499 let mut buffer = [0u8; 64];
500 let len = case.1.varint_encode(&mut buffer).unwrap();
501 assert_eq!(len, case.0.len());
502 assert_eq!(&buffer[0..len], case.0);
503 }
504 }
505
506 #[test]
507 fn encode_test_u64() {
508 for case in success_cases_u8::<u64>()
509 .into_iter()
510 .chain(success_cases_u32::<u64>())
511 {
512 let mut buffer = [0u8; 64];
513 let len = case.1.varint_encode(&mut buffer).unwrap();
514 assert_eq!(len, case.0.len());
515 assert_eq!(&buffer[0..len], case.0);
516 }
517 }
518
519 #[test]
520 fn encode_test_i64() {
521 for case in success_cases_i8::<i64>()
522 .into_iter()
523 .chain(success_cases_i32::<i64>())
524 {
525 let mut buffer = [0u8; 64];
526 let len = case.1.varint_encode(&mut buffer).unwrap();
527 assert_eq!(len, case.0.len());
528 assert_eq!(&buffer[0..len], case.0);
529 }
530 }
531
532 #[test]
533 fn zig_zag_encode_64bit_boundaries() {
534 assert_eq!(zig_zag_encode(0), 0);
535 assert_eq!(zig_zag_encode(-1), 1);
536 assert_eq!(zig_zag_encode(1), 2);
537 assert_eq!(zig_zag_encode(i64::MAX), u64::MAX - 1);
538 assert_eq!(zig_zag_encode(i64::MIN), u64::MAX);
539 }
540
541 #[test]
542 fn zig_zag_decode_64bit_boundaries() {
543 assert_eq!(zig_zag_decode(0), 0);
544 assert_eq!(zig_zag_decode(1), -1);
545 assert_eq!(zig_zag_decode(2), 1);
546 assert_eq!(zig_zag_decode(u64::MAX - 1), i64::MAX);
547 assert_eq!(zig_zag_decode(u64::MAX), i64::MIN);
548 }
549}