1use bytes::Bytes;
37
38use crate::{
39 error::{Error, Result},
40 msgpack::{Decoder, Encoder, Kind},
41};
42
43pub trait Wire: Sized {
45 fn encode(&self, encoder: &mut Encoder);
47
48 fn decode(decoder: &mut Decoder<'_>) -> Result<Self>;
50}
51
52pub fn encode_frames<T: Wire>(value: &T) -> Vec<Bytes> {
55 let mut encoder = Encoder::new();
56 value.encode(&mut encoder);
57 encoder.into_frames()
58}
59
60pub fn decode_frames<T: Wire>(frames: &[Bytes]) -> Result<T> {
62 let mut decoder = Decoder::new(frames);
63 let value = T::decode(&mut decoder)?;
64 decoder.finish()?;
65 Ok(value)
66}
67
68pub fn decode_bytes<T: Wire>(bytes: &[u8]) -> Result<T> {
70 decode_frames(&[Bytes::copy_from_slice(bytes)])
71}
72
73impl Wire for bool {
74 fn encode(&self, encoder: &mut Encoder) {
75 encoder.bool(*self);
76 }
77
78 fn decode(decoder: &mut Decoder<'_>) -> Result<Self> {
79 decoder.bool()
80 }
81}
82
83macro_rules! wire_int {
84 ($($ty:ty => $write:ident),* $(,)?) => {$(
85 impl Wire for $ty {
86 fn encode(&self, encoder: &mut Encoder) {
87 encoder.$write((*self).into());
88 }
89
90 fn decode(decoder: &mut Decoder<'_>) -> Result<Self> {
91 decoder.integer()?.narrow(stringify!($ty))
92 }
93 }
94 )*};
95}
96
97wire_int!(i32 => int, i64 => int, u16 => uint, u32 => uint, u64 => uint);
98
99impl Wire for f64 {
100 fn encode(&self, encoder: &mut Encoder) {
101 encoder.float(*self);
102 }
103
104 fn decode(decoder: &mut Decoder<'_>) -> Result<Self> {
105 decoder.float()
106 }
107}
108
109impl Wire for String {
110 fn encode(&self, encoder: &mut Encoder) {
111 encoder.str(self);
112 }
113
114 fn decode(decoder: &mut Decoder<'_>) -> Result<Self> {
115 Ok(decoder.str()?.to_owned())
116 }
117}
118
119impl<T: Wire> Wire for Option<T> {
121 fn encode(&self, encoder: &mut Encoder) {
122 match self {
123 Some(value) => value.encode(encoder),
124 None => encoder.nil(),
125 }
126 }
127
128 fn decode(decoder: &mut Decoder<'_>) -> Result<Self> {
129 if decoder.take_nil()? {
130 Ok(None)
131 } else {
132 T::decode(decoder).map(Some)
133 }
134 }
135}
136
137impl<T: Wire> Wire for Vec<T> {
139 fn encode(&self, encoder: &mut Encoder) {
140 encoder.array_len(self.len());
141 for item in self {
142 item.encode(encoder);
143 }
144 }
145
146 fn decode(decoder: &mut Decoder<'_>) -> Result<Self> {
147 let len = decoder.array_len()?;
148 let mut items = Vec::with_capacity(len.min(1 << 16));
150 for _ in 0..len {
151 items.push(T::decode(decoder)?);
152 }
153 Ok(items)
154 }
155}
156
157impl<A: Wire, B: Wire> Wire for (A, B) {
159 fn encode(&self, encoder: &mut Encoder) {
160 encoder.array_len(2);
161 self.0.encode(encoder);
162 self.1.encode(encoder);
163 }
164
165 fn decode(decoder: &mut Decoder<'_>) -> Result<Self> {
166 let len = decoder.array_len()?;
167 if len != 2 {
168 return Err(Error::Invalid(format!(
169 "expected a 2-element array, found {len} elements"
170 )));
171 }
172 Ok((A::decode(decoder)?, B::decode(decoder)?))
173 }
174}
175
176#[derive(Debug, Clone, PartialEq)]
178pub struct Dict<K, V>(pub Vec<(K, V)>);
179
180impl<K, V> Default for Dict<K, V> {
181 fn default() -> Self {
182 Dict(Vec::new())
183 }
184}
185
186impl<K: PartialEq, V> Dict<K, V> {
187 pub fn get<Q>(&self, key: &Q) -> Option<&V>
189 where
190 K: PartialEq<Q>,
191 Q: ?Sized,
192 {
193 self.0.iter().find(|(k, _)| k == key).map(|(_, v)| v)
194 }
195}
196
197impl<K: Wire, V: Wire> Wire for Dict<K, V> {
198 fn encode(&self, encoder: &mut Encoder) {
199 encoder.map_len(self.0.len());
200 for (key, value) in &self.0 {
201 key.encode(encoder);
202 value.encode(encoder);
203 }
204 }
205
206 fn decode(decoder: &mut Decoder<'_>) -> Result<Self> {
207 let len = decoder.map_len()?;
208 let mut entries = Vec::with_capacity(len.min(1 << 16));
209 for _ in 0..len {
210 let key = K::decode(decoder)?;
211 entries.push((key, V::decode(decoder)?));
212 }
213 Ok(Dict(entries))
214 }
215}
216
217#[derive(Debug, Clone, PartialEq, Eq)]
219pub enum StrOrList {
220 One(String),
222 Many(Vec<String>),
224}
225
226impl Wire for StrOrList {
227 fn encode(&self, encoder: &mut Encoder) {
228 match self {
229 StrOrList::One(value) => value.encode(encoder),
230 StrOrList::Many(values) => values.encode(encoder),
231 }
232 }
233
234 fn decode(decoder: &mut Decoder<'_>) -> Result<Self> {
235 match decoder.peek_kind()? {
236 Kind::Str => Ok(StrOrList::One(String::decode(decoder)?)),
237 Kind::Array => Ok(StrOrList::Many(Vec::decode(decoder)?)),
238 _ => Err(Error::Invalid(
239 "expected a string or a list of strings".to_owned(),
240 )),
241 }
242 }
243}
244
245#[doc(hidden)]
247pub struct ArrayFields<'d, 'f> {
248 decoder: &'d mut Decoder<'f>,
249 remaining: usize,
250}
251
252impl<'d, 'f> ArrayFields<'d, 'f> {
253 pub fn begin(decoder: &'d mut Decoder<'f>) -> Result<Self> {
255 let remaining = decoder.array_len()?;
256 Ok(Self { decoder, remaining })
257 }
258
259 pub fn tag(&mut self, expected: &'static str) -> Result<()> {
261 if self.remaining == 0 {
262 return Err(Error::MissingField("_tag"));
263 }
264 self.remaining -= 1;
265 let found = self.decoder.str()?;
266 if found != expected {
267 return Err(Error::Tag {
268 expected,
269 found: found.to_owned(),
270 });
271 }
272 Ok(())
273 }
274
275 pub fn next<T: Wire>(&mut self, name: &'static str) -> Result<Option<T>> {
277 if self.remaining == 0 {
278 return Ok(None);
279 }
280 self.remaining -= 1;
281 T::decode(self.decoder)
282 .map(Some)
283 .map_err(|error| error.in_field(name))
284 }
285
286 pub fn finish(self) -> Result<()> {
288 for _ in 0..self.remaining {
289 self.decoder.skip()?;
290 }
291 Ok(())
292 }
293}
294
295macro_rules! wire_struct {
313 (
314 $(#[$meta:meta])*
315 $vis:vis struct $name:ident: $layout:ident $(($tag:expr))? + Default {
316 $( $(#[$fmeta:meta])* $fvis:vis $field:ident: $fty:ty = $fdefault:expr ),* $(,)?
317 }
318 ) => {
319 wire_struct! {
320 $(#[$meta])*
321 $vis struct $name: $layout $(($tag))? {
322 $( $(#[$fmeta])* $fvis $field: $fty = $fdefault ),*
323 }
324 }
325
326 impl Default for $name {
327 fn default() -> Self {
328 Self { $( $field: $fdefault ),* }
329 }
330 }
331 };
332 (
333 $(#[$meta:meta])*
334 $vis:vis struct $name:ident: $layout:ident $(($tag:expr))? {
335 $( $(#[$fmeta:meta])* $fvis:vis $field:ident: $fty:ty $(= $fdefault:expr)? ),* $(,)?
336 }
337 ) => {
338 $(#[$meta])*
339 $vis struct $name {
340 $( $(#[$fmeta])* $fvis $field: $fty ),*
341 }
342
343 wire_struct!(@$layout $name $(($tag))? { $( $field: $fty $(= $fdefault)? ),* });
344 };
345 (@array $name:ident $(($tag:expr))? { $( $field:ident: $fty:ty $(= $fdefault:expr)? ),* }) => {
346 impl $crate::codec::Wire for $name {
347 fn encode(&self, encoder: &mut $crate::msgpack::Encoder) {
348 let tag_len: usize = 0 $( + { let _ = $tag; 1 } )?;
349 encoder.array_len(tag_len $( + { let _ = stringify!($field); 1 } )*);
350 $( encoder.str($tag); )?
351 $( $crate::codec::Wire::encode(&self.$field, encoder); )*
352 }
353
354 fn decode(
355 decoder: &mut $crate::msgpack::Decoder<'_>,
356 ) -> $crate::error::Result<Self> {
357 let mut fields = $crate::codec::ArrayFields::begin(decoder)?;
358 $( fields.tag($tag)?; )?
359 $(
360 let $field: $fty = match fields.next(stringify!($field))? {
361 Some(value) => value,
362 None => wire_struct!(@default $field $($fdefault)?),
363 };
364 )*
365 fields.finish()?;
366 Ok(Self { $( $field ),* })
367 }
368 }
369 };
370 (@map $name:ident { $( $field:ident: $fty:ty $(= $fdefault:expr)? ),* }) => {
371 impl $crate::codec::Wire for $name {
372 fn encode(&self, encoder: &mut $crate::msgpack::Encoder) {
373 encoder.map_len(0 $( + { let _ = stringify!($field); 1 } )*);
374 $(
375 encoder.str(stringify!($field));
376 $crate::codec::Wire::encode(&self.$field, encoder);
377 )*
378 }
379
380 fn decode(
381 decoder: &mut $crate::msgpack::Decoder<'_>,
382 ) -> $crate::error::Result<Self> {
383 $( let mut $field: Option<$fty> = None; )*
384 for _ in 0..decoder.map_len()? {
385 match decoder.str()? {
386 $(
387 stringify!($field) => {
388 $field = Some(
389 $crate::codec::Wire::decode(decoder)
390 .map_err(|error| error.in_field(stringify!($field)))?,
391 );
392 }
393 )*
394 _ => decoder.skip()?,
395 }
396 }
397 Ok(Self {
398 $(
399 $field: match $field {
400 Some(value) => value,
401 None => wire_struct!(@default $field $($fdefault)?),
402 },
403 )*
404 })
405 }
406 }
407 };
408 (@default $field:ident) => {
409 return Err($crate::error::Error::MissingField(stringify!($field)))
410 };
411 (@default $field:ident $default:expr) => {
412 $default
413 };
414}
415
416#[cfg(test)]
417mod tests {
418 use super::*;
419
420 wire_struct! {
421 #[derive(Debug, PartialEq)]
423 struct Tagged: array("Tagged") {
424 name: String,
425 count: i64 = 5,
426 }
427 }
428
429 wire_struct! {
430 #[derive(Debug, PartialEq)]
432 struct Named: map + Default {
433 x: i64 = 1,
434 y: Option<String> = None,
435 }
436 }
437
438 fn encode_value(write: impl FnOnce(&mut Encoder)) -> Vec<u8> {
439 let mut encoder = Encoder::new();
440 write(&mut encoder);
441 encoder.into_single_frame()
442 }
443
444 #[test]
445 fn short_arrays_take_defaults_and_long_arrays_drop_extras() {
446 let short = encode_value(|e| {
447 e.array_len(2);
448 e.str("Tagged");
449 e.str("a");
450 });
451 let decoded: Tagged = decode_bytes(&short).unwrap();
452 assert_eq!(
453 decoded,
454 Tagged {
455 name: "a".into(),
456 count: 5
457 }
458 );
459
460 let long = encode_value(|e| {
461 e.array_len(4);
462 e.str("Tagged");
463 e.str("a");
464 e.int(9);
465 e.str("from a newer peer");
466 });
467 let decoded: Tagged = decode_bytes(&long).unwrap();
468 assert_eq!(
469 decoded,
470 Tagged {
471 name: "a".into(),
472 count: 9
473 }
474 );
475 }
476
477 #[test]
478 fn required_fields_and_tags_are_enforced() {
479 let missing = encode_value(|e| {
480 e.array_len(1);
481 e.str("Tagged");
482 });
483 assert!(matches!(
484 decode_bytes::<Tagged>(&missing),
485 Err(Error::MissingField("name"))
486 ));
487
488 let wrong_tag = encode_value(|e| {
489 e.array_len(2);
490 e.str("Other");
491 e.str("a");
492 });
493 assert!(matches!(
494 decode_bytes::<Tagged>(&wrong_tag),
495 Err(Error::Tag { .. })
496 ));
497 }
498
499 #[test]
500 fn map_structs_ignore_unknown_keys_and_default_missing_ones() {
501 let bytes = encode_value(|e| {
502 e.map_len(2);
503 e.str("unknown");
504 e.array_len(1);
505 e.nil();
506 e.str("y");
507 e.str("v");
508 });
509 let decoded: Named = decode_bytes(&bytes).unwrap();
510 assert_eq!(
511 decoded,
512 Named {
513 x: 1,
514 y: Some("v".into())
515 }
516 );
517
518 let encoded = encode_frames(&Named::default());
519 assert_eq!(&encoded[0][..], b"\x82\xa1x\x01\xa1y\xc0");
520 }
521
522 #[test]
523 fn errors_name_the_field() {
524 let bytes = encode_value(|e| {
525 e.array_len(3);
526 e.str("Tagged");
527 e.str("a");
528 e.str("not an int");
529 });
530 let error = decode_bytes::<Tagged>(&bytes).unwrap_err();
531 assert!(error.to_string().starts_with("field `count`:"), "{error}");
532 }
533}