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