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