moq_lite/coding/
decode.rs

1use std::{borrow::Cow, string::FromUtf8Error};
2use thiserror::Error;
3
4pub trait Decode<V>: Sized {
5	fn decode<B: bytes::Buf>(buf: &mut B, version: V) -> Result<Self, DecodeError>;
6}
7
8/// A decode error.
9#[derive(Error, Debug, Clone)]
10pub enum DecodeError {
11	#[error("short buffer")]
12	Short,
13
14	#[error("long buffer")]
15	Long,
16
17	#[error("invalid string")]
18	InvalidString(#[from] FromUtf8Error),
19
20	#[error("invalid message: {0:?}")]
21	InvalidMessage(u64),
22
23	#[error("invalid subscribe location")]
24	InvalidSubscribeLocation,
25
26	#[error("invalid value")]
27	InvalidValue,
28
29	#[error("too many")]
30	TooMany,
31
32	#[error("bounds exceeded")]
33	BoundsExceeded,
34
35	#[error("expected end")]
36	ExpectedEnd,
37
38	#[error("expected data")]
39	ExpectedData,
40
41	#[error("duplicate")]
42	Duplicate,
43
44	#[error("missing")]
45	Missing,
46
47	#[error("unsupported")]
48	Unsupported,
49}
50
51impl<V> Decode<V> for bool {
52	fn decode<R: bytes::Buf>(r: &mut R, version: V) -> Result<Self, DecodeError> {
53		match u8::decode(r, version)? {
54			0 => Ok(false),
55			1 => Ok(true),
56			_ => Err(DecodeError::InvalidValue),
57		}
58	}
59}
60
61impl<V> Decode<V> for u8 {
62	fn decode<R: bytes::Buf>(r: &mut R, _: V) -> Result<Self, DecodeError> {
63		match r.has_remaining() {
64			true => Ok(r.get_u8()),
65			false => Err(DecodeError::Short),
66		}
67	}
68}
69
70impl<V> Decode<V> for u16 {
71	fn decode<R: bytes::Buf>(r: &mut R, _: V) -> Result<Self, DecodeError> {
72		match r.remaining() >= 2 {
73			true => Ok(r.get_u16()),
74			false => Err(DecodeError::Short),
75		}
76	}
77}
78
79impl<V> Decode<V> for String {
80	/// Decode a string with a varint length prefix.
81	fn decode<R: bytes::Buf>(r: &mut R, version: V) -> Result<Self, DecodeError> {
82		let v = Vec::<u8>::decode(r, version)?;
83		let str = String::from_utf8(v)?;
84
85		Ok(str)
86	}
87}
88
89impl<V> Decode<V> for Vec<u8> {
90	fn decode<B: bytes::Buf>(buf: &mut B, version: V) -> Result<Self, DecodeError> {
91		let size = usize::decode(buf, version)?;
92
93		if buf.remaining() < size {
94			return Err(DecodeError::Short);
95		}
96
97		let bytes = buf.copy_to_bytes(size);
98		Ok(bytes.to_vec())
99	}
100}
101
102impl<V> Decode<V> for i8 {
103	fn decode<R: bytes::Buf>(r: &mut R, _: V) -> Result<Self, DecodeError> {
104		if !r.has_remaining() {
105			return Err(DecodeError::Short);
106		}
107
108		// This is not the usual way of encoding negative numbers.
109		// i8 doesn't exist in the draft, but we use it instead of u8 for priority.
110		// A default of 0 is more ergonomic for the user than a default of 128.
111		Ok(((r.get_u8() as i16) - 128) as i8)
112	}
113}
114
115impl<V> Decode<V> for bytes::Bytes {
116	fn decode<R: bytes::Buf>(r: &mut R, version: V) -> Result<Self, DecodeError> {
117		let len = usize::decode(r, version)?;
118		if r.remaining() < len {
119			return Err(DecodeError::Short);
120		}
121		let bytes = r.copy_to_bytes(len);
122		Ok(bytes)
123	}
124}
125
126// TODO Support borrowed strings.
127impl<'a, V> Decode<V> for Cow<'a, str> {
128	fn decode<R: bytes::Buf>(r: &mut R, version: V) -> Result<Self, DecodeError> {
129		let s = String::decode(r, version)?;
130		Ok(Cow::Owned(s))
131	}
132}