Skip to main content

moq_lite/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	#[error("short buffer")]
17	Short,
18
19	#[error("long buffer")]
20	Long,
21
22	#[error("invalid string")]
23	InvalidString(#[from] FromUtf8Error),
24
25	#[error("invalid message: {0:?}")]
26	InvalidMessage(u64),
27
28	#[error("invalid subscribe location")]
29	InvalidSubscribeLocation,
30
31	#[error("invalid value")]
32	InvalidValue,
33
34	#[error("too many")]
35	TooMany,
36
37	#[error("bounds exceeded")]
38	BoundsExceeded,
39
40	#[error("expected end")]
41	ExpectedEnd,
42
43	#[error("expected data")]
44	ExpectedData,
45
46	#[error("duplicate")]
47	Duplicate,
48
49	#[error("missing")]
50	Missing,
51
52	#[error("unsupported")]
53	Unsupported,
54
55	#[error("trailing bytes")]
56	TrailingBytes,
57
58	#[error("unsupported version")]
59	Version,
60}
61
62impl<V> Decode<V> for bool {
63	fn decode<R: bytes::Buf>(r: &mut R, version: V) -> Result<Self, DecodeError> {
64		match u8::decode(r, version)? {
65			0 => Ok(false),
66			1 => Ok(true),
67			_ => Err(DecodeError::InvalidValue),
68		}
69	}
70}
71
72impl<V> Decode<V> for u8 {
73	fn decode<R: bytes::Buf>(r: &mut R, _: V) -> Result<Self, DecodeError> {
74		match r.has_remaining() {
75			true => Ok(r.get_u8()),
76			false => Err(DecodeError::Short),
77		}
78	}
79}
80
81impl<V> Decode<V> for u16 {
82	fn decode<R: bytes::Buf>(r: &mut R, _: V) -> Result<Self, DecodeError> {
83		match r.remaining() >= 2 {
84			true => Ok(r.get_u16()),
85			false => Err(DecodeError::Short),
86		}
87	}
88}
89
90impl<V: Copy> Decode<V> for String
91where
92	usize: Decode<V>,
93{
94	/// Decode a string with a varint length prefix.
95	fn decode<R: bytes::Buf>(r: &mut R, version: V) -> Result<Self, DecodeError> {
96		let v = Vec::<u8>::decode(r, version)?;
97		let str = String::from_utf8(v)?;
98
99		Ok(str)
100	}
101}
102
103impl<V: Copy> Decode<V> for Vec<u8>
104where
105	usize: Decode<V>,
106{
107	fn decode<B: bytes::Buf>(buf: &mut B, version: V) -> Result<Self, DecodeError> {
108		let size = usize::decode(buf, version)?;
109
110		if buf.remaining() < size {
111			return Err(DecodeError::Short);
112		}
113
114		let bytes = buf.copy_to_bytes(size);
115		Ok(bytes.to_vec())
116	}
117}
118
119impl<V> Decode<V> for i8 {
120	fn decode<R: bytes::Buf>(r: &mut R, _: V) -> Result<Self, DecodeError> {
121		if !r.has_remaining() {
122			return Err(DecodeError::Short);
123		}
124
125		// This is not the usual way of encoding negative numbers.
126		// i8 doesn't exist in the draft, but we use it instead of u8 for priority.
127		// A default of 0 is more ergonomic for the user than a default of 128.
128		Ok(((r.get_u8() as i16) - 128) as i8)
129	}
130}
131
132impl<V: Copy> Decode<V> for bytes::Bytes
133where
134	usize: Decode<V>,
135{
136	fn decode<R: bytes::Buf>(r: &mut R, version: V) -> Result<Self, DecodeError> {
137		let len = usize::decode(r, version)?;
138		if r.remaining() < len {
139			return Err(DecodeError::Short);
140		}
141		let bytes = r.copy_to_bytes(len);
142		Ok(bytes)
143	}
144}
145
146// TODO Support borrowed strings.
147impl<V: Copy> Decode<V> for Cow<'_, str>
148where
149	usize: Decode<V>,
150{
151	fn decode<R: bytes::Buf>(r: &mut R, version: V) -> Result<Self, DecodeError> {
152		let s = String::decode(r, version)?;
153		Ok(Cow::Owned(s))
154	}
155}
156
157impl<V: Copy> Decode<V> for Option<u64>
158where
159	u64: Decode<V>,
160{
161	fn decode<R: bytes::Buf>(r: &mut R, version: V) -> Result<Self, DecodeError> {
162		match u64::decode(r, version)? {
163			0 => Ok(None),
164			value => Ok(Some(value - 1)),
165		}
166	}
167}
168
169impl<V: Copy> Decode<V> for std::time::Duration
170where
171	u64: Decode<V>,
172{
173	fn decode<R: bytes::Buf>(r: &mut R, version: V) -> Result<Self, DecodeError> {
174		let value = u64::decode(r, version)?;
175		Ok(Self::from_millis(value))
176	}
177}