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 #[error("7-byte varint is not a defined encoding length in draft-17")]
29 InvalidCodePoint,
30}
31
32impl VarInt {
33 #[inline]
35 pub fn from_u64(v: u64) -> Result<Self, VarIntError> {
36 if v > MAX_VARINT {
37 Err(VarIntError::Overflow(v))
38 } else {
39 Ok(VarInt(v))
40 }
41 }
42
43 #[inline]
45 pub fn into_inner(self) -> u64 {
46 self.0
47 }
48
49 #[inline]
51 pub fn encoded_len(&self) -> usize {
52 if self.0 <= 63 {
53 1
54 } else if self.0 <= 16383 {
55 2
56 } else if self.0 <= 1073741823 {
57 4
58 } else {
59 8
60 }
61 }
62
63 #[inline]
65 pub fn encode(&self, buf: &mut impl BufMut) {
66 match self.encoded_len() {
67 1 => {
68 buf.put_u8(self.0 as u8);
69 }
70 2 => {
71 buf.put_u16((self.0 as u16) | 0x4000);
72 }
73 4 => {
74 buf.put_u32((self.0 as u32) | 0x80000000);
75 }
76 8 => {
77 buf.put_u64(self.0 | 0xC000000000000000);
78 }
79 _ => unreachable!(),
80 }
81 }
82
83 #[inline]
85 pub fn decode(buf: &mut impl Buf) -> Result<Self, VarIntError> {
86 if buf.remaining() < 1 {
87 return Err(VarIntError::UnexpectedEnd);
88 }
89 let first = buf.chunk()[0];
90 let prefix = first >> 6;
91 let len = 1usize << prefix;
92 if buf.remaining() < len {
93 return Err(VarIntError::UnexpectedEnd);
94 }
95 let val = match len {
96 1 => {
97 buf.advance(1);
98 (first & 0x3F) as u64
99 }
100 2 => {
101 let v = buf.get_u16();
102 (v & 0x3FFF) as u64
103 }
104 4 => {
105 let v = buf.get_u32();
106 (v & 0x3FFFFFFF) as u64
107 }
108 8 => {
109 let v = buf.get_u64();
110 v & 0x3FFFFFFFFFFFFFFF
111 }
112 _ => unreachable!(),
113 };
114 Ok(VarInt(val))
115 }
116}
117
118pub const MAX_MOQT_VARINT: u64 = u64::MAX;
120
121impl VarInt {
122 #[inline]
125 pub fn from_u64_moqt(v: u64) -> Self {
126 VarInt(v)
127 }
128
129 #[inline]
134 fn encoded_len_moqt(&self, seven_byte: bool) -> usize {
135 for len in 1..=8 {
136 if (len != 7 || seven_byte) && self.0 < 1u64 << (7 * len) {
137 return len;
138 }
139 }
140 9
141 }
142
143 #[inline]
144 fn encode_moqt_inner(&self, buf: &mut impl BufMut, seven_byte: bool) {
145 let len = self.encoded_len_moqt(seven_byte);
146 if len == 9 {
147 buf.put_u8(0xFF);
148 buf.put_u64(self.0);
149 return;
150 }
151 let prefix = (((1u16 << (len - 1)) - 1) << (9 - len)) as u8;
153 let combined = ((prefix as u64) << (8 * (len - 1))) | self.0;
154 for i in (0..len).rev() {
155 buf.put_u8((combined >> (8 * i)) as u8);
156 }
157 }
158
159 #[inline]
160 fn decode_moqt_inner(buf: &mut impl Buf, seven_byte: bool) -> Result<Self, VarIntError> {
161 if buf.remaining() < 1 {
162 return Err(VarIntError::UnexpectedEnd);
163 }
164 let first = buf.chunk()[0];
165
166 if first == 0xFF {
167 if buf.remaining() < 9 {
168 return Err(VarIntError::UnexpectedEnd);
169 }
170 buf.advance(1);
171 return Ok(VarInt(buf.get_u64()));
172 }
173
174 let len = first.leading_ones() as usize + 1;
175 if len == 7 && !seven_byte {
176 return Err(VarIntError::InvalidCodePoint);
177 }
178 if buf.remaining() < len {
179 return Err(VarIntError::UnexpectedEnd);
180 }
181 let mut val = (first & ((1u16 << (8 - len)) - 1) as u8) as u64;
182 buf.advance(1);
183 for _ in 1..len {
184 val = (val << 8) | buf.get_u8() as u64;
185 }
186 Ok(VarInt(val))
187 }
188
189 #[inline]
196 pub fn encode_moqt<P: MoqtProfile>(&self, buf: &mut impl BufMut) {
197 self.encode_moqt_inner(buf, P::SEVEN_BYTE);
198 }
199
200 #[inline]
206 pub fn decode_moqt<P: MoqtProfile>(buf: &mut impl Buf) -> Result<Self, VarIntError> {
207 Self::decode_moqt_inner(buf, P::SEVEN_BYTE)
208 }
209}
210
211mod sealed {
212 pub trait Sealed {}
213 impl Sealed for super::Moqt17 {}
214 impl Sealed for super::Moqt18 {}
215}
216
217pub trait MoqtProfile: sealed::Sealed {
223 const SEVEN_BYTE: bool;
225}
226
227pub struct Moqt17;
231
232pub struct Moqt18;
235
236impl MoqtProfile for Moqt17 {
237 const SEVEN_BYTE: bool = false;
238}
239
240impl MoqtProfile for Moqt18 {
241 const SEVEN_BYTE: bool = true;
242}
243
244impl TryFrom<u64> for VarInt {
245 type Error = VarIntError;
246 #[inline]
247 fn try_from(v: u64) -> Result<Self, Self::Error> {
248 Self::from_u64(v)
249 }
250}
251
252impl From<VarInt> for u64 {
253 #[inline]
254 fn from(v: VarInt) -> u64 {
255 v.0
256 }
257}
258
259impl VarInt {
260 #[inline]
263 pub fn from_usize(v: usize) -> Self {
264 VarInt(v as u64)
265 }
266}
267
268impl From<u32> for VarInt {
269 #[inline]
270 fn from(v: u32) -> Self {
271 VarInt(v as u64)
272 }
273}