1#![expect(unsafe_code)]
39#![warn(clippy::std_instead_of_alloc)]
40#![warn(clippy::std_instead_of_core)]
41#![warn(clippy::alloc_instead_of_core)]
42#![no_std]
43
44extern crate alloc;
45extern crate self as mesh_protobuf;
46#[cfg(feature = "std")]
47extern crate std;
48
49pub mod buffer;
50mod encode_with;
51pub mod encoding;
52pub mod inplace;
53pub mod message;
54pub mod oneof;
55#[cfg(feature = "prost")]
56pub mod prost;
57pub mod protobuf;
58pub mod protofile;
59pub mod table;
60mod time;
61pub mod transparent;
62
63pub use encode_with::EncodeAs;
64pub use mesh_derive::Protobuf;
65pub use time::Timestamp;
66
67use self::table::decode::DecoderEntry;
68use self::table::encode::EncoderEntry;
69use alloc::boxed::Box;
70use alloc::fmt;
71use alloc::vec::Vec;
72use core::cell::RefCell;
73use core::mem::MaybeUninit;
74use core::num::Wrapping;
75use inplace::InplaceOption;
76use protofile::DescribeMessage;
77use protofile::MessageDescription;
78use protofile::TypeUrl;
79
80#[diagnostic::on_unimplemented(
83 message = "`{Self}` cannot be encoded as a mesh message",
84 note = "consider deriving the necessary trait on `{Self}` with one of:
85 #[derive(MeshPayload)]
86 #[derive(Protobuf)]",
87 note = "alternatively, consider using an explicit encoder with #[mesh(encoding = \"MyEncoding\")]"
88)]
89pub trait DefaultEncoding {
90 type Encoding;
97}
98
99pub trait Protobuf: DefaultEncoding<Encoding = <Self as Protobuf>::Encoding> + Sized {
101 type Encoding: MessageEncode<Self, NoResources>
103 + for<'a> MessageDecode<'a, Self, NoResources>
104 + FieldEncode<Self, NoResources>
105 + for<'a> FieldDecode<'a, Self, NoResources>;
106}
107
108impl<T> Protobuf for T
109where
110 T: DefaultEncoding,
111 T::Encoding: MessageEncode<T, NoResources>
112 + for<'a> MessageDecode<'a, T, NoResources>
113 + FieldEncode<T, NoResources>
114 + for<'a> FieldDecode<'a, T, NoResources>,
115{
116 type Encoding = <T as DefaultEncoding>::Encoding;
117}
118
119pub trait DescribedProtobuf: Protobuf {
122 const DESCRIPTION: MessageDescription<'static>;
124 const TYPE_URL: TypeUrl<'static> = Self::DESCRIPTION.type_url();
126}
127
128impl<T: DefaultEncoding + Protobuf> DescribedProtobuf for T
129where
130 <T as DefaultEncoding>::Encoding: DescribeMessage<T>,
131{
132 const DESCRIPTION: MessageDescription<'static> =
133 <<T as DefaultEncoding>::Encoding as DescribeMessage<T>>::DESCRIPTION;
134}
135
136pub trait MessageEncode<T, R>: Sized {
142 fn write_message(item: T, writer: protobuf::MessageWriter<'_, '_, R>);
144
145 fn compute_message_size(item: &mut T, sizer: protobuf::MessageSizer<'_>);
154}
155
156pub trait MessageDecode<'a, T, R>: Sized {
162 fn read_message(
164 item: &mut InplaceOption<'_, T>,
165 reader: protobuf::MessageReader<'a, '_, R>,
166 ) -> Result<()>;
167}
168
169pub trait FieldEncode<T, R>: Sized {
175 fn write_field(item: T, writer: protobuf::FieldWriter<'_, '_, R>);
177
178 fn compute_field_size(item: &mut T, sizer: protobuf::FieldSizer<'_>);
187
188 fn packed<'a>() -> Option<&'a dyn PackedEncode<T>>
191 where
192 T: 'a,
193 {
194 None
195 }
196
197 fn wrap_in_sequence() -> bool {
203 false
204 }
205
206 fn write_field_in_sequence(item: T, writer: &mut protobuf::SequenceWriter<'_, '_, R>) {
209 if Self::wrap_in_sequence() {
210 WrappedField::<Self>::write_field(item, writer.field())
211 } else {
212 Self::write_field(item, writer.field())
213 }
214 }
215
216 fn compute_field_size_in_sequence(item: &mut T, sizer: &mut protobuf::SequenceSizer<'_>) {
219 if Self::wrap_in_sequence() {
220 WrappedField::<Self>::compute_field_size(item, sizer.field())
221 } else {
222 Self::compute_field_size(item, sizer.field())
223 }
224 }
225
226 const ENTRY: EncoderEntry<T, R> = EncoderEntry::custom::<Self>();
231}
232
233pub trait PackedEncode<T> {
235 fn write_packed(&self, data: &[T], writer: protobuf::PackedWriter<'_, '_>);
237
238 fn compute_packed_size(&self, data: &[T], sizer: protobuf::PackedSizer<'_>);
240
241 fn must_pack(&self) -> bool;
246}
247
248pub trait FieldDecode<'a, T, R>: Sized {
254 fn read_field(
256 item: &mut InplaceOption<'_, T>,
257 reader: protobuf::FieldReader<'a, '_, R>,
258 ) -> Result<()>;
259
260 fn default_field(item: &mut InplaceOption<'_, T>) -> Result<()>;
265
266 fn packed<'p, C: CopyExtend<T>>() -> Option<&'p dyn PackedDecode<'a, T, C>>
269 where
270 T: 'p,
271 {
272 None
273 }
274
275 fn wrap_in_sequence() -> bool {
278 false
279 }
280
281 fn read_field_in_sequence(
284 item: &mut InplaceOption<'_, T>,
285 reader: protobuf::FieldReader<'a, '_, R>,
286 ) -> Result<()> {
287 if Self::wrap_in_sequence() {
288 WrappedField::<Self>::read_field(item, reader)
289 } else {
290 Self::read_field(item, reader)
291 }
292 }
293
294 const ENTRY: DecoderEntry<'a, T, R> = DecoderEntry::custom::<Self>();
299}
300
301pub trait PackedDecode<'a, T, C> {
303 fn read_packed(&self, data: &mut C, reader: &mut protobuf::PackedReader<'a>) -> Result<()>;
305
306 fn must_pack(&self) -> bool;
309}
310
311pub trait CopyExtend<T> {
313 fn push(&mut self, item: T)
315 where
316 T: Copy;
317
318 fn extend_from_slice(&mut self, items: &[T])
320 where
321 T: Copy;
322}
323
324impl<T> CopyExtend<T> for Vec<T> {
325 fn push(&mut self, item: T)
326 where
327 T: Copy,
328 {
329 self.push(item);
330 }
331
332 fn extend_from_slice(&mut self, items: &[T])
333 where
334 T: Copy,
335 {
336 self.extend_from_slice(items);
337 }
338}
339
340struct WrappedField<E>(pub E);
343
344impl<T, R, E: FieldEncode<T, R>> FieldEncode<T, R> for WrappedField<E> {
345 fn write_field(item: T, writer: protobuf::FieldWriter<'_, '_, R>) {
346 writer.message(|mut writer| E::write_field(item, writer.field(1)));
347 }
348
349 fn compute_field_size(item: &mut T, sizer: protobuf::FieldSizer<'_>) {
350 sizer.message(|mut sizer| E::compute_field_size(item, sizer.field(1)));
351 }
352}
353
354impl<'a, T, R, E: FieldDecode<'a, T, R>> FieldDecode<'a, T, R> for WrappedField<E> {
355 fn read_field(
356 item: &mut InplaceOption<'_, T>,
357 reader: protobuf::FieldReader<'a, '_, R>,
358 ) -> Result<()> {
359 for field in reader.message()? {
360 let (number, reader) = field?;
361 if number == 1 {
362 E::read_field(item, reader)?;
363 }
364 }
365 if item.is_none() {
366 E::default_field(item)?;
367 }
368 Ok(())
369 }
370
371 fn default_field(item: &mut InplaceOption<'_, T>) -> Result<()> {
372 E::default_field(item)
373 }
374}
375
376pub fn encode<T: DefaultEncoding>(message: T) -> Vec<u8>
378where
379 T::Encoding: MessageEncode<T, NoResources>,
380{
381 protobuf::Encoder::new(message).encode().0
382}
383
384pub fn decode<'a, T: DefaultEncoding>(data: &'a [u8]) -> Result<T>
386where
387 T::Encoding: MessageDecode<'a, T, NoResources>,
388{
389 inplace_none!(message: T);
390 protobuf::decode_with::<T::Encoding, _, _>(&mut message, data, &mut [])?;
391 Ok(message.take().expect("should be constructed"))
392}
393
394pub fn merge<'a, T: DefaultEncoding>(value: T, data: &'a [u8]) -> Result<T>
396where
397 T::Encoding: MessageDecode<'a, T, NoResources>,
398{
399 inplace_some!(value);
400 protobuf::decode_with::<T::Encoding, _, _>(&mut value, data, &mut [])?;
401 Ok(value.take().expect("should be constructed"))
402}
403
404pub enum NoResources {}
407
408#[derive(Debug)]
411pub struct SerializedMessage<R = NoResources> {
412 pub data: Vec<u8>,
414 pub resources: Vec<R>,
416}
417
418impl<R> Default for SerializedMessage<R> {
419 fn default() -> Self {
420 Self {
421 data: Default::default(),
422 resources: Default::default(),
423 }
424 }
425}
426
427impl<R> SerializedMessage<R> {
428 pub fn from_message<T: DefaultEncoding>(t: T) -> Self
430 where
431 T::Encoding: MessageEncode<T, R>,
432 {
433 let (data, resources) = protobuf::Encoder::new(t).encode();
434 Self { data, resources }
435 }
436
437 pub fn into_message<T: DefaultEncoding>(self) -> Result<T>
439 where
440 T::Encoding: for<'a> MessageDecode<'a, T, R>,
441 {
442 let (data, mut resources) = self.prep_decode();
443 inplace_none!(message: T);
444 protobuf::decode_with::<T::Encoding, _, _>(&mut message, &data, &mut resources)?;
445 Ok(message.take().expect("should be constructed"))
446 }
447
448 fn prep_decode(self) -> (Vec<u8>, Vec<Option<R>>) {
449 let data = self.data;
450 let resources = self.resources.into_iter().map(Some).collect();
451 (data, resources)
452 }
453}
454
455#[derive(Debug)]
457pub struct Error(Box<ErrorInner>);
458
459#[derive(Debug)]
460struct ErrorInner {
461 types: Vec<&'static str>,
462 err: Box<dyn core::error::Error + Send + Sync>,
463}
464
465#[derive(Debug, thiserror::Error)]
467enum DecodeError {
468 #[error("expected a message")]
469 ExpectedMessage,
470 #[error("expected a resource")]
471 ExpectedResource,
472 #[error("expected a varint")]
473 ExpectedVarInt,
474 #[error("expected a fixed64")]
475 ExpectedFixed64,
476 #[error("expected a fixed32")]
477 ExpectedFixed32,
478 #[error("expected a byte array")]
479 ExpectedByteArray,
480 #[error("field cannot exist")]
481 Unexpected,
482
483 #[error("eof parsing a varint")]
484 EofVarInt,
485 #[error("eof parsing a fixed64")]
486 EofFixed64,
487 #[error("eof parsing a fixed32")]
488 EofFixed32,
489 #[error("eof parsing a byte array")]
490 EofByteArray,
491
492 #[error("varint too big")]
493 VarIntTooBig,
494
495 #[error("missing resource")]
496 MissingResource,
497 #[error("invalid resource range")]
498 InvalidResourceRange,
499
500 #[error("unknown wire type {0}")]
501 UnknownWireType(u32),
502
503 #[error("invalid UTF-32 character")]
504 InvalidUtf32,
505 #[error("wrong buffer size for u128")]
506 BadU128,
507 #[error("wrong buffer size for ipv6 address")]
508 BadIpv6,
509 #[error("invalid UTF-8 string")]
510 InvalidUtf8(#[source] core::str::Utf8Error),
511 #[error("missing required field")]
512 MissingRequiredField,
513 #[error("wrong packed array length")]
514 BadPackedArrayLength,
515 #[error("wrong array length")]
516 BadArrayLength,
517
518 #[error("duration out of range")]
519 DurationRange,
520}
521
522impl Error {
523 pub fn new(error: impl Into<Box<dyn core::error::Error + Send + Sync>>) -> Self {
525 Self(Box::new(ErrorInner {
526 types: Vec::new(),
527 err: error.into(),
528 }))
529 }
530
531 pub fn typed<T>(mut self) -> Self {
533 self.0.types.push(core::any::type_name::<T>());
534 self
535 }
536}
537
538impl From<DecodeError> for Error {
539 fn from(kind: DecodeError) -> Self {
540 Self(Box::new(ErrorInner {
541 types: Vec::new(),
542 err: kind.into(),
543 }))
544 }
545}
546
547impl fmt::Display for Error {
548 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
549 if let Some(&ty) = self.0.types.last() {
550 write!(f, "decoding failed in {}", ty)?;
551 for &ty in self.0.types.iter().rev().skip(1) {
552 write!(f, "/{}", ty)?;
553 }
554 Ok(())
555 } else {
556 write!(f, "decoding failed")
557 }
558 }
559}
560
561impl core::error::Error for Error {
562 fn source(&self) -> Option<&(dyn core::error::Error + 'static)> {
563 Some(self.0.err.as_ref())
564 }
565}
566
567pub trait ResultExt {
569 fn typed<T>(self) -> Self;
571}
572
573impl<T> ResultExt for Result<T> {
574 fn typed<U>(self) -> Self {
575 self.map_err(Error::typed::<U>)
576 }
577}
578
579pub type Result<T> = core::result::Result<T, Error>;
581
582#[cfg(test)]
583mod tests {
584 extern crate std;
585
586 use super::SerializedMessage;
587 use super::encode;
588 use crate::DecodeError;
589 use crate::FieldDecode;
590 use crate::FieldEncode;
591 use crate::NoResources;
592 use crate::decode;
593 use crate::encoding::BorrowedCowField;
594 use crate::encoding::OwningCowField;
595 use crate::encoding::VecField;
596 use crate::protobuf::read_varint;
597 use alloc::borrow::Cow;
598 use alloc::collections::BTreeMap;
599 use alloc::vec;
600 use core::convert::Infallible;
601 use core::error::Error;
602 use core::fmt::Write;
603 use core::net::Ipv4Addr;
604 use core::net::Ipv6Addr;
605 use core::num::NonZeroU32;
606 use core::str::FromStr as _;
607 use core::time::Duration;
608 use expect_test::Expect;
609 use expect_test::expect;
610 use mesh_derive::Protobuf;
611 use std::prelude::rust_2021::*;
612 use std::println;
613
614 pub(crate) fn as_expect_str(v: &[u8]) -> String {
615 let cooked = parsed_expect_str(v).unwrap_or_else(|e| alloc::format!("PARSE ERROR: {e}\n"));
616 let raw = hex_str(v);
617 alloc::format!("{cooked}raw: {raw}")
618 }
619
620 fn hex_str(v: &[u8]) -> String {
621 v.iter()
622 .map(|x| alloc::format!("{x:02x}"))
623 .collect::<Vec<_>>()
624 .join("")
625 }
626
627 fn parsed_expect_str(mut v: &[u8]) -> Result<String, crate::Error> {
628 let mut s = String::new();
629 while !v.is_empty() {
630 let key = read_varint(&mut v)?;
631 let wire_type = (key & 7) as u32;
632 let field_number = (key >> 3) as u32;
633 write!(s, "{field_number}: ").ok();
634 match wire_type {
635 0 => {
636 let n = read_varint(&mut v)?;
637 writeln!(s, "varint {n}").ok();
638 }
639 1 => {
640 let n = u64::from_le_bytes(
641 v.get(..8)
642 .ok_or(DecodeError::EofFixed64)?
643 .try_into()
644 .unwrap(),
645 );
646 writeln!(s, "fixed64 {n:#018x}").ok();
647 v = &v[8..];
648 }
649 2 => {
650 let len = read_varint(&mut v)? as usize;
651 let data = v.get(..len).ok_or(DecodeError::EofByteArray)?;
652 if !data.is_empty() && data.iter().all(|&x| matches!(x, 0x20..=0x7e)) {
653 let data = core::str::from_utf8(data).unwrap();
654 writeln!(s, "string \"{data}\"").ok();
655 } else {
656 let data = hex_str(data);
657 writeln!(s, "bytes <{data}>").ok();
658 }
659 v = &v[len..];
660 }
661 5 => {
662 let n = u32::from_le_bytes(
663 v.get(..4)
664 .ok_or(DecodeError::EofFixed32)?
665 .try_into()
666 .unwrap(),
667 );
668 writeln!(s, "fixed32 {n:#010x}").ok();
669 v = &v[4..];
670 }
671 n => Err(DecodeError::UnknownWireType(n))?,
672 }
673 }
674 if s.is_empty() {
675 writeln!(s, "empty").ok();
676 }
677 Ok(s)
678 }
679
680 #[track_caller]
684 fn assert_roundtrips_nondeterministic<T>(t: T) -> Vec<u8>
685 where
686 T: crate::DefaultEncoding + Clone + Eq + core::fmt::Debug,
687 T::Encoding:
688 crate::MessageEncode<T, NoResources> + for<'a> crate::MessageDecode<'a, T, NoResources>,
689 {
690 println!("{t:?}");
691 let v = encode(t.clone());
692 println!("{v:x?}");
693 let t2 = decode::<T>(&v).unwrap();
694 assert_eq!(t, t2);
695 v
696 }
697
698 #[track_caller]
699 fn assert_roundtrips<T>(t: T, expect: Expect)
700 where
701 T: crate::DefaultEncoding + Clone + Eq + core::fmt::Debug,
702 T::Encoding:
703 crate::MessageEncode<T, NoResources> + for<'a> crate::MessageDecode<'a, T, NoResources>,
704 {
705 let v = assert_roundtrips_nondeterministic(t);
706 expect.assert_eq(&as_expect_str(&v));
707 }
708
709 #[track_caller]
710 fn assert_field_roundtrips<T>(t: T, expect: Expect)
711 where
712 T: crate::DefaultEncoding + Clone + Eq + core::fmt::Debug,
713 T::Encoding: FieldEncode<T, NoResources> + for<'a> FieldDecode<'a, T, NoResources>,
714 {
715 assert_roundtrips((t,), expect);
716 }
717
718 #[test]
719 fn test_field() {
720 assert_field_roundtrips(
721 5u32,
722 expect!([r#"
723 1: varint 5
724 raw: 0805"#]),
725 );
726 assert_field_roundtrips(
727 true,
728 expect!([r#"
729 1: varint 1
730 raw: 0801"#]),
731 );
732 assert_field_roundtrips(
733 "hi".to_string(),
734 expect!([r#"
735 1: string "hi"
736 raw: 0a026869"#]),
737 );
738 assert_field_roundtrips(
739 5u128,
740 expect!([r#"
741 1: bytes <05000000000000000000000000000000>
742 raw: 0a1005000000000000000000000000000000"#]),
743 );
744 assert_field_roundtrips(
745 (),
746 expect!([r#"
747 empty
748 raw: "#]),
749 );
750 assert_field_roundtrips(
751 (1, 2),
752 expect!([r#"
753 1: bytes <08021004>
754 raw: 0a0408021004"#]),
755 );
756 assert_field_roundtrips(
757 ("foo".to_string(), "bar".to_string()),
758 expect!([r#"
759 1: bytes <0a03666f6f1203626172>
760 raw: 0a0a0a03666f6f1203626172"#]),
761 );
762 assert_field_roundtrips(
763 [1, 2, 3],
764 expect!([r#"
765 1: bytes <020406>
766 raw: 0a03020406"#]),
767 );
768 assert_field_roundtrips(
769 ["abc".to_string(), "def".to_string()],
770 expect!([r#"
771 1: bytes <0a036162630a03646566>
772 raw: 0a0a0a036162630a03646566"#]),
773 );
774 assert_field_roundtrips(
775 Some(5),
776 expect!([r#"
777 1: varint 10
778 raw: 080a"#]),
779 );
780 assert_field_roundtrips(
781 Option::<u32>::None,
782 expect!([r#"
783 empty
784 raw: "#]),
785 );
786 assert_field_roundtrips(
787 vec![1, 2, 3],
788 expect!([r#"
789 1: bytes <020406>
790 raw: 0a03020406"#]),
791 );
792 assert_field_roundtrips(
793 vec!["abc".to_string(), "def".to_string()],
794 expect!([r#"
795 1: string "abc"
796 1: string "def"
797 raw: 0a036162630a03646566"#]),
798 );
799 assert_field_roundtrips(
800 Some(Some(true)),
801 expect!([r#"
802 1: bytes <0801>
803 raw: 0a020801"#]),
804 );
805 assert_field_roundtrips(
806 Some(Option::<bool>::None),
807 expect!([r#"
808 1: bytes <>
809 raw: 0a00"#]),
810 );
811 assert_field_roundtrips(
812 vec![None, Some(true), None],
813 expect!([r#"
814 1: bytes <>
815 1: bytes <0801>
816 1: bytes <>
817 raw: 0a000a0208010a00"#]),
818 );
819 #[cfg(feature = "std")]
820 assert_roundtrips_nondeterministic((std::collections::HashMap::from_iter([
821 (5u32, 6u32),
822 (4, 2),
823 ]),));
824 assert_field_roundtrips(
825 BTreeMap::from_iter([("hi".to_owned(), 6u32), ("hmm".to_owned(), 2)]),
826 expect!([r#"
827 1: bytes <0a0268691006>
828 1: bytes <0a03686d6d1002>
829 raw: 0a060a02686910060a070a03686d6d1002"#]),
830 );
831 assert_field_roundtrips(
832 Ipv4Addr::from_str("1.2.3.4").unwrap(),
833 expect!([r#"
834 1: fixed32 0x01020304
835 raw: 0d04030201"#]),
836 );
837 assert_field_roundtrips(
838 Ipv4Addr::UNSPECIFIED,
839 expect!([r#"
840 empty
841 raw: "#]),
842 );
843 assert_field_roundtrips(
844 Ipv6Addr::from_str("1:2:3:4:5:6:7:8").unwrap(),
845 expect!([r#"
846 1: bytes <00010002000300040005000600070008>
847 raw: 0a1000010002000300040005000600070008"#]),
848 );
849 assert_field_roundtrips(
850 Ipv6Addr::UNSPECIFIED,
851 expect!([r#"
852 empty
853 raw: "#]),
854 );
855 }
856
857 #[test]
858 fn test_nonzero() {
859 assert_field_roundtrips(
860 NonZeroU32::new(1).unwrap(),
861 expect!([r#"
862 1: varint 1
863 raw: 0801"#]),
864 );
865 assert_eq!(encode((5u32,)), encode((NonZeroU32::new(5).unwrap(),)));
866 assert_eq!(
867 decode::<(NonZeroU32,)>(&encode((Some(0u32),)))
868 .unwrap_err()
869 .source()
870 .unwrap()
871 .to_string(),
872 "value must be non-zero"
873 )
874 }
875
876 #[test]
877 fn test_derive_struct() {
878 #[derive(Protobuf, Debug, Clone, PartialEq, Eq)]
879 struct Foo {
880 x: u32,
881 y: u32,
882 z: String,
883 w: Option<bool>,
884 }
885
886 let foo = Foo {
887 x: 5,
888 y: 104824,
889 z: "alphabet".to_owned(),
890 w: None,
891 };
892 assert_roundtrips(
893 foo,
894 expect!([r#"
895 1: varint 5
896 2: varint 104824
897 3: string "alphabet"
898 raw: 080510f8b2061a08616c706861626574"#]),
899 );
900 }
901
902 #[test]
903 fn test_nested_derive_struct() {
904 #[derive(Protobuf, Debug, Clone, PartialEq, Eq)]
905 struct Foo {
906 x: u32,
907 y: u32,
908 b: Option<Bar>,
909 }
910
911 #[derive(Protobuf, Debug, Clone, PartialEq, Eq)]
912 struct Bar {
913 a: Option<bool>,
914 b: u32,
915 }
916
917 let foo = Foo {
918 x: 5,
919 y: 104824,
920 b: Some(Bar {
921 a: Some(true),
922 b: 5,
923 }),
924 };
925 assert_roundtrips(
926 foo,
927 expect!([r#"
928 1: varint 5
929 2: varint 104824
930 3: bytes <08011005>
931 raw: 080510f8b2061a0408011005"#]),
932 );
933 }
934
935 #[test]
936 fn test_derive_enum() {
937 #[derive(Protobuf, Debug, Clone, PartialEq, Eq)]
938 enum Foo {
939 A,
940 B(u32, String),
941 C { x: bool, y: u32 },
942 }
943
944 assert_roundtrips(
945 Foo::A,
946 expect!([r#"
947 1: bytes <>
948 raw: 0a00"#]),
949 );
950 assert_roundtrips(
951 Foo::B(12, "hi".to_owned()),
952 expect!([r#"
953 2: bytes <080c12026869>
954 raw: 1206080c12026869"#]),
955 );
956 assert_roundtrips(
957 Foo::C { x: true, y: 0 },
958 expect!([r#"
959 3: bytes <0801>
960 raw: 1a020801"#]),
961 );
962 assert_roundtrips(
963 Foo::C { x: false, y: 0 },
964 expect!([r#"
965 3: bytes <>
966 raw: 1a00"#]),
967 );
968 }
969
970 #[test]
971 fn test_vec() {
972 #[derive(Protobuf, Debug, Clone, PartialEq, Eq)]
973 struct Foo {
974 u32: Vec<u32>,
975 u8: Vec<u8>,
976 vec_no_pack: Vec<(u32,)>,
977 vec_of_vec8: Vec<Vec<u8>>,
978 vec_of_vec32: Vec<Vec<u32>>,
979 vec_of_vec_no_pack: Vec<Vec<(u32,)>>,
980 }
981
982 let foo = Foo {
983 u32: vec![1, 2, 3, 4, 5],
984 u8: b"abcdefg".to_vec(),
985 vec_no_pack: vec![(1,), (2,), (3,), (4,), (5,)],
986 vec_of_vec8: vec![b"abc".to_vec(), b"def".to_vec()],
987 vec_of_vec32: vec![vec![1, 2, 3], vec![4, 5, 6]],
988 vec_of_vec_no_pack: vec![vec![(64,), (65,)], vec![(66,), (67,)]],
989 };
990 assert_roundtrips(
991 foo,
992 expect!([r#"
993 1: bytes <0102030405>
994 2: string "abcdefg"
995 3: bytes <0801>
996 3: bytes <0802>
997 3: bytes <0803>
998 3: bytes <0804>
999 3: bytes <0805>
1000 4: string "abc"
1001 4: string "def"
1002 5: bytes <0a03010203>
1003 5: bytes <0a03040506>
1004 6: bytes <0a0208400a020841>
1005 6: bytes <0a0208420a020843>
1006 raw: 0a0501020304051207616263646566671a0208011a0208021a0208031a0208041a020805220361626322036465662a050a030102032a050a0304050632080a0208400a02084132080a0208420a020843"#]),
1007 );
1008 }
1009
1010 struct NoPackU32;
1011
1012 impl<R> FieldEncode<u32, R> for NoPackU32 {
1013 fn write_field(item: u32, writer: crate::protobuf::FieldWriter<'_, '_, R>) {
1014 writer.varint(item.into())
1015 }
1016
1017 fn compute_field_size(item: &mut u32, sizer: crate::protobuf::FieldSizer<'_>) {
1018 sizer.varint((*item).into())
1019 }
1020 }
1021
1022 impl<R> FieldDecode<'_, u32, R> for NoPackU32 {
1023 fn read_field(
1024 _item: &mut crate::inplace::InplaceOption<'_, u32>,
1025 _reader: crate::protobuf::FieldReader<'_, '_, R>,
1026 ) -> crate::Result<()> {
1027 unimplemented!()
1028 }
1029
1030 fn default_field(_item: &mut crate::inplace::InplaceOption<'_, u32>) -> crate::Result<()> {
1031 unimplemented!()
1032 }
1033 }
1034
1035 #[test]
1036 fn test_vec_alt() {
1037 {
1038 #[derive(Protobuf, Clone)]
1039 struct NoPack {
1040 #[mesh(encoding = "VecField<NoPackU32>")]
1041 v: Vec<u32>,
1042 }
1043
1044 #[derive(Protobuf)]
1045 struct CanPack {
1046 v: Vec<u32>,
1047 }
1048
1049 let no_pack = NoPack { v: vec![1, 2, 3] };
1050 let v = encode(no_pack.clone());
1051 println!("{v:x?}");
1052 let can_pack = decode::<CanPack>(&v).unwrap();
1053 assert_eq!(no_pack.v, can_pack.v);
1054 }
1055
1056 {
1057 #[derive(Protobuf, Clone)]
1058 struct NoPackNest {
1059 #[mesh(encoding = "VecField<VecField<NoPackU32>>")]
1060 v: Vec<Vec<u32>>,
1061 }
1062
1063 #[derive(Protobuf)]
1064 struct CanPackNest {
1065 v: Vec<Vec<u32>>,
1066 }
1067
1068 let no_pack = NoPackNest {
1069 v: vec![vec![1, 2, 3], vec![4, 5, 6]],
1070 };
1071 let v = encode(no_pack.clone());
1072 println!("{v:x?}");
1073 let can_pack = decode::<CanPackNest>(&v).unwrap();
1074 assert_eq!(no_pack.v, can_pack.v);
1075 }
1076 }
1077
1078 #[test]
1079 fn test_merge() {
1080 #[derive(Protobuf, Debug, Clone, PartialEq, Eq)]
1081 struct Bar(u32);
1082
1083 #[derive(Protobuf, Debug, Clone, PartialEq, Eq)]
1084 enum Enum {
1085 A(u32),
1086 B(Option<u32>, Vec<u8>),
1087 }
1088
1089 #[derive(Protobuf, Debug, Clone, PartialEq, Eq)]
1090 struct Foo {
1091 x: u32,
1092 y: u32,
1093 z: String,
1094 w: Option<bool>,
1095 v: Vec<u32>,
1096 v8: Vec<u8>,
1097 vb: Vec<Bar>,
1098 e: Enum,
1099 }
1100
1101 let foo = Foo {
1102 x: 1,
1103 y: 2,
1104 z: "abc".to_string(),
1105 w: Some(true),
1106 v: vec![1, 2, 3],
1107 v8: b"xyz".to_vec(),
1108 vb: vec![Bar(1), Bar(2)],
1109 e: Enum::B(Some(1), b"abc".to_vec()),
1110 };
1111 assert_roundtrips(
1112 foo.clone(),
1113 expect!([r#"
1114 1: varint 1
1115 2: varint 2
1116 3: string "abc"
1117 4: varint 1
1118 5: bytes <010203>
1119 6: string "xyz"
1120 7: bytes <0801>
1121 7: bytes <0802>
1122 8: bytes <120708011203616263>
1123 raw: 080110021a0361626320012a03010203320378797a3a0208013a0208024209120708011203616263"#]),
1124 );
1125 let foo2 = Foo {
1126 x: 3,
1127 y: 4,
1128 z: "def".to_string(),
1129 w: None,
1130 v: vec![4, 5, 6],
1131 v8: b"uvw".to_vec(),
1132 vb: vec![Bar(3), Bar(4), Bar(5)],
1133 e: Enum::B(None, b"def".to_vec()),
1134 };
1135 assert_roundtrips(
1136 foo2.clone(),
1137 expect!([r#"
1138 1: varint 3
1139 2: varint 4
1140 3: string "def"
1141 5: bytes <040506>
1142 6: string "uvw"
1143 7: bytes <0803>
1144 7: bytes <0804>
1145 7: bytes <0805>
1146 8: bytes <12051203646566>
1147 raw: 080310041a036465662a0304050632037576773a0208033a0208043a020805420712051203646566"#]),
1148 );
1149 let foo3 = Foo {
1150 x: 3,
1151 y: 4,
1152 z: "def".to_string(),
1153 w: Some(true),
1154 v: vec![1, 2, 3, 4, 5, 6],
1155 v8: b"xyzuvw".to_vec(),
1156 vb: vec![Bar(1), Bar(2), Bar(3), Bar(4), Bar(5)],
1157 e: Enum::B(Some(1), b"abcdef".to_vec()),
1158 };
1159 assert_roundtrips(
1160 foo3.clone(),
1161 expect!([r#"
1162 1: varint 3
1163 2: varint 4
1164 3: string "def"
1165 4: varint 1
1166 5: bytes <010203040506>
1167 6: string "xyzuvw"
1168 7: bytes <0801>
1169 7: bytes <0802>
1170 7: bytes <0803>
1171 7: bytes <0804>
1172 7: bytes <0805>
1173 8: bytes <120a08011206616263646566>
1174 raw: 080310041a0364656620012a06010203040506320678797a7576773a0208013a0208023a0208033a0208043a020805420c120a08011206616263646566"#]),
1175 );
1176 let foo = super::merge(foo, &<SerializedMessage>::from_message(foo2).data).unwrap();
1177 assert_eq!(foo, foo3);
1178 }
1179
1180 #[test]
1181 fn test_alternate_encoding() {
1182 #[derive(Protobuf, Debug, Clone, PartialEq, Eq)]
1183 struct Foo {
1184 sint32: i32,
1185 #[mesh(encoding = "mesh_protobuf::encoding::VarintField")]
1186 int32: i32,
1187 }
1188 assert_roundtrips(
1189 Foo {
1190 int32: -1,
1191 sint32: -1,
1192 },
1193 expect!([r#"
1194 1: varint 1
1195 2: varint 18446744073709551615
1196 raw: 080110ffffffffffffffffff01"#]),
1197 );
1198 assert_eq!(
1199 &encode(Foo {
1200 sint32: -1,
1201 int32: -1,
1202 }),
1203 &[8, 1, 16, 255, 255, 255, 255, 255, 255, 255, 255, 255, 1]
1204 );
1205 }
1206
1207 #[test]
1208 fn test_array() {
1209 assert_field_roundtrips(
1210 [1, 2, 3],
1211 expect!([r#"
1212 1: bytes <020406>
1213 raw: 0a03020406"#]),
1214 );
1215 assert_field_roundtrips(
1216 ["a".to_string(), "b".to_string(), "c".to_string()],
1217 expect!([r#"
1218 1: bytes <0a01610a01620a0163>
1219 raw: 0a090a01610a01620a0163"#]),
1220 );
1221 assert_field_roundtrips(
1222 [vec![1, 2, 3], vec![4, 5, 6]],
1223 expect!([r#"
1224 1: bytes <0a050a030204060a050a03080a0c>
1225 raw: 0a0e0a050a030204060a050a03080a0c"#]),
1226 );
1227 assert_field_roundtrips(
1228 [vec![1u8, 2]],
1229 expect!([r#"
1230 1: bytes <0a020102>
1231 raw: 0a040a020102"#]),
1232 );
1233 assert_field_roundtrips(
1234 [[0_u8, 1], [2, 3]],
1235 expect!([r#"
1236 1: bytes <0a0200010a020203>
1237 raw: 0a080a0200010a020203"#]),
1238 );
1239 assert_field_roundtrips(
1240 [Vec::<()>::new()],
1241 expect!([r#"
1242 1: bytes <0a00>
1243 raw: 0a020a00"#]),
1244 );
1245 assert_field_roundtrips(
1246 [vec!["abc".to_string()]],
1247 expect!([r#"
1248 1: bytes <0a050a03616263>
1249 raw: 0a070a050a03616263"#]),
1250 );
1251 }
1252
1253 #[test]
1254 fn test_nested() {
1255 #[derive(Protobuf, Debug, Clone, PartialEq, Eq)]
1256 struct Nested<T> {
1257 pub n: u32,
1258 pub foo: T,
1259 }
1260
1261 #[derive(Protobuf, Debug, Clone, PartialEq, Eq)]
1262 struct Foo {
1263 x: u32,
1264 y: u32,
1265 z: String,
1266 w: Option<bool>,
1267 }
1268
1269 let t = Nested {
1270 n: 5,
1271 foo: Foo {
1272 x: 5,
1273 y: 104824,
1274 z: "alphabet".to_owned(),
1275 w: None,
1276 },
1277 };
1278 let t2: Nested<SerializedMessage> = SerializedMessage::from_message(t.clone())
1279 .into_message()
1280 .unwrap();
1281 let t3: Nested<Foo> = SerializedMessage::from_message(t2).into_message().unwrap();
1282 assert_eq!(t, t3);
1283 }
1284
1285 #[test]
1286 fn test_lifetime() {
1287 #[derive(Protobuf)]
1288 struct Foo<'a>(&'a str);
1289
1290 let s = String::from("foo");
1291 let v = encode(Foo(&s));
1292 let foo: Foo<'_> = decode(&v).unwrap();
1293 assert_eq!(foo.0, &s);
1294 }
1295
1296 #[test]
1297 fn test_generic_lifetime() {
1298 #[derive(Protobuf)]
1299 struct Foo<T>(T);
1300
1301 let s = String::from("foo");
1302 let v = encode(Foo(s.as_str()));
1303 let foo: Foo<&str> = decode(&v).unwrap();
1304 assert_eq!(foo.0, &s);
1305 }
1306
1307 #[test]
1308 fn test_infallible() {
1309 assert!(matches!(
1310 decode::<Infallible>(&[])
1311 .unwrap_err()
1312 .source()
1313 .unwrap()
1314 .downcast_ref::<DecodeError>(),
1315 Some(DecodeError::Unexpected)
1316 ));
1317 }
1318
1319 #[test]
1320 fn test_empty_message() {
1321 #[derive(Protobuf)]
1322 struct Message(u32);
1323
1324 let v = encode(((Message(0),),));
1325 assert_eq!(&v, b"");
1326
1327 let _message: ((Message,),) = decode(&[]).unwrap();
1328 }
1329
1330 #[test]
1331 fn test_nested_empty_message() {
1332 #[derive(Debug, Clone, PartialEq, Eq, Protobuf)]
1333 struct Message(Outer, Inner);
1334
1335 #[derive(Debug, Default, Clone, PartialEq, Eq, Protobuf)]
1336 struct Outer(Inner);
1337
1338 #[derive(Debug, Default, Clone, PartialEq, Eq, Protobuf)]
1339 struct Inner(u32);
1340
1341 assert_roundtrips(
1342 Message(Default::default(), Inner(1)),
1343 expect!([r#"
1344 2: bytes <0801>
1345 raw: 12020801"#]),
1346 );
1347 }
1348
1349 #[test]
1350 fn test_transparent_message() {
1351 #[derive(Protobuf, Copy, Clone, PartialEq, Eq, Debug)]
1352 struct Inner(u32);
1353
1354 #[derive(Protobuf, Copy, Clone, PartialEq, Eq, Debug)]
1355 #[mesh(transparent)]
1356 struct TupleStruct(Inner);
1357
1358 #[derive(Protobuf, Copy, Clone, PartialEq, Eq, Debug)]
1359 #[mesh(transparent)]
1360 struct NamedStruct {
1361 x: Inner,
1362 }
1363
1364 #[derive(Protobuf, Copy, Clone, PartialEq, Eq, Debug)]
1365 #[mesh(transparent)]
1366 struct GenericStruct<T>(T);
1367
1368 assert_roundtrips(
1369 TupleStruct(Inner(5)),
1370 expect!([r#"
1371 1: varint 5
1372 raw: 0805"#]),
1373 );
1374 assert_eq!(encode(TupleStruct(Inner(5))), encode(Inner(5)));
1375 assert_eq!(encode(NamedStruct { x: Inner(5) }), encode(Inner(5)));
1376 assert_eq!(encode(GenericStruct(Inner(5))), encode(Inner(5)));
1377 }
1378
1379 #[test]
1380 fn test_transparent_field() {
1381 #[derive(Protobuf, Copy, Clone, PartialEq, Eq, Debug)]
1382 #[mesh(transparent)]
1383 struct Inner(u32);
1384
1385 #[derive(Protobuf, Copy, Clone, PartialEq, Eq, Debug)]
1386 struct Outer<T>(T);
1387
1388 assert_roundtrips(
1389 Outer(Inner(5)),
1390 expect!([r#"
1391 1: varint 5
1392 raw: 0805"#]),
1393 );
1394 assert_eq!(encode(Outer(Inner(5))), encode(Outer(5u32)));
1395 }
1396
1397 #[test]
1398 fn test_transparent_enum() {
1399 #[derive(Protobuf, Clone, PartialEq, Eq, Debug)]
1400 enum Foo {
1401 #[mesh(transparent)]
1402 Bar(u32),
1403 #[mesh(transparent)]
1404 Option(Option<u32>),
1405 #[mesh(transparent)]
1406 Vec(Vec<u32>),
1407 #[mesh(transparent)]
1408 VecNoPack(Vec<(u32,)>),
1409 }
1410
1411 assert_roundtrips(
1412 Foo::Bar(0),
1413 expect!([r#"
1414 1: varint 0
1415 raw: 0800"#]),
1416 );
1417 assert_eq!(encode(Foo::Bar(0)), encode((Some(0),)));
1418 assert_roundtrips(
1419 Foo::Option(Some(5)),
1420 expect!([r#"
1421 2: bytes <0805>
1422 raw: 12020805"#]),
1423 );
1424 assert_roundtrips(
1425 Foo::Option(None),
1426 expect!([r#"
1427 2: bytes <>
1428 raw: 1200"#]),
1429 );
1430 assert_roundtrips(
1431 Foo::Vec(vec![]),
1432 expect!([r#"
1433 3: bytes <>
1434 raw: 1a00"#]),
1435 );
1436 assert_roundtrips(
1437 Foo::Vec(vec![5]),
1438 expect!([r#"
1439 3: bytes <0a0105>
1440 raw: 1a030a0105"#]),
1441 );
1442 assert_roundtrips(
1443 Foo::VecNoPack(vec![(5,)]),
1444 expect!([r#"
1445 4: bytes <0a020805>
1446 raw: 22040a020805"#]),
1447 );
1448 }
1449
1450 #[test]
1451 fn test_cow() {
1452 #[derive(Protobuf)]
1453 struct OwnedString<'a>(#[mesh(encoding = "OwningCowField")] Cow<'a, str>);
1454 #[derive(Protobuf)]
1455 struct BorrowedString<'a>(#[mesh(encoding = "BorrowedCowField")] Cow<'a, str>);
1456 #[derive(Protobuf)]
1457 struct OwnedBytes<'a>(#[mesh(encoding = "OwningCowField")] Cow<'a, [u8]>);
1458 #[derive(Protobuf)]
1459 struct BorrowedBytes<'a>(#[mesh(encoding = "BorrowedCowField")] Cow<'a, [u8]>);
1460
1461 let s_owning: OwnedString<'_>;
1462 let v_owning: OwnedBytes<'_>;
1463
1464 {
1465 let b = encode(("abc",));
1466 let mut b2 = b.clone();
1467 b2.extend(encode(("def",)));
1468
1469 let s_borrowed: BorrowedString<'_>;
1470 let v_borrowed: BorrowedBytes<'_>;
1471 let v_borrowed2: BorrowedBytes<'_>;
1472 {
1473 let (s,): (String,) = decode(&b2).unwrap();
1474 assert_eq!(&s, "def");
1475 let (v,): (Vec<u8>,) = decode(&b2).unwrap();
1476 assert_eq!(&v, b"abcdef");
1477
1478 s_owning = decode(&b2).unwrap();
1479 let s_owning = s_owning.0;
1480 assert!(matches!(s_owning, Cow::Owned(_)));
1481 assert_eq!(s_owning.as_ref(), "def");
1482
1483 s_borrowed = decode(&b2).unwrap();
1484 let s_borrowed = s_borrowed.0;
1485 assert!(matches!(s_borrowed, Cow::Borrowed(_)));
1486 assert_eq!(s_borrowed.as_ref(), "def");
1487
1488 v_owning = decode(&b2).unwrap();
1489 let v_owning = v_owning.0;
1490 assert!(matches!(v_owning, Cow::Owned(_)));
1491 assert_eq!(v_owning.as_ref(), b"abcdef");
1492
1493 v_borrowed = decode(&b).unwrap();
1494 let v_borrowed = v_borrowed.0;
1495 assert!(matches!(v_borrowed, Cow::Borrowed(_)));
1496 assert_eq!(v_borrowed.as_ref(), b"abc");
1497
1498 v_borrowed2 = decode(&b2).unwrap();
1500 let v_borrowed2 = v_borrowed2.0;
1501 assert!(matches!(v_borrowed2, Cow::Owned(_)));
1502 assert_eq!(v_borrowed2.as_ref(), b"abcdef");
1503 }
1504 }
1505 }
1506
1507 #[test]
1508 fn test_duration() {
1509 assert_roundtrips(
1510 Duration::ZERO,
1511 expect!([r#"
1512 empty
1513 raw: "#]),
1514 );
1515 assert_roundtrips(
1516 Duration::from_secs(1),
1517 expect!([r#"
1518 1: varint 1
1519 raw: 0801"#]),
1520 );
1521 assert_roundtrips(
1522 Duration::from_secs(1) + Duration::from_nanos(10000),
1523 expect!([r#"
1524 1: varint 1
1525 2: varint 10000
1526 raw: 080110904e"#]),
1527 );
1528 assert_roundtrips(
1529 Duration::from_secs(1) - Duration::from_nanos(10000),
1530 expect!([r#"
1531 2: varint 999990000
1532 raw: 10f0c5eadc03"#]),
1533 );
1534 decode::<Duration>(&encode((-1i64 as u64, 0u32))).unwrap_err();
1535 assert_eq!(
1536 decode::<Duration>(&encode((1u64, 1u32))).unwrap(),
1537 Duration::from_secs(1) + Duration::from_nanos(1)
1538 );
1539 }
1540
1541 #[test]
1542 fn test_failure_recovery() {
1543 let m = encode(("foo", 2, 3));
1544 decode::<(String, String, String)>(&m).unwrap_err();
1545 }
1546
1547 #[test]
1552 fn test_transparent_enum_variant_switch() {
1553 #[derive(Protobuf, Clone, PartialEq, Eq, Debug)]
1554 enum Switchy {
1555 #[mesh(transparent)]
1556 Str(String),
1557 #[mesh(transparent)]
1558 Num(u32),
1559 }
1560
1561 let num_bytes = encode(Switchy::Num(42));
1568 let str_bytes = encode(Switchy::Str("hello".to_owned()));
1569 let mut combined = num_bytes;
1570 combined.extend_from_slice(&str_bytes);
1571
1572 let result: Switchy = decode(&combined).unwrap();
1573 assert_eq!(result, Switchy::Str("hello".to_owned()));
1574 }
1575}