1use std::borrow::Cow;
2
3use varing::{decode_u32_varint, encode_u32_varint_to, encoded_u32_varint_len};
4
5use super::WireType;
6
7pub use tuple::TupleEncoder;
8
9#[cfg(any(feature = "std", feature = "alloc"))]
10mod bytes;
11#[cfg(any(feature = "std", feature = "alloc"))]
12mod nodecraft;
13mod primitives;
14#[cfg(any(feature = "std", feature = "alloc"))]
15mod string;
16
17mod tuple;
18
19pub trait DataRef<'a, D>
21where
22 D: Data + ?Sized,
23 Self: Copy + core::fmt::Debug + Send + Sync,
24{
25 fn decode(buf: &'a [u8]) -> Result<(usize, Self), DecodeError>
29 where
30 Self: Sized;
31
32 fn decode_length_delimited(src: &'a [u8]) -> Result<(usize, Self), DecodeError>
34 where
35 Self: Sized,
36 {
37 if D::WIRE_TYPE != WireType::LengthDelimited {
38 return Self::decode(src);
39 }
40
41 let (offset, len) = decode_u32_varint(src)?;
42 let mut offset = offset.get();
43 let len = len as usize;
44 if len + offset > src.len() {
45 return Err(DecodeError::buffer_underflow());
46 }
47
48 let src = &src[offset..offset + len];
49 let (bytes_read, value) = Self::decode(src)?;
50
51 #[cfg(debug_assertions)]
52 super::debug_assert_read_eq::<Self>(bytes_read, len);
53
54 offset += bytes_read;
55 Ok((offset, value))
56 }
57}
58
59pub trait Data: core::fmt::Debug + Send + Sync {
61 const WIRE_TYPE: WireType = WireType::LengthDelimited;
63
64 type Ref<'a>: DataRef<'a, Self>;
66
67 fn from_ref(val: Self::Ref<'_>) -> Result<Self, DecodeError>
69 where
70 Self: Sized;
71
72 fn encoded_len(&self) -> usize;
74
75 fn encoded_len_with_length_delimited(&self) -> usize {
77 let len = self.encoded_len();
78 match Self::WIRE_TYPE {
79 WireType::LengthDelimited => encoded_u32_varint_len(len as u32).get() + len,
80 _ => len,
81 }
82 }
83
84 fn encode(&self, buf: &mut [u8]) -> Result<usize, EncodeError>;
88
89 #[cfg(any(feature = "std", feature = "alloc"))]
91 fn encode_to_vec(&self) -> Result<std::vec::Vec<u8>, EncodeError> {
92 let len = self.encoded_len();
93 let mut vec = std::vec![0; len];
94 self.encode(&mut vec).map(|_| vec)
95 }
96
97 #[cfg(any(feature = "std", feature = "alloc"))]
99 fn encode_to_bytes(&self) -> Result<::bytes::Bytes, EncodeError> {
100 self.encode_to_vec().map(Into::into)
101 }
102
103 fn encode_length_delimited(&self, buf: &mut [u8]) -> Result<usize, EncodeError> {
107 if Self::WIRE_TYPE != WireType::LengthDelimited {
108 return self.encode(buf);
109 }
110
111 let len = self.encoded_len();
112 if len > u32::MAX as usize {
113 return Err(EncodeError::TooLarge);
114 }
115
116 let mut offset = 0;
117 offset += encode_u32_varint_to(len as u32, buf)?.get();
118 offset += self.encode(&mut buf[offset..])?;
119
120 #[cfg(debug_assertions)]
121 super::debug_assert_write_eq::<Self>(offset, self.encoded_len_with_length_delimited());
122
123 Ok(offset)
124 }
125
126 #[cfg(any(feature = "std", feature = "alloc"))]
128 fn encode_length_delimited_to_vec(&self) -> Result<std::vec::Vec<u8>, EncodeError> {
129 let len = self.encoded_len_with_length_delimited();
130 let mut vec = std::vec![0; len];
131 self.encode_length_delimited(&mut vec).map(|_| vec)
132 }
133
134 #[cfg(any(feature = "std", feature = "alloc"))]
136 fn encode_length_delimited_to_bytes(&self) -> Result<::bytes::Bytes, EncodeError> {
137 self.encode_length_delimited_to_vec().map(Into::into)
138 }
139
140 fn decode(src: &[u8]) -> Result<(usize, Self), DecodeError>
144 where
145 Self: Sized,
146 {
147 <Self::Ref<'_> as DataRef<Self>>::decode(src)
148 .and_then(|(bytes_read, value)| Self::from_ref(value).map(|val| (bytes_read, val)))
149 }
150
151 fn decode_length_delimited(buf: &[u8]) -> Result<(usize, Self), DecodeError>
153 where
154 Self: Sized,
155 {
156 <Self::Ref<'_> as DataRef<Self>>::decode_length_delimited(buf)
157 .and_then(|(bytes_read, value)| Self::from_ref(value).map(|val| (bytes_read, val)))
158 }
159}
160
161#[derive(Debug, thiserror::Error)]
163pub enum EncodeError {
164 #[error("insufficient buffer capacity, required: {required}, remaining: {remaining}")]
166 InsufficientBuffer {
167 required: usize,
169 remaining: usize,
171 },
172 #[error("encoded data is too large, the maximum allowed size is {MAX} bytes", MAX = u32::MAX)]
174 TooLarge,
175 #[error("{0}")]
177 Custom(Cow<'static, str>),
178}
179
180impl EncodeError {
181 #[inline]
183 pub const fn insufficient_buffer(required: usize, remaining: usize) -> Self {
184 Self::InsufficientBuffer {
185 required,
186 remaining,
187 }
188 }
189
190 pub fn custom<T>(value: T) -> Self
192 where
193 T: Into<Cow<'static, str>>,
194 {
195 Self::Custom(value.into())
196 }
197
198 pub fn update(mut self, required: usize, remaining: usize) -> Self {
200 match self {
201 Self::InsufficientBuffer {
202 required: ref mut r,
203 remaining: ref mut rem,
204 } => {
205 *r = required;
206 *rem = remaining;
207 self
208 }
209 _ => self,
210 }
211 }
212}
213
214impl From<varing::EncodeError> for EncodeError {
215 #[inline]
216 fn from(value: varing::EncodeError) -> Self {
217 match value {
218 varing::EncodeError::InsufficientSpace(err) => Self::InsufficientBuffer {
219 required: err.requested().get(),
220 remaining: err.available(),
221 },
222 varing::EncodeError::Other(e) => EncodeError::custom(e),
223 _ => EncodeError::custom("unknown encoding error"),
224 }
225 }
226}
227
228impl From<varing::ConstEncodeError> for EncodeError {
229 #[inline]
230 fn from(value: varing::ConstEncodeError) -> Self {
231 match value {
232 varing::ConstEncodeError::InsufficientSpace(err) => Self::InsufficientBuffer {
233 required: err.requested().get(),
234 remaining: err.available(),
235 },
236 varing::ConstEncodeError::Other(e) => EncodeError::custom(e),
237 _ => EncodeError::custom("unknown encoding error"),
238 }
239 }
240}
241
242impl From<Cow<'static, str>> for EncodeError {
243 fn from(value: Cow<'static, str>) -> Self {
244 Self::Custom(value)
245 }
246}
247
248#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error, derive_more::IsVariant)]
254pub enum DecodeError {
255 #[error("buffer underflow")]
257 BufferUnderflow,
258
259 #[error("missing {field} in {ty}")]
261 MissingField {
262 ty: &'static str,
264 field: &'static str,
266 },
267
268 #[error("duplicate field {field} with tag {tag} in {ty}")]
270 DuplicateField {
271 ty: &'static str,
273 field: &'static str,
275 tag: u8,
277 },
278
279 #[error("unknown wire type value {value} with tag {tag} when decoding {ty}")]
281 UnknownWireType {
282 ty: &'static str,
284 value: u8,
286 tag: u8,
288 },
289
290 #[error("unknown tag {tag} when decoding {ty}")]
292 UnknownTag {
293 ty: &'static str,
295 tag: u8,
297 },
298
299 #[error("length-delimited overflow the maximum value of u32")]
301 LengthDelimitedOverflow,
302
303 #[error("{0}")]
305 Custom(Cow<'static, str>),
306}
307
308impl From<varing::DecodeError> for DecodeError {
309 #[inline]
310 fn from(e: varing::DecodeError) -> Self {
311 match e {
312 varing::DecodeError::Overflow => Self::LengthDelimitedOverflow,
313 varing::DecodeError::InsufficientData { .. } => Self::buffer_underflow(),
314 varing::DecodeError::Other(cow) => Self::Custom(cow),
315 _ => {
316 Self::custom("unknown decoding error")
318 }
319 }
320 }
321}
322
323impl From<varing::ConstDecodeError> for DecodeError {
324 #[inline]
325 fn from(e: varing::ConstDecodeError) -> Self {
326 match e {
327 varing::ConstDecodeError::Overflow => Self::LengthDelimitedOverflow,
328 varing::ConstDecodeError::InsufficientData { .. } => Self::buffer_underflow(),
329 varing::ConstDecodeError::Other(cow) => Self::custom(cow),
330 _ => {
331 Self::custom("unknown decoding error")
333 }
334 }
335 }
336}
337
338impl DecodeError {
339 #[inline]
341 pub const fn buffer_underflow() -> Self {
342 Self::BufferUnderflow
343 }
344
345 #[inline]
347 pub const fn missing_field(ty: &'static str, field: &'static str) -> Self {
348 Self::MissingField { ty, field }
349 }
350
351 #[inline]
353 pub const fn duplicate_field(ty: &'static str, field: &'static str, tag: u8) -> Self {
354 Self::DuplicateField { ty, field, tag }
355 }
356
357 #[inline]
359 pub const fn unknown_wire_type(ty: &'static str, value: u8, tag: u8) -> Self {
360 Self::UnknownWireType { ty, value, tag }
361 }
362
363 #[inline]
365 pub const fn unknown_tag(ty: &'static str, tag: u8) -> Self {
366 Self::UnknownTag { ty, tag }
367 }
368
369 #[inline]
371 pub fn custom<T>(value: T) -> Self
372 where
373 T: Into<Cow<'static, str>>,
374 {
375 Self::Custom(value.into())
376 }
377}