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