Skip to main content

moq_net/coding/
decode.rs

1use std::{borrow::Cow, string::FromUtf8Error};
2use thiserror::Error;
3
4/// Read the from the buffer using the given version.
5///
6/// If [DecodeError::Short] is returned, the caller should try again with more data.
7pub trait Decode<V>: Sized {
8	/// Decode the value from the given buffer.
9	fn decode<B: bytes::Buf>(buf: &mut B, version: V) -> Result<Self, DecodeError>;
10}
11
12/// A decode error.
13#[derive(Error, Debug, Clone)]
14#[non_exhaustive]
15pub enum DecodeError {
16	/// The buffer ran out mid-value. Retry once more bytes arrive.
17	#[error("short buffer")]
18	Short,
19
20	/// The value claims more bytes than the enclosing message allows.
21	#[error("long buffer")]
22	Long,
23
24	/// A string field was not valid UTF-8.
25	#[error("invalid string")]
26	InvalidString(#[from] FromUtf8Error),
27
28	/// The message type ID is unknown for the negotiated version.
29	#[error("invalid message: {0:?}")]
30	InvalidMessage(u64),
31
32	/// A SUBSCRIBE start/end location is malformed or out of order.
33	#[error("invalid subscribe location")]
34	InvalidSubscribeLocation,
35
36	/// A field held a value outside its permitted range.
37	#[error("invalid value")]
38	InvalidValue,
39
40	/// A repeated field exceeded the count this implementation accepts.
41	#[error("too many")]
42	TooMany,
43
44	/// An integer was too large for the QUIC varint range.
45	#[error("bounds exceeded")]
46	BoundsExceeded,
47
48	/// More data followed where the message was required to end.
49	#[error("expected end")]
50	ExpectedEnd,
51
52	/// A length-prefixed message exceeded the receiver's byte limit.
53	#[error("message too large: {size} bytes exceeds {max} byte limit")]
54	MessageTooLarge {
55		/// The byte length declared by the peer.
56		size: usize,
57		/// The largest message this receiver accepts.
58		max: usize,
59	},
60
61	/// The stream ended where a payload was required.
62	#[error("expected data")]
63	ExpectedData,
64
65	/// A parameter or field appeared more than once.
66	#[error("duplicate")]
67	Duplicate,
68
69	/// A required parameter or field was absent.
70	#[error("missing")]
71	Missing,
72
73	/// The value is well-formed but this implementation does not handle it.
74	#[error("unsupported")]
75	Unsupported,
76
77	/// Bytes remained after the value was fully decoded.
78	#[error("trailing bytes")]
79	TrailingBytes,
80
81	/// The field does not exist in the negotiated protocol version.
82	#[error("unsupported version")]
83	Version,
84}
85
86impl DecodeError {
87	/// A complete frame cannot be extended by reading more stream bytes.
88	pub(crate) fn complete(self) -> Self {
89		match self {
90			Self::Short => Self::InvalidValue,
91			other => other,
92		}
93	}
94}
95
96impl<V> Decode<V> for bool {
97	fn decode<R: bytes::Buf>(r: &mut R, version: V) -> Result<Self, DecodeError> {
98		match u8::decode(r, version)? {
99			0 => Ok(false),
100			1 => Ok(true),
101			_ => Err(DecodeError::InvalidValue),
102		}
103	}
104}
105
106impl<V> Decode<V> for u8 {
107	fn decode<R: bytes::Buf>(r: &mut R, _: V) -> Result<Self, DecodeError> {
108		match r.has_remaining() {
109			true => Ok(r.get_u8()),
110			false => Err(DecodeError::Short),
111		}
112	}
113}
114
115impl<V> Decode<V> for u16 {
116	fn decode<R: bytes::Buf>(r: &mut R, _: V) -> Result<Self, DecodeError> {
117		match r.remaining() >= 2 {
118			true => Ok(r.get_u16()),
119			false => Err(DecodeError::Short),
120		}
121	}
122}
123
124impl<V: Copy> Decode<V> for String
125where
126	usize: Decode<V>,
127{
128	/// Decode a string with a varint length prefix.
129	fn decode<R: bytes::Buf>(r: &mut R, version: V) -> Result<Self, DecodeError> {
130		let v = Vec::<u8>::decode(r, version)?;
131		let str = String::from_utf8(v)?;
132
133		Ok(str)
134	}
135}
136
137impl<V: Copy> Decode<V> for Vec<u8>
138where
139	usize: Decode<V>,
140{
141	fn decode<B: bytes::Buf>(buf: &mut B, version: V) -> Result<Self, DecodeError> {
142		let size = usize::decode(buf, version)?;
143
144		if buf.remaining() < size {
145			return Err(DecodeError::Short);
146		}
147
148		let bytes = buf.copy_to_bytes(size);
149		Ok(bytes.to_vec())
150	}
151}
152
153impl<V> Decode<V> for i8 {
154	fn decode<R: bytes::Buf>(r: &mut R, _: V) -> Result<Self, DecodeError> {
155		if !r.has_remaining() {
156			return Err(DecodeError::Short);
157		}
158
159		// This is not the usual way of encoding negative numbers.
160		// i8 doesn't exist in the draft, but we use it instead of u8 for priority.
161		// A default of 0 is more ergonomic for the user than a default of 128.
162		Ok(((r.get_u8() as i16) - 128) as i8)
163	}
164}
165
166impl<V: Copy> Decode<V> for bytes::Bytes
167where
168	usize: Decode<V>,
169{
170	fn decode<R: bytes::Buf>(r: &mut R, version: V) -> Result<Self, DecodeError> {
171		let len = usize::decode(r, version)?;
172		if r.remaining() < len {
173			return Err(DecodeError::Short);
174		}
175		let bytes = r.copy_to_bytes(len);
176		Ok(bytes)
177	}
178}
179
180// TODO Support borrowed strings.
181impl<V: Copy> Decode<V> for Cow<'_, str>
182where
183	usize: Decode<V>,
184{
185	fn decode<R: bytes::Buf>(r: &mut R, version: V) -> Result<Self, DecodeError> {
186		let s = String::decode(r, version)?;
187		Ok(Cow::Owned(s))
188	}
189}
190
191impl<V: Copy> Decode<V> for Option<u64>
192where
193	u64: Decode<V>,
194{
195	fn decode<R: bytes::Buf>(r: &mut R, version: V) -> Result<Self, DecodeError> {
196		match u64::decode(r, version)? {
197			0 => Ok(None),
198			value => Ok(Some(value - 1)),
199		}
200	}
201}
202
203impl<V: Copy> Decode<V> for std::time::Duration
204where
205	u64: Decode<V>,
206{
207	fn decode<R: bytes::Buf>(r: &mut R, version: V) -> Result<Self, DecodeError> {
208		let value = u64::decode(r, version)?;
209		Ok(Self::from_millis(value))
210	}
211}