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