moq_lite/coding/
decode.rs

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