1use bytes::{Buf, BufMut};
2
3pub const MAX_VARINT: u64 = 4_611_686_018_427_387_903;
5
6#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
14pub struct VarInt(u64);
15
16#[derive(Debug, thiserror::Error, PartialEq, Eq, Clone)]
18pub enum VarIntError {
19 #[error("value {0} exceeds maximum varint value (2^62 - 1)")]
21 Overflow(u64),
22 #[error("insufficient bytes for varint decoding")]
24 UnexpectedEnd,
25}
26
27impl VarInt {
28 #[inline]
30 pub fn from_u64(v: u64) -> Result<Self, VarIntError> {
31 if v > MAX_VARINT {
32 Err(VarIntError::Overflow(v))
33 } else {
34 Ok(VarInt(v))
35 }
36 }
37
38 #[inline]
40 pub fn into_inner(self) -> u64 {
41 self.0
42 }
43
44 #[inline]
46 pub fn encoded_len(&self) -> usize {
47 if self.0 <= 63 {
48 1
49 } else if self.0 <= 16383 {
50 2
51 } else if self.0 <= 1073741823 {
52 4
53 } else {
54 8
55 }
56 }
57
58 #[inline]
60 pub fn encode(&self, buf: &mut impl BufMut) {
61 match self.encoded_len() {
62 1 => {
63 buf.put_u8(self.0 as u8);
64 }
65 2 => {
66 buf.put_u16((self.0 as u16) | 0x4000);
67 }
68 4 => {
69 buf.put_u32((self.0 as u32) | 0x80000000);
70 }
71 8 => {
72 buf.put_u64(self.0 | 0xC000000000000000);
73 }
74 _ => unreachable!(),
75 }
76 }
77
78 #[inline]
80 pub fn decode(buf: &mut impl Buf) -> Result<Self, VarIntError> {
81 if buf.remaining() < 1 {
82 return Err(VarIntError::UnexpectedEnd);
83 }
84 let first = buf.chunk()[0];
85 let prefix = first >> 6;
86 let len = 1usize << prefix;
87 if buf.remaining() < len {
88 return Err(VarIntError::UnexpectedEnd);
89 }
90 let val = match len {
91 1 => {
92 buf.advance(1);
93 (first & 0x3F) as u64
94 }
95 2 => {
96 let v = buf.get_u16();
97 (v & 0x3FFF) as u64
98 }
99 4 => {
100 let v = buf.get_u32();
101 (v & 0x3FFFFFFF) as u64
102 }
103 8 => {
104 let v = buf.get_u64();
105 v & 0x3FFFFFFFFFFFFFFF
106 }
107 _ => unreachable!(),
108 };
109 Ok(VarInt(val))
110 }
111}
112
113impl TryFrom<u64> for VarInt {
114 type Error = VarIntError;
115 #[inline]
116 fn try_from(v: u64) -> Result<Self, Self::Error> {
117 Self::from_u64(v)
118 }
119}
120
121impl From<VarInt> for u64 {
122 #[inline]
123 fn from(v: VarInt) -> u64 {
124 v.0
125 }
126}
127
128impl VarInt {
129 #[inline]
132 pub fn from_usize(v: usize) -> Self {
133 VarInt(v as u64)
134 }
135}
136
137impl From<u32> for VarInt {
138 #[inline]
139 fn from(v: u32) -> Self {
140 VarInt(v as u64)
141 }
142}