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}
30
31impl From<BoundsExceeded> for EncodeError {
32	fn from(_: BoundsExceeded) -> Self {
33		Self::BoundsExceeded
34	}
35}
36
37/// Check that the writer has enough remaining capacity.
38fn check_remaining(w: &impl bytes::BufMut, needed: usize) -> Result<(), EncodeError> {
39	if w.remaining_mut() < needed {
40		return Err(EncodeError::Short);
41	}
42	Ok(())
43}
44
45/// Write the value to the buffer using the given version.
46pub trait Encode<V>: Sized {
47	/// Encode the value to the given writer.
48	fn encode<W: bytes::BufMut>(&self, w: &mut W, version: V) -> Result<(), EncodeError>;
49
50	/// Encode the value into a [Bytes] buffer.
51	///
52	/// NOTE: This will allocate.
53	fn encode_bytes(&self, v: V) -> Result<Bytes, EncodeError> {
54		let mut buf = BytesMut::new();
55		self.encode(&mut buf, v)?;
56		Ok(buf.freeze())
57	}
58}
59
60impl<V> Encode<V> for bool {
61	fn encode<W: bytes::BufMut>(&self, w: &mut W, _: V) -> Result<(), EncodeError> {
62		check_remaining(&*w, 1)?;
63		w.put_u8(*self as u8);
64		Ok(())
65	}
66}
67
68impl<V> Encode<V> for u8 {
69	fn encode<W: bytes::BufMut>(&self, w: &mut W, _: V) -> Result<(), EncodeError> {
70		check_remaining(&*w, 1)?;
71		w.put_u8(*self);
72		Ok(())
73	}
74}
75
76impl<V> Encode<V> for u16 {
77	fn encode<W: bytes::BufMut>(&self, w: &mut W, _: V) -> Result<(), EncodeError> {
78		check_remaining(&*w, 2)?;
79		w.put_u16(*self);
80		Ok(())
81	}
82}
83
84impl<V: Copy> Encode<V> for String
85where
86	usize: Encode<V>,
87{
88	fn encode<W: bytes::BufMut>(&self, w: &mut W, version: V) -> Result<(), EncodeError> {
89		self.as_str().encode(w, version)
90	}
91}
92
93impl<V: Copy> Encode<V> for &str
94where
95	usize: Encode<V>,
96{
97	fn encode<W: bytes::BufMut>(&self, w: &mut W, version: V) -> Result<(), EncodeError> {
98		self.len().encode(w, version)?;
99		check_remaining(&*w, self.len())?;
100		w.put(self.as_bytes());
101		Ok(())
102	}
103}
104
105impl<V> Encode<V> for i8 {
106	fn encode<W: bytes::BufMut>(&self, w: &mut W, _: V) -> Result<(), EncodeError> {
107		// This is not the usual way of encoding negative numbers.
108		// i8 doesn't exist in the draft, but we use it instead of u8 for priority.
109		// A default of 0 is more ergonomic for the user than a default of 128.
110		check_remaining(&*w, 1)?;
111		w.put_u8(((*self as i16) + 128) as u8);
112		Ok(())
113	}
114}
115
116impl<V: Copy, T: Encode<V>> Encode<V> for &[T]
117where
118	usize: Encode<V>,
119{
120	fn encode<W: bytes::BufMut>(&self, w: &mut W, version: V) -> Result<(), EncodeError> {
121		self.len().encode(w, version)?;
122		for item in self.iter() {
123			item.encode(w, version)?;
124		}
125		Ok(())
126	}
127}
128
129impl<V: Copy> Encode<V> for Vec<u8>
130where
131	usize: Encode<V>,
132{
133	fn encode<W: bytes::BufMut>(&self, w: &mut W, version: V) -> Result<(), EncodeError> {
134		self.len().encode(w, version)?;
135		check_remaining(&*w, self.len())?;
136		w.put_slice(self);
137		Ok(())
138	}
139}
140
141impl<V: Copy> Encode<V> for bytes::Bytes
142where
143	usize: Encode<V>,
144{
145	fn encode<W: bytes::BufMut>(&self, w: &mut W, version: V) -> Result<(), EncodeError> {
146		self.len().encode(w, version)?;
147		check_remaining(&*w, self.len())?;
148		w.put_slice(self);
149		Ok(())
150	}
151}
152
153impl<T: Encode<V>, V> Encode<V> for Arc<T> {
154	fn encode<W: bytes::BufMut>(&self, w: &mut W, version: V) -> Result<(), EncodeError> {
155		(**self).encode(w, version)
156	}
157}
158
159impl<V: Copy> Encode<V> for Cow<'_, str>
160where
161	usize: Encode<V>,
162{
163	fn encode<W: bytes::BufMut>(&self, w: &mut W, version: V) -> Result<(), EncodeError> {
164		self.len().encode(w, version)?;
165		check_remaining(&*w, self.len())?;
166		w.put(self.as_bytes());
167		Ok(())
168	}
169}
170
171impl<V: Copy> Encode<V> for Option<u64>
172where
173	u64: Encode<V>,
174{
175	fn encode<W: bytes::BufMut>(&self, w: &mut W, version: V) -> Result<(), EncodeError> {
176		match self {
177			Some(value) => value.checked_add(1).ok_or(EncodeError::TooLarge)?.encode(w, version),
178			None => 0u64.encode(w, version),
179		}
180	}
181}
182
183impl<V: Copy> Encode<V> for std::time::Duration
184where
185	super::VarInt: Encode<V>,
186{
187	fn encode<W: bytes::BufMut>(&self, w: &mut W, version: V) -> Result<(), EncodeError> {
188		let ms = super::VarInt::try_from(self.as_millis())?;
189		ms.encode(w, version)
190	}
191}