moq_lite/coding/
varint.rs

1// Based on quinn-proto
2// https://github.com/quinn-rs/quinn/blob/main/quinn-proto/src/varint.rs
3// Licensed via Apache 2.0 and MIT
4
5use std::convert::{TryFrom, TryInto};
6use std::fmt;
7
8use thiserror::Error;
9
10use super::{Decode, DecodeError, Encode};
11
12/// The number is too large to fit in a VarInt (62 bits).
13#[derive(Debug, Copy, Clone, Eq, PartialEq, Error)]
14#[error("value out of range")]
15pub struct BoundsExceeded;
16
17/// An integer less than 2^62
18///
19/// Values of this type are suitable for encoding as QUIC variable-length integer.
20/// It would be neat if we could express to Rust that the top two bits are available for use as enum
21/// discriminants
22#[derive(Debug, Default, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
23#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
24pub struct VarInt(u64);
25
26impl VarInt {
27	/// The largest possible value.
28	pub const MAX: Self = Self((1 << 62) - 1);
29
30	/// The smallest possible value.
31	pub const ZERO: Self = Self(0);
32
33	/// Construct a `VarInt` infallibly using the largest available type.
34	/// Larger values need to use `try_from` instead.
35	pub const fn from_u32(x: u32) -> Self {
36		Self(x as u64)
37	}
38
39	pub const fn from_u64(x: u64) -> Option<Self> {
40		if x <= Self::MAX.0 { Some(Self(x)) } else { None }
41	}
42
43	pub const fn from_u128(x: u128) -> Option<Self> {
44		if x <= Self::MAX.0 as u128 {
45			Some(Self(x as u64))
46		} else {
47			None
48		}
49	}
50
51	/// Extract the integer value
52	pub const fn into_inner(self) -> u64 {
53		self.0
54	}
55}
56
57impl From<VarInt> for u64 {
58	fn from(x: VarInt) -> Self {
59		x.0
60	}
61}
62
63impl From<VarInt> for usize {
64	fn from(x: VarInt) -> Self {
65		x.0 as usize
66	}
67}
68
69impl From<VarInt> for u128 {
70	fn from(x: VarInt) -> Self {
71		x.0 as u128
72	}
73}
74
75impl From<u8> for VarInt {
76	fn from(x: u8) -> Self {
77		Self(x.into())
78	}
79}
80
81impl From<u16> for VarInt {
82	fn from(x: u16) -> Self {
83		Self(x.into())
84	}
85}
86
87impl From<u32> for VarInt {
88	fn from(x: u32) -> Self {
89		Self(x.into())
90	}
91}
92
93impl TryFrom<u64> for VarInt {
94	type Error = BoundsExceeded;
95
96	/// Succeeds iff `x` < 2^62
97	fn try_from(x: u64) -> Result<Self, BoundsExceeded> {
98		let x = Self(x);
99		if x <= Self::MAX { Ok(x) } else { Err(BoundsExceeded) }
100	}
101}
102
103impl TryFrom<u128> for VarInt {
104	type Error = BoundsExceeded;
105
106	/// Succeeds iff `x` < 2^62
107	fn try_from(x: u128) -> Result<Self, BoundsExceeded> {
108		if x <= Self::MAX.into() {
109			Ok(Self(x as u64))
110		} else {
111			Err(BoundsExceeded)
112		}
113	}
114}
115
116impl TryFrom<usize> for VarInt {
117	type Error = BoundsExceeded;
118
119	/// Succeeds iff `x` < 2^62
120	fn try_from(x: usize) -> Result<Self, BoundsExceeded> {
121		Self::try_from(x as u64)
122	}
123}
124
125impl TryFrom<VarInt> for u32 {
126	type Error = BoundsExceeded;
127
128	/// Succeeds iff `x` < 2^32
129	fn try_from(x: VarInt) -> Result<Self, BoundsExceeded> {
130		if x.0 <= u32::MAX.into() {
131			Ok(x.0 as u32)
132		} else {
133			Err(BoundsExceeded)
134		}
135	}
136}
137
138impl TryFrom<VarInt> for u16 {
139	type Error = BoundsExceeded;
140
141	/// Succeeds iff `x` < 2^16
142	fn try_from(x: VarInt) -> Result<Self, BoundsExceeded> {
143		if x.0 <= u16::MAX.into() {
144			Ok(x.0 as u16)
145		} else {
146			Err(BoundsExceeded)
147		}
148	}
149}
150
151impl TryFrom<VarInt> for u8 {
152	type Error = BoundsExceeded;
153
154	/// Succeeds iff `x` < 2^8
155	fn try_from(x: VarInt) -> Result<Self, BoundsExceeded> {
156		if x.0 <= u8::MAX.into() {
157			Ok(x.0 as u8)
158		} else {
159			Err(BoundsExceeded)
160		}
161	}
162}
163
164impl fmt::Display for VarInt {
165	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
166		self.0.fmt(f)
167	}
168}
169
170impl<V> Decode<V> for VarInt {
171	/// Decode a varint from the given reader.
172	fn decode<R: bytes::Buf>(r: &mut R, _: V) -> Result<Self, DecodeError> {
173		if !r.has_remaining() {
174			return Err(DecodeError::Short);
175		}
176
177		let b = r.get_u8();
178		let tag = b >> 6;
179
180		let mut buf = [0u8; 8];
181		buf[0] = b & 0b0011_1111;
182
183		let x = match tag {
184			0b00 => u64::from(buf[0]),
185			0b01 => {
186				if !r.has_remaining() {
187					return Err(DecodeError::Short);
188				}
189				r.copy_to_slice(buf[1..2].as_mut());
190				u64::from(u16::from_be_bytes(buf[..2].try_into().unwrap()))
191			}
192			0b10 => {
193				if r.remaining() < 3 {
194					return Err(DecodeError::Short);
195				}
196				r.copy_to_slice(buf[1..4].as_mut());
197				u64::from(u32::from_be_bytes(buf[..4].try_into().unwrap()))
198			}
199			0b11 => {
200				if r.remaining() < 7 {
201					return Err(DecodeError::Short);
202				}
203				r.copy_to_slice(buf[1..8].as_mut());
204				u64::from_be_bytes(buf)
205			}
206			_ => unreachable!(),
207		};
208
209		Ok(Self(x))
210	}
211}
212
213impl<V> Encode<V> for VarInt {
214	/// Encode a varint to the given writer.
215	fn encode<W: bytes::BufMut>(&self, w: &mut W, _: V) {
216		if self.0 < (1u64 << 6) {
217			w.put_u8(self.0 as u8);
218		} else if self.0 < (1u64 << 14) {
219			w.put_u16((0b01 << 14) | self.0 as u16);
220		} else if self.0 < (1u64 << 30) {
221			w.put_u32((0b10 << 30) | self.0 as u32);
222		} else {
223			w.put_u64((0b11 << 62) | self.0);
224		}
225	}
226}
227
228impl<V> Encode<V> for u64 {
229	/// Encode a varint to the given writer.
230	fn encode<W: bytes::BufMut>(&self, w: &mut W, version: V) {
231		// TODO use VarInt everywhere instead of u64
232		let v = VarInt::try_from(*self).expect("u64 too large");
233		v.encode(w, version)
234	}
235}
236
237impl<V> Decode<V> for u64 {
238	fn decode<R: bytes::Buf>(r: &mut R, version: V) -> Result<Self, DecodeError> {
239		VarInt::decode(r, version).map(|v| v.into_inner())
240	}
241}
242
243impl<V> Encode<V> for usize {
244	/// Encode a varint to the given writer.
245	fn encode<W: bytes::BufMut>(&self, w: &mut W, version: V) {
246		// TODO use VarInt everywhere instead of usize
247		let v = VarInt::try_from(*self).expect("usize too large");
248		v.encode(w, version)
249	}
250}
251
252impl<V> Decode<V> for usize {
253	fn decode<R: bytes::Buf>(r: &mut R, version: V) -> Result<Self, DecodeError> {
254		VarInt::decode(r, version).map(|v| v.into_inner() as usize)
255	}
256}
257
258impl<V> Encode<V> for u32 {
259	fn encode<W: bytes::BufMut>(&self, w: &mut W, version: V) {
260		VarInt::from(*self).encode(w, version)
261	}
262}
263
264impl<V> Decode<V> for u32 {
265	fn decode<R: bytes::Buf>(r: &mut R, version: V) -> Result<Self, DecodeError> {
266		let v = VarInt::decode(r, version)?;
267		let v = v.try_into().map_err(|_| DecodeError::BoundsExceeded)?;
268		Ok(v)
269	}
270}