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 fn control(&self, _version: V) -> Option<crate::stats::Control> {
13 None
14 }
15
16 fn uncounted(&self) -> usize {
19 0
20 }
21}
22
23#[derive(Error, Debug, Clone)]
25#[non_exhaustive]
26pub enum DecodeError {
27 #[error("short buffer")]
29 Short,
30
31 #[error("long buffer")]
33 Long,
34
35 #[error("invalid string")]
37 InvalidString(#[from] FromUtf8Error),
38
39 #[error("invalid message: {0:?}")]
41 InvalidMessage(u64),
42
43 #[error("invalid subscribe location")]
45 InvalidSubscribeLocation,
46
47 #[error("invalid value")]
49 InvalidValue,
50
51 #[error("too many")]
53 TooMany,
54
55 #[error("bounds exceeded")]
57 BoundsExceeded,
58
59 #[error("expected end")]
61 ExpectedEnd,
62
63 #[error("message too large: {size} bytes exceeds {max} byte limit")]
65 MessageTooLarge {
66 size: usize,
68 max: usize,
70 },
71
72 #[error("expected data")]
74 ExpectedData,
75
76 #[error("duplicate")]
78 Duplicate,
79
80 #[error("missing")]
82 Missing,
83
84 #[error("unsupported")]
86 Unsupported,
87
88 #[error("trailing bytes")]
90 TrailingBytes,
91
92 #[error("unsupported version")]
94 Version,
95}
96
97impl DecodeError {
98 pub(crate) fn complete(self) -> Self {
100 match self {
101 Self::Short => Self::InvalidValue,
102 other => other,
103 }
104 }
105}
106
107impl<V> Decode<V> for bool {
108 fn decode<R: bytes::Buf>(r: &mut R, version: V) -> Result<Self, DecodeError> {
109 match u8::decode(r, version)? {
110 0 => Ok(false),
111 1 => Ok(true),
112 _ => Err(DecodeError::InvalidValue),
113 }
114 }
115}
116
117impl<V> Decode<V> for u8 {
118 fn decode<R: bytes::Buf>(r: &mut R, _: V) -> Result<Self, DecodeError> {
119 match r.has_remaining() {
120 true => Ok(r.get_u8()),
121 false => Err(DecodeError::Short),
122 }
123 }
124}
125
126impl<V> Decode<V> for u16 {
127 fn decode<R: bytes::Buf>(r: &mut R, _: V) -> Result<Self, DecodeError> {
128 match r.remaining() >= 2 {
129 true => Ok(r.get_u16()),
130 false => Err(DecodeError::Short),
131 }
132 }
133}
134
135impl<V: Copy> Decode<V> for String
136where
137 usize: Decode<V>,
138{
139 fn decode<R: bytes::Buf>(r: &mut R, version: V) -> Result<Self, DecodeError> {
141 let v = Vec::<u8>::decode(r, version)?;
142 let str = String::from_utf8(v)?;
143
144 Ok(str)
145 }
146}
147
148impl<V: Copy> Decode<V> for Vec<u8>
149where
150 usize: Decode<V>,
151{
152 fn decode<B: bytes::Buf>(buf: &mut B, version: V) -> Result<Self, DecodeError> {
153 let size = usize::decode(buf, version)?;
154
155 if buf.remaining() < size {
156 return Err(DecodeError::Short);
157 }
158
159 let bytes = buf.copy_to_bytes(size);
160 Ok(bytes.to_vec())
161 }
162}
163
164impl<V> Decode<V> for i8 {
165 fn decode<R: bytes::Buf>(r: &mut R, _: V) -> Result<Self, DecodeError> {
166 if !r.has_remaining() {
167 return Err(DecodeError::Short);
168 }
169
170 Ok(((r.get_u8() as i16) - 128) as i8)
174 }
175}
176
177impl<V: Copy> Decode<V> for bytes::Bytes
178where
179 usize: Decode<V>,
180{
181 fn decode<R: bytes::Buf>(r: &mut R, version: V) -> Result<Self, DecodeError> {
182 let len = usize::decode(r, version)?;
183 if r.remaining() < len {
184 return Err(DecodeError::Short);
185 }
186 let bytes = r.copy_to_bytes(len);
187 Ok(bytes)
188 }
189}
190
191impl<V: Copy> Decode<V> for Cow<'_, str>
193where
194 usize: Decode<V>,
195{
196 fn decode<R: bytes::Buf>(r: &mut R, version: V) -> Result<Self, DecodeError> {
197 let s = String::decode(r, version)?;
198 Ok(Cow::Owned(s))
199 }
200}
201
202impl<V: Copy> Decode<V> for Option<u64>
203where
204 u64: Decode<V>,
205{
206 fn decode<R: bytes::Buf>(r: &mut R, version: V) -> Result<Self, DecodeError> {
207 match u64::decode(r, version)? {
208 0 => Ok(None),
209 value => Ok(Some(value - 1)),
210 }
211 }
212}
213
214impl<V: Copy> Decode<V> for std::time::Duration
215where
216 u64: Decode<V>,
217{
218 fn decode<R: bytes::Buf>(r: &mut R, version: V) -> Result<Self, DecodeError> {
219 let value = u64::decode(r, version)?;
220 Ok(Self::from_millis(value))
221 }
222}