1pub mod encode;
3
4pub mod decode;
6
7const U8_LEN: usize = 2;
8const U16_LEN: usize = 3;
9const U32_LEN: usize = 5;
10const U64_LEN: usize = 10;
11const U128_LEN: usize = 19;
12
13#[cfg(target_pointer_width = "64")]
14const USIZE_LEN: usize = U64_LEN;
15
16#[cfg(target_pointer_width = "32")]
17const USIZE_LEN: usize = U32_LEN;
18
19#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
21#[repr(u8)]
22pub enum U8Size {
23 One,
25 Two,
27}
28
29impl U8Size {
30 #[inline]
32 pub const fn val(self) -> usize {
33 match self {
34 Self::One => 1,
35 Self::Two => 2,
36 }
37 }
38
39 #[inline]
41 pub const fn max() -> Self {
42 Self::Two
43 }
44
45 #[inline]
47 pub const fn min() -> Self {
48 Self::One
49 }
50
51 #[inline]
52 const fn from(val: usize) -> Self {
53 match val {
54 1 => Self::One,
55 2 => Self::Two,
56 _ => unreachable!(),
57 }
58 }
59}
60
61#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
63#[repr(u8)]
64pub enum U16Size {
65 One,
67 Two,
69 Three,
71}
72
73impl U16Size {
74 #[inline]
76 pub const fn val(self) -> usize {
77 match self {
78 Self::One => 1,
79 Self::Two => 2,
80 Self::Three => 3,
81 }
82 }
83
84 #[inline]
86 pub const fn max() -> Self {
87 Self::Three
88 }
89
90 #[inline]
92 pub const fn min() -> Self {
93 Self::One
94 }
95
96 #[inline]
97 const fn from(val: usize) -> Self {
98 match val {
99 1 => Self::One,
100 2 => Self::Two,
101 3 => Self::Three,
102 _ => unreachable!(),
103 }
104 }
105}
106
107#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
109#[repr(u8)]
110pub enum U32Size {
111 One,
113 Two,
115 Three,
117 Four,
119 Five,
121}
122
123impl U32Size {
124 #[inline]
126 pub const fn val(self) -> usize {
127 match self {
128 Self::One => 1,
129 Self::Two => 2,
130 Self::Three => 3,
131 Self::Four => 4,
132 Self::Five => 5,
133 }
134 }
135
136 #[inline]
138 pub const fn max() -> Self {
139 Self::Five
140 }
141
142 #[inline]
144 pub const fn min() -> Self {
145 Self::One
146 }
147
148 #[inline]
149 const fn from(val: usize) -> Self {
150 match val {
151 1 => Self::One,
152 2 => Self::Two,
153 3 => Self::Three,
154 4 => Self::Four,
155 5 => Self::Five,
156 _ => unreachable!(),
157 }
158 }
159}
160
161#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
163#[repr(u8)]
164pub enum U64Size {
165 One,
167 Two,
169 Three,
171 Four,
173 Five,
175 Six,
177 Seven,
179 Eight,
181 Nine,
183 Ten,
185}
186
187impl U64Size {
188 #[inline]
190 pub const fn val(&self) -> usize {
191 match self {
192 Self::One => 1,
193 Self::Two => 2,
194 Self::Three => 3,
195 Self::Four => 4,
196 Self::Five => 5,
197 Self::Six => 6,
198 Self::Seven => 7,
199 Self::Eight => 8,
200 Self::Nine => 9,
201 Self::Ten => 10,
202 }
203 }
204
205 #[inline]
207 pub const fn max() -> Self {
208 Self::Ten
209 }
210
211 #[inline]
213 pub const fn min() -> Self {
214 Self::One
215 }
216
217 #[inline]
218 const fn from(val: usize) -> Self {
219 match val {
220 1 => Self::One,
221 2 => Self::Two,
222 3 => Self::Three,
223 4 => Self::Four,
224 5 => Self::Five,
225 6 => Self::Six,
226 7 => Self::Seven,
227 8 => Self::Eight,
228 9 => Self::Nine,
229 10 => Self::Ten,
230 _ => unreachable!(),
231 }
232 }
233}
234
235#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
237#[repr(u8)]
238pub enum U128Size {
239 One,
241 Two,
243 Three,
245 Four,
247 Five,
249 Six,
251 Seven,
253 Eight,
255 Nine,
257 Ten,
259 Eleven,
261 Twelve,
263 Thirteen,
265 Fourteen,
267 Fifteen,
269 Sixteen,
271 Seventeen,
273 Eighteen,
275 Nineteen,
277}
278
279impl U128Size {
280 #[inline]
282 pub const fn val(&self) -> usize {
283 match self {
284 Self::One => 1,
285 Self::Two => 2,
286 Self::Three => 3,
287 Self::Four => 4,
288 Self::Five => 5,
289 Self::Six => 6,
290 Self::Seven => 7,
291 Self::Eight => 8,
292 Self::Nine => 9,
293 Self::Ten => 10,
294 Self::Eleven => 11,
295 Self::Twelve => 12,
296 Self::Thirteen => 13,
297 Self::Fourteen => 14,
298 Self::Fifteen => 15,
299 Self::Sixteen => 16,
300 Self::Seventeen => 17,
301 Self::Eighteen => 18,
302 Self::Nineteen => 19,
303 }
304 }
305
306 #[inline]
308 pub const fn max() -> Self {
309 Self::Nineteen
310 }
311
312 #[inline]
314 pub const fn min() -> Self {
315 Self::One
316 }
317
318 #[inline]
319 const fn from(val: usize) -> Self {
320 match val {
321 1 => Self::One,
322 2 => Self::Two,
323 3 => Self::Three,
324 4 => Self::Four,
325 5 => Self::Five,
326 6 => Self::Six,
327 7 => Self::Seven,
328 8 => Self::Eight,
329 9 => Self::Nine,
330 10 => Self::Ten,
331 11 => Self::Eleven,
332 12 => Self::Twelve,
333 13 => Self::Thirteen,
334 14 => Self::Fourteen,
335 15 => Self::Fifteen,
336 16 => Self::Sixteen,
337 17 => Self::Seventeen,
338 18 => Self::Eighteen,
339 19 => Self::Nineteen,
340 _ => unreachable!(),
341 }
342 }
343}
344
345#[cfg(target_pointer_width = "64")]
347pub type Usize = U64Size;
348
349#[cfg(target_pointer_width = "32")]
351pub type Usize = U32Size;
352
353const MAX_VARINT_LEN64: usize = 10;
355
356#[cfg(feature = "alloc")]
359#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
360#[inline]
361pub fn append_uvarint(mut buf: alloc::vec::Vec<u8>, x: impl Unsigned) -> alloc::vec::Vec<u8> {
362 let mut x = x.to_u64();
363 while x >= 0x80 {
364 buf.push((x as u8) | 0x80);
365 x >>= 7;
366 }
367 buf.push(x as u8);
368 buf
369}
370
371#[cfg(feature = "std")]
373#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
374#[inline]
375pub fn write_uvarint<W: std::io::Write>(
376 mut buf: W,
377 x: impl Unsigned,
378) -> Result<usize, std::io::Error> {
379 let mut x = x.to_u64();
380 let mut n = 0;
381 while x >= 0x80 {
382 n += buf.write(&[(x as u8) | 0x80])?;
383 x >>= 7;
384 }
385 buf.write(&[x as u8]).map(|nn| {
386 n += nn;
387 n
388 })
389}
390
391#[cfg(feature = "std")]
394#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
395#[inline]
396pub fn read_uvarint<R: std::io::Read, I: Unsigned>(mut r: R) -> std::io::Result<(I, usize)> {
397 let mut x = 0;
398 let mut s = 0;
399 for i in 0..MAX_VARINT_LEN64 {
400 let mut b = [0; 1];
401 r.read_exact(&mut b)?;
402
403 if b[0] < 0x80 {
404 if i == MAX_VARINT_LEN64 - 1 && b[0] > 1 {
405 return Err(std::io::Error::new(
406 std::io::ErrorKind::Other,
407 Error::Overflow,
408 ));
409 }
410 return Ok((I::from_u64(x | ((b[0] as u64) << s)), i));
411 }
412 x |= ((b[0] & 0x7f) as u64) << s;
413 s += 7;
414 }
415
416 Err(std::io::Error::new(
417 std::io::ErrorKind::Other,
418 Error::Overflow,
419 ))
420}
421
422#[inline]
427pub fn put_uvarint(buf: &mut [u8], x: impl Unsigned) -> usize {
428 let mut i = 0;
429 let mut x = x.to_u64();
430 while x >= 0x80 {
431 buf[i] = (x as u8) | 0x80;
432 x >>= 7;
433 i += 1;
434 }
435 buf[i] = x as u8;
436 i + 1
437}
438
439#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
441pub enum Error {
442 SmallBuffer,
444 Overflow,
446}
447
448impl core::fmt::Display for Error {
449 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
450 match self {
451 Self::SmallBuffer => write!(f, "binary: the buffer is too small"),
452 Self::Overflow => write!(f, "binary: varint overflows a 64-bit integer"),
453 }
454 }
455}
456
457#[cfg(feature = "std")]
458impl std::error::Error for Error {}
459
460#[inline]
463pub fn uvarint<R: Unsigned>(buf: &[u8]) -> Result<(R, usize), Error> {
464 let (mut x, mut s) = (0, 0);
465 for (i, b) in buf.iter().enumerate() {
466 if i == MAX_VARINT_LEN64 {
467 return Err(Error::Overflow);
468 }
469
470 let b = *b;
471 if b < 0x80 {
472 if i == MAX_VARINT_LEN64 - 1 && b > 1 {
473 return Err(Error::Overflow);
474 }
475 return Ok((R::from_u64(x | (b as u64) << s), i + 1));
476 }
477 x |= ((b & 0x7f) as u64) << s;
478 s += 7;
479 }
480 Err(Error::SmallBuffer)
481}
482
483#[cfg(feature = "alloc")]
486#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
487#[inline]
488pub fn append_varint(buf: alloc::vec::Vec<u8>, x: impl Signed) -> alloc::vec::Vec<u8> {
489 let x = x.to_i64();
490 let mut ux = (x as u64) << 1;
491 if x < 0 {
492 ux = !ux;
493 }
494 append_uvarint(buf, ux)
495}
496
497#[cfg(feature = "std")]
499#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
500#[inline]
501pub fn write_varint<W: std::io::Write>(buf: W, x: impl Signed) -> std::io::Result<usize> {
502 let x = x.to_i64();
503 let mut ux = (x as u64) << 1;
504 if x < 0 {
505 ux = !ux;
506 }
507 write_uvarint(buf, ux)
508}
509
510#[cfg(feature = "std")]
513#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
514#[inline]
515pub fn read_varint<R: std::io::Read, I: Signed>(r: R) -> std::io::Result<(I, usize)> {
516 let (ux, readed) = read_uvarint::<R, u64>(r)?;
517 let mut x = (ux >> 1) as i64;
518 if ux & 1 != 0 {
519 x = !x;
520 }
521 Ok((I::from_i64(x), readed))
522}
523
524#[inline]
529pub fn put_varint(buf: &mut [u8], x: impl Signed) -> usize {
530 let x = x.to_i64();
531 let mut ux = (x as u64) << 1;
532 if x < 0 {
533 ux = !ux;
534 }
535 put_uvarint(buf, ux)
536}
537
538#[inline]
541pub fn varint<R: Signed>(buf: &[u8]) -> Result<(R, usize), Error> {
542 let (ux, n) = uvarint::<u64>(buf)?;
543 let mut x = (ux >> 1) as i64;
544 if ux & 1 != 0 {
545 x = !x;
546 }
547 Ok((R::from_i64(x), n))
548}
549
550macro_rules! impl_ {
551 ($trait: ident::<$ret:ident>::$fn: ident::$from_fn: ident { $($x:ident),+ $(,)? }) => {
552 $(
553 impl $trait for $x {
554 fn $fn(&self) -> $ret {
555 *self as $ret
556 }
557
558 fn $from_fn(val: $ret) -> Self {
559 val as Self
560 }
561 }
562 )*
563 };
564}
565
566pub trait Unsigned {
568 fn to_u64(&self) -> u64;
570
571 fn from_u64(val: u64) -> Self;
573}
574
575impl_! {
576 Unsigned::<u64>::to_u64::from_u64 {
577 u8,
578 u16,
579 u32,
580 usize,
581 u64,
582 u128,
583 }
584}
585
586pub trait Signed {
588 fn to_i64(&self) -> i64;
590
591 fn from_i64(val: i64) -> Self;
593}
594
595impl_! {
596 Signed::<i64>::to_i64::from_i64 {
597 i8,
598 i16,
599 i32,
600 isize,
601 i64,
602 i128,
603 }
604}
605
606#[cfg(test)]
607mod tests {
608 use super::*;
609
610 const MAX_VARINT_LEN16: usize = 3;
611 const MAX_VARINT_LEN32: usize = 5;
612
613 fn test_constant(w: u64, max: usize) {
614 let mut buf = vec![0; MAX_VARINT_LEN64];
615 let n = put_uvarint(&mut buf, 1u64 << (w - 1));
616 assert_eq!(n, max);
617 }
618
619 #[test]
620 fn test_constants() {
621 test_constant(16, MAX_VARINT_LEN16);
622 test_constant(32, MAX_VARINT_LEN32);
623 test_constant(64, MAX_VARINT_LEN64);
624 }
625}