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("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 Decode for bool {
52	fn decode<R: bytes::Buf>(r: &mut R) -> Result<Self, DecodeError> {
53		match u8::decode(r)? {
54			0 => Ok(false),
55			1 => Ok(true),
56			_ => Err(DecodeError::InvalidValue),
57		}
58	}
59}
60
61impl Decode for u8 {
62	fn decode<R: bytes::Buf>(r: &mut R) -> Result<Self, DecodeError> {
63		match r.has_remaining() {
64			true => Ok(r.get_u8()),
65			false => Err(DecodeError::Short),
66		}
67	}
68}
69
70impl Decode for u16 {
71	fn decode<R: bytes::Buf>(r: &mut R) -> Result<Self, DecodeError> {
72		match r.remaining() >= 2 {
73			true => Ok(r.get_u16()),
74			false => Err(DecodeError::Short),
75		}
76	}
77}
78
79impl Decode for String {
80	/// Decode a string with a varint length prefix.
81	fn decode<R: bytes::Buf>(r: &mut R) -> Result<Self, DecodeError> {
82		let v = Vec::<u8>::decode(r)?;
83		let str = String::from_utf8(v)?;
84
85		Ok(str)
86	}
87}
88
89impl Decode for Vec<u8> {
90	fn decode<B: bytes::Buf>(buf: &mut B) -> Result<Self, DecodeError> {
91		let size = usize::decode(buf)?;
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 Decode for std::time::Duration {
103	fn decode<B: bytes::Buf>(buf: &mut B) -> Result<Self, DecodeError> {
104		let ms = u64::decode(buf)?;
105		Ok(std::time::Duration::from_micros(ms))
106	}
107}
108
109impl Decode for i8 {
110	fn decode<R: bytes::Buf>(r: &mut R) -> Result<Self, DecodeError> {
111		if !r.has_remaining() {
112			return Err(DecodeError::Short);
113		}
114
115		// This is not the usual way of encoding negative numbers.
116		// i8 doesn't exist in the draft, but we use it instead of u8 for priority.
117		// A default of 0 is more ergonomic for the user than a default of 128.
118		Ok(((r.get_u8() as i16) - 128) as i8)
119	}
120}
121
122impl Decode for bytes::Bytes {
123	fn decode<R: bytes::Buf>(r: &mut R) -> Result<Self, DecodeError> {
124		let len = usize::decode(r)?;
125		if r.remaining() < len {
126			return Err(DecodeError::Short);
127		}
128		let bytes = r.copy_to_bytes(len);
129		Ok(bytes)
130	}
131}
132
133// TODO Support borrowed strings.
134impl<'a> Decode for Cow<'a, str> {
135	fn decode<R: bytes::Buf>(r: &mut R) -> Result<Self, DecodeError> {
136		let s = String::decode(r)?;
137		Ok(Cow::Owned(s))
138	}
139}