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 DecodeError {
87 pub(crate) fn complete(self) -> Self {
89 match self {
90 Self::Short => Self::InvalidValue,
91 other => other,
92 }
93 }
94}
95
96impl<V> Decode<V> for bool {
97 fn decode<R: bytes::Buf>(r: &mut R, version: V) -> Result<Self, DecodeError> {
98 match u8::decode(r, version)? {
99 0 => Ok(false),
100 1 => Ok(true),
101 _ => Err(DecodeError::InvalidValue),
102 }
103 }
104}
105
106impl<V> Decode<V> for u8 {
107 fn decode<R: bytes::Buf>(r: &mut R, _: V) -> Result<Self, DecodeError> {
108 match r.has_remaining() {
109 true => Ok(r.get_u8()),
110 false => Err(DecodeError::Short),
111 }
112 }
113}
114
115impl<V> Decode<V> for u16 {
116 fn decode<R: bytes::Buf>(r: &mut R, _: V) -> Result<Self, DecodeError> {
117 match r.remaining() >= 2 {
118 true => Ok(r.get_u16()),
119 false => Err(DecodeError::Short),
120 }
121 }
122}
123
124impl<V: Copy> Decode<V> for String
125where
126 usize: Decode<V>,
127{
128 fn decode<R: bytes::Buf>(r: &mut R, version: V) -> Result<Self, DecodeError> {
130 let v = Vec::<u8>::decode(r, version)?;
131 let str = String::from_utf8(v)?;
132
133 Ok(str)
134 }
135}
136
137impl<V: Copy> Decode<V> for Vec<u8>
138where
139 usize: Decode<V>,
140{
141 fn decode<B: bytes::Buf>(buf: &mut B, version: V) -> Result<Self, DecodeError> {
142 let size = usize::decode(buf, version)?;
143
144 if buf.remaining() < size {
145 return Err(DecodeError::Short);
146 }
147
148 let bytes = buf.copy_to_bytes(size);
149 Ok(bytes.to_vec())
150 }
151}
152
153impl<V> Decode<V> for i8 {
154 fn decode<R: bytes::Buf>(r: &mut R, _: V) -> Result<Self, DecodeError> {
155 if !r.has_remaining() {
156 return Err(DecodeError::Short);
157 }
158
159 Ok(((r.get_u8() as i16) - 128) as i8)
163 }
164}
165
166impl<V: Copy> Decode<V> for bytes::Bytes
167where
168 usize: Decode<V>,
169{
170 fn decode<R: bytes::Buf>(r: &mut R, version: V) -> Result<Self, DecodeError> {
171 let len = usize::decode(r, version)?;
172 if r.remaining() < len {
173 return Err(DecodeError::Short);
174 }
175 let bytes = r.copy_to_bytes(len);
176 Ok(bytes)
177 }
178}
179
180impl<V: Copy> Decode<V> for Cow<'_, str>
182where
183 usize: Decode<V>,
184{
185 fn decode<R: bytes::Buf>(r: &mut R, version: V) -> Result<Self, DecodeError> {
186 let s = String::decode(r, version)?;
187 Ok(Cow::Owned(s))
188 }
189}
190
191impl<V: Copy> Decode<V> for Option<u64>
192where
193 u64: Decode<V>,
194{
195 fn decode<R: bytes::Buf>(r: &mut R, version: V) -> Result<Self, DecodeError> {
196 match u64::decode(r, version)? {
197 0 => Ok(None),
198 value => Ok(Some(value - 1)),
199 }
200 }
201}
202
203impl<V: Copy> Decode<V> for std::time::Duration
204where
205 u64: Decode<V>,
206{
207 fn decode<R: bytes::Buf>(r: &mut R, version: V) -> Result<Self, DecodeError> {
208 let value = u64::decode(r, version)?;
209 Ok(Self::from_millis(value))
210 }
211}