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
37#[cfg(feature = "std")]
38impl std::error::Error for VarIntError {}
39
40#[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 #[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 #[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 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 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 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 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 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 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 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 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 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 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 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 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 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}