1use std::{borrow::Cow, string::FromUtf8Error};
2use thiserror::Error;
3
4pub trait Decode<V>: Sized {
8 fn decode<B: bytes::Buf>(buf: &mut B, version: V) -> Result<Self, DecodeError>;
10}
11
12#[derive(Error, Debug, Clone)]
14#[non_exhaustive]
15pub enum DecodeError {
16 #[error("short buffer")]
18 Short,
19
20 #[error("long buffer")]
22 Long,
23
24 #[error("invalid string")]
26 InvalidString(#[from] FromUtf8Error),
27
28 #[error("invalid message: {0:?}")]
30 InvalidMessage(u64),
31
32 #[error("invalid subscribe location")]
34 InvalidSubscribeLocation,
35
36 #[error("invalid value")]
38 InvalidValue,
39
40 #[error("too many")]
42 TooMany,
43
44 #[error("bounds exceeded")]
46 BoundsExceeded,
47
48 #[error("expected end")]
50 ExpectedEnd,
51
52 #[error("message too large: {size} bytes exceeds {max} byte limit")]
54 MessageTooLarge {
55 size: usize,
57 max: usize,
59 },
60
61 #[error("expected data")]
63 ExpectedData,
64
65 #[error("duplicate")]
67 Duplicate,
68
69 #[error("missing")]
71 Missing,
72
73 #[error("unsupported")]
75 Unsupported,
76
77 #[error("trailing bytes")]
79 TrailingBytes,
80
81 #[error("unsupported version")]
83 Version,
84}
85
86impl<V> Decode<V> for bool {
87 fn decode<R: bytes::Buf>(r: &mut R, version: V) -> Result<Self, DecodeError> {
88 match u8::decode(r, version)? {
89 0 => Ok(false),
90 1 => Ok(true),
91 _ => Err(DecodeError::InvalidValue),
92 }
93 }
94}
95
96impl<V> Decode<V> for u8 {
97 fn decode<R: bytes::Buf>(r: &mut R, _: V) -> Result<Self, DecodeError> {
98 match r.has_remaining() {
99 true => Ok(r.get_u8()),
100 false => Err(DecodeError::Short),
101 }
102 }
103}
104
105impl<V> Decode<V> for u16 {
106 fn decode<R: bytes::Buf>(r: &mut R, _: V) -> Result<Self, DecodeError> {
107 match r.remaining() >= 2 {
108 true => Ok(r.get_u16()),
109 false => Err(DecodeError::Short),
110 }
111 }
112}
113
114impl<V: Copy> Decode<V> for String
115where
116 usize: Decode<V>,
117{
118 fn decode<R: bytes::Buf>(r: &mut R, version: V) -> Result<Self, DecodeError> {
120 let v = Vec::<u8>::decode(r, version)?;
121 let str = String::from_utf8(v)?;
122
123 Ok(str)
124 }
125}
126
127impl<V: Copy> Decode<V> for Vec<u8>
128where
129 usize: Decode<V>,
130{
131 fn decode<B: bytes::Buf>(buf: &mut B, version: V) -> Result<Self, DecodeError> {
132 let size = usize::decode(buf, version)?;
133
134 if buf.remaining() < size {
135 return Err(DecodeError::Short);
136 }
137
138 let bytes = buf.copy_to_bytes(size);
139 Ok(bytes.to_vec())
140 }
141}
142
143impl<V> Decode<V> for i8 {
144 fn decode<R: bytes::Buf>(r: &mut R, _: V) -> Result<Self, DecodeError> {
145 if !r.has_remaining() {
146 return Err(DecodeError::Short);
147 }
148
149 Ok(((r.get_u8() as i16) - 128) as i8)
153 }
154}
155
156impl<V: Copy> Decode<V> for bytes::Bytes
157where
158 usize: Decode<V>,
159{
160 fn decode<R: bytes::Buf>(r: &mut R, version: V) -> Result<Self, DecodeError> {
161 let len = usize::decode(r, version)?;
162 if r.remaining() < len {
163 return Err(DecodeError::Short);
164 }
165 let bytes = r.copy_to_bytes(len);
166 Ok(bytes)
167 }
168}
169
170impl<V: Copy> Decode<V> for Cow<'_, str>
172where
173 usize: Decode<V>,
174{
175 fn decode<R: bytes::Buf>(r: &mut R, version: V) -> Result<Self, DecodeError> {
176 let s = String::decode(r, version)?;
177 Ok(Cow::Owned(s))
178 }
179}
180
181impl<V: Copy> Decode<V> for Option<u64>
182where
183 u64: Decode<V>,
184{
185 fn decode<R: bytes::Buf>(r: &mut R, version: V) -> Result<Self, DecodeError> {
186 match u64::decode(r, version)? {
187 0 => Ok(None),
188 value => Ok(Some(value - 1)),
189 }
190 }
191}
192
193impl<V: Copy> Decode<V> for std::time::Duration
194where
195 u64: Decode<V>,
196{
197 fn decode<R: bytes::Buf>(r: &mut R, version: V) -> Result<Self, DecodeError> {
198 let value = u64::decode(r, version)?;
199 Ok(Self::from_millis(value))
200 }
201}