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<V> Decode<V> for bool {
87	fn decode<R: bytes::Buf>(r: &mut R, version: V) -> Result<Self, DecodeError> {
88		match u8::decode(r, version)? {
89			0 => Ok(false),
90			1 => Ok(true),
91			_ => Err(DecodeError::InvalidValue),
92		}
93	}
94}
95
96impl<V> Decode<V> for u8 {
97	fn decode<R: bytes::Buf>(r: &mut R, _: V) -> Result<Self, DecodeError> {
98		match r.has_remaining() {
99			true => Ok(r.get_u8()),
100			false => Err(DecodeError::Short),
101		}
102	}
103}
104
105impl<V> Decode<V> for u16 {
106	fn decode<R: bytes::Buf>(r: &mut R, _: V) -> Result<Self, DecodeError> {
107		match r.remaining() >= 2 {
108			true => Ok(r.get_u16()),
109			false => Err(DecodeError::Short),
110		}
111	}
112}
113
114impl<V: Copy> Decode<V> for String
115where
116	usize: Decode<V>,
117{
118	/// Decode a string with a varint length prefix.
119	fn decode<R: bytes::Buf>(r: &mut R, version: V) -> Result<Self, DecodeError> {
120		let v = Vec::<u8>::decode(r, version)?;
121		let str = String::from_utf8(v)?;
122
123		Ok(str)
124	}
125}
126
127impl<V: Copy> Decode<V> for Vec<u8>
128where
129	usize: Decode<V>,
130{
131	fn decode<B: bytes::Buf>(buf: &mut B, version: V) -> Result<Self, DecodeError> {
132		let size = usize::decode(buf, version)?;
133
134		if buf.remaining() < size {
135			return Err(DecodeError::Short);
136		}
137
138		let bytes = buf.copy_to_bytes(size);
139		Ok(bytes.to_vec())
140	}
141}
142
143impl<V> Decode<V> for i8 {
144	fn decode<R: bytes::Buf>(r: &mut R, _: V) -> Result<Self, DecodeError> {
145		if !r.has_remaining() {
146			return Err(DecodeError::Short);
147		}
148
149		// This is not the usual way of encoding negative numbers.
150		// i8 doesn't exist in the draft, but we use it instead of u8 for priority.
151		// A default of 0 is more ergonomic for the user than a default of 128.
152		Ok(((r.get_u8() as i16) - 128) as i8)
153	}
154}
155
156impl<V: Copy> Decode<V> for bytes::Bytes
157where
158	usize: Decode<V>,
159{
160	fn decode<R: bytes::Buf>(r: &mut R, version: V) -> Result<Self, DecodeError> {
161		let len = usize::decode(r, version)?;
162		if r.remaining() < len {
163			return Err(DecodeError::Short);
164		}
165		let bytes = r.copy_to_bytes(len);
166		Ok(bytes)
167	}
168}
169
170// TODO Support borrowed strings.
171impl<V: Copy> Decode<V> for Cow<'_, str>
172where
173	usize: Decode<V>,
174{
175	fn decode<R: bytes::Buf>(r: &mut R, version: V) -> Result<Self, DecodeError> {
176		let s = String::decode(r, version)?;
177		Ok(Cow::Owned(s))
178	}
179}
180
181impl<V: Copy> Decode<V> for Option<u64>
182where
183	u64: Decode<V>,
184{
185	fn decode<R: bytes::Buf>(r: &mut R, version: V) -> Result<Self, DecodeError> {
186		match u64::decode(r, version)? {
187			0 => Ok(None),
188			value => Ok(Some(value - 1)),
189		}
190	}
191}
192
193impl<V: Copy> Decode<V> for std::time::Duration
194where
195	u64: Decode<V>,
196{
197	fn decode<R: bytes::Buf>(r: &mut R, version: V) -> Result<Self, DecodeError> {
198		let value = u64::decode(r, version)?;
199		Ok(Self::from_millis(value))
200	}
201}