s2n_quic_core/varint/
mod.rs1use core::{fmt, ops::Deref};
5use s2n_codec::{decoder_value, Encoder, EncoderValue};
6
7#[cfg(any(test, feature = "generator"))]
8use bolero_generator::prelude::*;
9
10use crate::event::IntoEvent;
11
12mod table;
13#[cfg(test)]
14mod tests;
15
16pub const MAX_VARINT_VALUE: u64 = 4_611_686_018_427_387_903;
27
28#[derive(Debug)]
29pub struct VarIntError;
30
31impl fmt::Display for VarIntError {
32 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
33 write!(f, "varint range exceeded")
34 }
35}
36
37impl core::error::Error for VarIntError {}
38
39#[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq, PartialOrd, Ord)]
42#[cfg_attr(any(feature = "generator", test), derive(TypeGenerator))]
43pub struct VarInt(#[cfg_attr(any(feature = "generator", test), generator(Self::GENERATOR))] u64);
44
45#[cfg(any(feature = "generator", test))]
46impl bolero_generator::bounded::BoundedValue for VarInt {
47 fn gen_bounded<D: bolero_generator::Driver>(
48 driver: &mut D,
49 min: core::ops::Bound<&Self>,
50 max: core::ops::Bound<&Self>,
51 ) -> Option<Self> {
52 use core::ops::Bound;
53
54 let map = |v: Bound<&Self>| match v {
55 Bound::Excluded(v) => Bound::Excluded(v.0),
56 Bound::Included(v) => Bound::Included(v.0),
57 Bound::Unbounded => Bound::Unbounded,
58 };
59
60 let min = map(min);
61 let max = map(max);
62 let bounded = u64::gen_bounded(driver, min.as_ref(), max.as_ref())?;
63 VarInt::new(bounded).ok()
64 }
65}
66
67impl fmt::Display for VarInt {
68 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
69 self.0.fmt(f)
70 }
71}
72
73impl VarInt {
74 pub const MAX: Self = Self(MAX_VARINT_VALUE);
75
76 pub const ZERO: Self = Self(0);
77
78 #[cfg(any(feature = "generator", test))]
79 const GENERATOR: core::ops::RangeInclusive<u64> = 0..=MAX_VARINT_VALUE;
80
81 #[inline(always)]
82 pub fn new(v: u64) -> Result<Self, VarIntError> {
83 if v > MAX_VARINT_VALUE {
84 return Err(VarIntError);
85 }
86 Ok(Self(v))
87 }
88
89 #[inline(always)]
95 pub const unsafe fn new_unchecked(value: u64) -> Self {
96 Self(value)
97 }
98
99 #[inline(always)]
100 pub const fn from_u8(v: u8) -> Self {
101 Self(v as u64)
102 }
103
104 #[inline(always)]
105 pub const fn from_u16(v: u16) -> Self {
106 Self(v as u64)
107 }
108
109 #[inline(always)]
110 pub const fn from_u32(v: u32) -> Self {
111 Self(v as u64)
112 }
113
114 #[inline(always)]
115 pub const fn as_u64(self) -> u64 {
116 self.0
117 }
118
119 #[inline]
120 pub fn checked_add(self, value: Self) -> Option<Self> {
121 Self::new(self.0.checked_add(value.0)?).ok()
122 }
123
124 #[inline]
125 pub fn checked_add_usize(self, value: usize) -> Option<Self> {
126 let value = value.try_into().ok()?;
127 self.checked_add(value)
128 }
129
130 #[inline]
131 #[must_use]
132 pub fn saturating_add(self, value: Self) -> Self {
133 Self::new(self.0.saturating_add(value.0)).unwrap_or(Self::MAX)
134 }
135
136 #[inline]
137 pub fn checked_sub(self, value: Self) -> Option<Self> {
138 Some(Self(self.0.checked_sub(value.0)?))
139 }
140
141 #[inline]
142 #[must_use]
143 pub fn saturating_sub(self, value: Self) -> Self {
144 Self(self.0.saturating_sub(value.0))
145 }
146
147 #[inline]
148 pub fn checked_mul(self, value: Self) -> Option<Self> {
149 Self::new(self.0.checked_mul(value.0)?).ok()
150 }
151
152 #[inline]
153 #[must_use]
154 pub fn saturating_mul(self, value: Self) -> Self {
155 Self::new(self.0.saturating_mul(value.0)).unwrap_or(Self::MAX)
156 }
157
158 #[inline]
159 pub fn checked_div(self, value: Self) -> Option<Self> {
160 Some(Self(self.0.checked_div(value.0)?))
161 }
162
163 #[inline]
165 pub fn encode_updated<E: Encoder>(self, replacement: Self, encoder: &mut E) {
166 debug_assert!(
167 self.table_entry().len >= replacement.table_entry().len,
168 "the replacement encoding_size should not be greater than the previous value"
169 );
170
171 self.table_entry()
173 .format(replacement.0)
174 .encode_maybe_undersized(encoder)
175 }
176
177 #[inline(always)]
178 fn table_entry(self) -> table::Entry {
179 table::Entry::read(self.0)
180 }
181
182 #[inline(always)]
183 fn format(self) -> table::Formatted {
184 table::Formatted::new(self.0)
185 }
186}
187
188impl EncoderValue for VarInt {
189 #[inline(always)]
190 fn encode<E: Encoder>(&self, encoder: &mut E) {
191 self.format().encode(encoder);
192 }
193
194 #[inline(always)]
195 fn encoding_size(&self) -> usize {
196 self.format().encoding_size()
197 }
198
199 #[inline(always)]
200 fn encoding_size_for_encoder<E: Encoder>(&self, encoder: &E) -> usize {
201 self.format().encoding_size_for_encoder(encoder)
202 }
203}
204
205impl IntoEvent<u64> for VarInt {
206 #[inline]
207 fn into_event(self) -> u64 {
208 self.as_u64()
209 }
210}
211
212decoder_value!(
213 impl<'a> VarInt {
214 fn decode(buffer: Buffer) -> Result<Self> {
215 let header = buffer.peek_byte(0)?;
216
217 Ok(match (header >> 6) & 0b11 {
218 0b00 => {
219 let value = header & (2u8.pow(6) - 1);
220 let buffer = buffer.skip(1)?;
221 (Self(value.into()), buffer)
222 }
223 0b01 => {
224 let (value, buffer) = buffer.decode::<u16>()?;
225 let value = value & (2u16.pow(14) - 1);
226 (Self(value.into()), buffer)
227 }
228 0b10 => {
229 let (value, buffer) = buffer.decode::<u32>()?;
230 let value = value & (2u32.pow(30) - 1);
231 (Self(value.into()), buffer)
232 }
233 0b11 => {
234 let (value, buffer) = buffer.decode::<u64>()?;
235 let value = value & (2u64.pow(62) - 1);
236 (Self(value), buffer)
237 }
238 _ => unsafe { core::hint::unreachable_unchecked() },
239 })
240 }
241 }
242);
243
244impl AsRef<u64> for VarInt {
245 #[inline]
246 fn as_ref(&self) -> &u64 {
247 &self.0
248 }
249}
250
251impl Deref for VarInt {
252 type Target = u64;
253
254 #[inline]
255 fn deref(&self) -> &Self::Target {
256 &self.0
257 }
258}
259
260macro_rules! impl_from_lesser {
261 ($ty:ty) => {
262 impl From<$ty> for VarInt {
263 #[inline]
264 fn from(value: $ty) -> Self {
265 Self(value.into())
266 }
267 }
268
269 impl TryInto<$ty> for VarInt {
270 type Error = <$ty as TryFrom<u64>>::Error;
271
272 #[inline]
273 fn try_into(self) -> Result<$ty, Self::Error> {
274 self.0.try_into()
275 }
276 }
277 };
278}
279
280impl_from_lesser!(u8);
281impl_from_lesser!(u16);
282impl_from_lesser!(u32);
283
284impl From<VarInt> for u64 {
285 #[inline]
286 fn from(v: VarInt) -> u64 {
287 v.0
288 }
289}
290
291impl TryFrom<usize> for VarInt {
292 type Error = VarIntError;
293
294 #[inline]
295 fn try_from(value: usize) -> Result<Self, Self::Error> {
296 Self::new(value as u64)
297 }
298}
299
300impl TryInto<usize> for VarInt {
301 type Error = <usize as TryFrom<u64>>::Error;
302
303 #[inline]
304 fn try_into(self) -> Result<usize, Self::Error> {
305 self.0.try_into()
306 }
307}
308
309impl TryFrom<u64> for VarInt {
310 type Error = VarIntError;
311
312 #[inline]
313 fn try_from(value: u64) -> Result<Self, Self::Error> {
314 Self::new(value)
315 }
316}
317
318impl TryFrom<u128> for VarInt {
319 type Error = VarIntError;
320
321 #[inline]
322 fn try_from(value: u128) -> Result<Self, Self::Error> {
323 if value > MAX_VARINT_VALUE as u128 {
324 Err(VarIntError)
325 } else {
326 Ok(Self(value as u64))
327 }
328 }
329}
330
331impl core::ops::Add for VarInt {
332 type Output = Self;
333
334 #[inline]
335 #[track_caller]
336 fn add(self, rhs: Self) -> Self {
337 if cfg!(debug_assertions) {
338 self.checked_add(rhs).expect("VarInt overflow occurred")
339 } else {
340 Self(self.0 + rhs.0)
341 }
342 }
343}
344
345impl core::ops::Add<usize> for VarInt {
346 type Output = Self;
347
348 #[inline]
349 #[track_caller]
350 fn add(self, rhs: usize) -> Self {
351 if cfg!(debug_assertions) {
352 self.checked_add(VarInt::new(rhs as u64).expect("VarInt overflow occurred"))
353 .expect("VarInt overflow occurred")
354 } else {
355 Self(self.0 + rhs as u64)
356 }
357 }
358}
359
360impl core::ops::AddAssign<Self> for VarInt {
361 #[inline]
362 #[track_caller]
363 fn add_assign(&mut self, rhs: Self) {
364 if cfg!(debug_assertions) {
365 *self = self.checked_add(rhs).expect("VarInt overflow occurred")
366 } else {
367 self.0 += rhs.0
368 }
369 }
370}
371
372impl core::ops::AddAssign<usize> for VarInt {
373 #[inline]
374 #[track_caller]
375 fn add_assign(&mut self, rhs: usize) {
376 if cfg!(debug_assertions) {
377 *self = self
378 .checked_add(VarInt::new(rhs as u64).expect("VarInt overflow occurred"))
379 .expect("VarInt overflow occurred")
380 } else {
381 self.0 += rhs as u64
382 }
383 }
384}
385
386impl core::ops::Sub for VarInt {
387 type Output = Self;
388
389 #[inline]
390 #[track_caller]
391 fn sub(self, rhs: Self) -> Self {
392 Self(self.0 - rhs.0)
394 }
395}
396
397impl core::ops::Sub<usize> for VarInt {
398 type Output = Self;
399
400 #[inline]
401 #[track_caller]
402 fn sub(self, rhs: usize) -> Self {
403 Self(self.0 - rhs as u64)
405 }
406}
407
408impl core::ops::SubAssign<Self> for VarInt {
409 #[inline]
410 #[track_caller]
411 fn sub_assign(&mut self, rhs: Self) {
412 self.0 -= rhs.0
414 }
415}
416
417impl core::ops::SubAssign<usize> for VarInt {
418 #[inline]
419 #[track_caller]
420 fn sub_assign(&mut self, rhs: usize) {
421 self.0 -= rhs as u64
423 }
424}
425
426impl core::ops::Mul for VarInt {
427 type Output = Self;
428
429 #[inline]
430 #[track_caller]
431 fn mul(self, rhs: Self) -> Self {
432 if cfg!(debug_assertions) {
433 self.checked_mul(rhs).expect("VarInt overflow occurred")
434 } else {
435 Self(self.0 * rhs.0)
436 }
437 }
438}
439
440impl core::ops::Mul<usize> for VarInt {
441 type Output = Self;
442
443 #[inline]
444 #[track_caller]
445 fn mul(self, rhs: usize) -> Self {
446 if cfg!(debug_assertions) {
447 self.checked_mul(VarInt::new(rhs as u64).expect("VarInt overflow occurred"))
448 .expect("VarInt overflow occurred")
449 } else {
450 Self(self.0 * rhs as u64)
451 }
452 }
453}
454
455impl core::ops::MulAssign<Self> for VarInt {
456 #[inline]
457 #[track_caller]
458 fn mul_assign(&mut self, rhs: Self) {
459 if cfg!(debug_assertions) {
460 *self = self.checked_mul(rhs).expect("VarInt overflow occurred")
461 } else {
462 self.0 *= rhs.0
463 }
464 }
465}
466
467impl core::ops::MulAssign<usize> for VarInt {
468 #[inline]
469 #[track_caller]
470 fn mul_assign(&mut self, rhs: usize) {
471 if cfg!(debug_assertions) {
472 *self = self
473 .checked_mul(VarInt::new(rhs as u64).expect("VarInt overflow occurred"))
474 .expect("VarInt overflow occurred")
475 } else {
476 self.0 *= rhs as u64
477 }
478 }
479}
480
481impl core::ops::Div for VarInt {
482 type Output = Self;
483
484 #[inline]
485 #[track_caller]
486 fn div(self, rhs: Self) -> Self {
487 Self(self.0 / rhs.0)
489 }
490}
491
492impl core::ops::Div<usize> for VarInt {
493 type Output = Self;
494
495 #[inline]
496 #[track_caller]
497 fn div(self, rhs: usize) -> Self {
498 Self(self.0 / rhs as u64)
500 }
501}
502
503impl core::ops::DivAssign<Self> for VarInt {
504 #[inline]
505 #[track_caller]
506 fn div_assign(&mut self, rhs: Self) {
507 self.0 /= rhs.0
509 }
510}
511
512impl core::ops::DivAssign<usize> for VarInt {
513 #[inline]
514 #[track_caller]
515 fn div_assign(&mut self, rhs: usize) {
516 self.0 /= rhs as u64
518 }
519}
520
521impl core::ops::Rem for VarInt {
522 type Output = Self;
523
524 #[inline]
525 #[track_caller]
526 fn rem(self, rhs: Self) -> Self {
527 Self(self.0.rem(rhs.0))
529 }
530}
531
532impl core::ops::Rem<usize> for VarInt {
533 type Output = Self;
534
535 #[inline]
536 #[track_caller]
537 fn rem(self, rhs: usize) -> Self {
538 Self(self.0.rem(rhs as u64))
540 }
541}
542
543impl core::ops::RemAssign<Self> for VarInt {
544 #[inline]
545 #[track_caller]
546 fn rem_assign(&mut self, rhs: Self) {
547 self.0 %= rhs.0
549 }
550}
551
552impl core::ops::RemAssign<usize> for VarInt {
553 #[inline]
554 #[track_caller]
555 fn rem_assign(&mut self, rhs: usize) {
556 self.0 %= rhs as u64
558 }
559}
560
561impl PartialEq<u64> for VarInt {
562 #[inline]
563 fn eq(&self, other: &u64) -> bool {
564 self.0.eq(other)
565 }
566}
567
568impl PartialEq<usize> for VarInt {
569 #[inline]
570 fn eq(&self, other: &usize) -> bool {
571 self.0.eq(&(*other as u64))
572 }
573}
574
575impl PartialOrd<u64> for VarInt {
576 #[inline]
577 fn partial_cmp(&self, other: &u64) -> Option<core::cmp::Ordering> {
578 self.0.partial_cmp(other)
579 }
580}
581
582impl PartialOrd<usize> for VarInt {
583 #[inline]
584 fn partial_cmp(&self, other: &usize) -> Option<core::cmp::Ordering> {
585 self.0.partial_cmp(&(*other as u64))
586 }
587}