s2n_quic_core/varint/
mod.rs

1// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2// SPDX-License-Identifier: Apache-2.0
3
4use 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
16//= https://www.rfc-editor.org/rfc/rfc9000#section-16
17//# QUIC packets and frames commonly use a variable-length encoding for
18//# non-negative integer values.  This encoding ensures that smaller
19//# integer values need fewer bytes to encode.
20
21//# The QUIC variable-length integer encoding reserves the two most
22//# significant bits of the first byte to encode the base 2 logarithm of
23//# the integer encoding length in bytes.  The integer value is encoded
24//# on the remaining bits, in network byte order.
25
26pub 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// === API ===
40
41#[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    /// Returns a `VarInt` without validating the value is less than VarInt::MAX
90    ///
91    /// # Safety
92    ///
93    /// Callers need to ensure the value is less than or equal to VarInt::MAX
94    #[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    /// Re-encodes a replacement value where `self` was used as a placeholder.
164    #[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        // don't use the basic version to avoid overwriting things
172        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        // Bounds check is inherited from u64
393        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        // Bounds check is inherited from u64
404        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        // Bounds check is inherited from u64
413        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        // Bounds check is inherited from u64
422        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        // Bounds check is inherited from u64
488        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        // Bounds check is inherited from u64
499        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        // Bounds check is inherited from u64
508        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        // Bounds check is inherited from u64
517        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        // Bounds check is inherited from u64
528        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        // Bounds check is inherited from u64
539        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        // Bounds check is inherited from u64
548        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        // Bounds check is inherited from u64
557        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}