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