Skip to main content

moq_net/coding/
encode.rs

1use std::{borrow::Cow, sync::Arc};
2
3use bytes::{Bytes, BytesMut};
4
5use super::BoundsExceeded;
6
7/// An error that occurs during encoding.
8#[derive(thiserror::Error, Debug, Clone)]
9#[non_exhaustive]
10pub enum EncodeError {
11	/// An integer was too large for the QUIC varint range.
12	#[error("bounds exceeded")]
13	BoundsExceeded,
14	/// The payload exceeds the maximum size the wire format can express.
15	#[error("too large")]
16	TooLarge,
17	/// The destination buffer had no room for the value.
18	#[error("short buffer")]
19	Short,
20	/// The message cannot be encoded from the current session state.
21	#[error("invalid state")]
22	InvalidState,
23	/// A repeated field exceeded the count the wire format permits.
24	#[error("too many")]
25	TooMany,
26	/// The field does not exist in the negotiated protocol version.
27	#[error("unsupported version")]
28	Version,
29	/// The value is well-formed but this implementation cannot put it on the wire.
30	#[error("unsupported")]
31	Unsupported,
32}
33
34impl From<BoundsExceeded> for EncodeError {
35	fn from(_: BoundsExceeded) -> Self {
36		Self::BoundsExceeded
37	}
38}
39
40/// Check that the writer has enough remaining capacity.
41fn check_remaining(w: &impl bytes::BufMut, needed: usize) -> Result<(), EncodeError> {
42	if w.remaining_mut() < needed {
43		return Err(EncodeError::Short);
44	}
45	Ok(())
46}
47
48/// Write the value to the buffer using the given version.
49pub trait Encode<V>: Sized {
50	/// Encode the value to the given writer.
51	fn encode<W: bytes::BufMut>(&self, w: &mut W, version: V) -> Result<(), EncodeError>;
52
53	/// The control metric class of this value, or `None` for selectors and media headers.
54	fn control(&self, _version: V) -> Option<crate::stats::Control> {
55		None
56	}
57
58	/// Encode the value into a [Bytes] buffer.
59	///
60	/// NOTE: This will allocate.
61	fn encode_bytes(&self, v: V) -> Result<Bytes, EncodeError> {
62		let mut buf = BytesMut::new();
63		self.encode(&mut buf, v)?;
64		Ok(buf.freeze())
65	}
66}
67
68impl<V> Encode<V> for bool {
69	fn encode<W: bytes::BufMut>(&self, w: &mut W, _: V) -> Result<(), EncodeError> {
70		check_remaining(&*w, 1)?;
71		w.put_u8(*self as u8);
72		Ok(())
73	}
74}
75
76impl<V> Encode<V> for u8 {
77	fn encode<W: bytes::BufMut>(&self, w: &mut W, _: V) -> Result<(), EncodeError> {
78		check_remaining(&*w, 1)?;
79		w.put_u8(*self);
80		Ok(())
81	}
82}
83
84impl<V> Encode<V> for u16 {
85	fn encode<W: bytes::BufMut>(&self, w: &mut W, _: V) -> Result<(), EncodeError> {
86		check_remaining(&*w, 2)?;
87		w.put_u16(*self);
88		Ok(())
89	}
90}
91
92impl<V: Copy> Encode<V> for String
93where
94	usize: Encode<V>,
95{
96	fn encode<W: bytes::BufMut>(&self, w: &mut W, version: V) -> Result<(), EncodeError> {
97		self.as_str().encode(w, version)
98	}
99}
100
101impl<V: Copy> Encode<V> for &str
102where
103	usize: Encode<V>,
104{
105	fn encode<W: bytes::BufMut>(&self, w: &mut W, version: V) -> Result<(), EncodeError> {
106		self.len().encode(w, version)?;
107		check_remaining(&*w, self.len())?;
108		w.put(self.as_bytes());
109		Ok(())
110	}
111}
112
113impl<V> Encode<V> for i8 {
114	fn encode<W: bytes::BufMut>(&self, w: &mut W, _: V) -> Result<(), EncodeError> {
115		// This is not the usual way of encoding negative numbers.
116		// i8 doesn't exist in the draft, but we use it instead of u8 for priority.
117		// A default of 0 is more ergonomic for the user than a default of 128.
118		check_remaining(&*w, 1)?;
119		w.put_u8(((*self as i16) + 128) as u8);
120		Ok(())
121	}
122}
123
124impl<V: Copy, T: Encode<V>> Encode<V> for &[T]
125where
126	usize: Encode<V>,
127{
128	fn encode<W: bytes::BufMut>(&self, w: &mut W, version: V) -> Result<(), EncodeError> {
129		self.len().encode(w, version)?;
130		for item in self.iter() {
131			item.encode(w, version)?;
132		}
133		Ok(())
134	}
135}
136
137impl<V: Copy> Encode<V> for Vec<u8>
138where
139	usize: Encode<V>,
140{
141	fn encode<W: bytes::BufMut>(&self, w: &mut W, version: V) -> Result<(), EncodeError> {
142		self.len().encode(w, version)?;
143		check_remaining(&*w, self.len())?;
144		w.put_slice(self);
145		Ok(())
146	}
147}
148
149impl<V: Copy> Encode<V> for bytes::Bytes
150where
151	usize: Encode<V>,
152{
153	fn encode<W: bytes::BufMut>(&self, w: &mut W, version: V) -> Result<(), EncodeError> {
154		self.len().encode(w, version)?;
155		check_remaining(&*w, self.len())?;
156		w.put_slice(self);
157		Ok(())
158	}
159}
160
161impl<T: Encode<V>, V> Encode<V> for Arc<T> {
162	fn encode<W: bytes::BufMut>(&self, w: &mut W, version: V) -> Result<(), EncodeError> {
163		(**self).encode(w, version)
164	}
165}
166
167impl<V: Copy> Encode<V> for Cow<'_, str>
168where
169	usize: Encode<V>,
170{
171	fn encode<W: bytes::BufMut>(&self, w: &mut W, version: V) -> Result<(), EncodeError> {
172		self.len().encode(w, version)?;
173		check_remaining(&*w, self.len())?;
174		w.put(self.as_bytes());
175		Ok(())
176	}
177}
178
179impl<V: Copy> Encode<V> for Option<u64>
180where
181	u64: Encode<V>,
182{
183	fn encode<W: bytes::BufMut>(&self, w: &mut W, version: V) -> Result<(), EncodeError> {
184		match self {
185			Some(value) => value.checked_add(1).ok_or(EncodeError::TooLarge)?.encode(w, version),
186			None => 0u64.encode(w, version),
187		}
188	}
189}
190
191impl<V: Copy> Encode<V> for std::time::Duration
192where
193	super::VarInt: Encode<V>,
194{
195	/// Milliseconds as a QUIC varint. Sub-millisecond precision is truncated
196	/// (`Duration::as_millis`). Fails with [`EncodeError::BoundsExceeded`] if the
197	/// millisecond count exceeds `2^62 - 1`.
198	fn encode<W: bytes::BufMut>(&self, w: &mut W, version: V) -> Result<(), EncodeError> {
199		let ms = super::VarInt::try_from(self.as_millis())?;
200		ms.encode(w, version)
201	}
202}