Skip to main content

mesh_protobuf/
lib.rs

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4//! Low-level serialization and deserialization engine for mesh messages.
5//!
6//! Most code won't use this directly but will instead use one of the derive
7//! macros:
8//!
9//! - [`derive@Protobuf`] — generates tagged protobuf encoding with explicit
10//!   field numbers (`#[mesh(N)]`). Use for durable saved state that must be
11//!   forward- and backward-compatible.
12//! - `MeshPayload` (in `mesh_derive`) — generates positional encoding without
13//!   field numbers. Use for internal runtime messages where compatibility
14//!   across versions is not required.
15//!
16//! # Wire format
17//!
18//! The encoding is a superset of
19//! [Protocol Buffers](https://developers.google.com/protocol-buffers/docs/encoding),
20//! allowing protobuf clients and mesh to interoperate for a subset of types.
21//! The extension adds a sideband resource channel for transferring OS resources
22//! (file descriptors, handles, ports) that cannot be serialized to bytes.
23//!
24//! # Why not serde?
25//!
26//! serde takes values by reference (`&self`), which makes it impossible to
27//! transfer ownership of resources like ports, handles, and file descriptors.
28//! mesh's encoding takes values by value, consuming the source and producing
29//! the value at the destination. This is the fundamental design difference
30//! that enables mesh's resource-transfer model.
31//!
32//! # `no_std` support
33//!
34//! This crate is `no_std` by default (with `alloc`). Enable the `std` feature
35//! for additional functionality.
36
37// UNSAFETY: Serialization and deserialization of structs directly.
38#![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/// Associates the default encoder/decoder type for converting an object to/from
81/// protobuf format.
82#[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    /// The encoding to use for the serialization.
91    ///
92    /// This type may or may not implement and of the four traits
93    /// ([`MessageEncode`], [`MessageDecode`], [`FieldEncode`], [`FieldDecode`],
94    /// since a type may only be serializable and not deserializable, for
95    /// example.
96    type Encoding;
97}
98
99/// Trait for types that can be encoded and decoded as a protobuf message.
100pub trait Protobuf: DefaultEncoding<Encoding = <Self as Protobuf>::Encoding> + Sized {
101    /// The default encoding for `Self`.
102    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
119/// Trait for types implementing [`Protobuf`] and having an associated protobuf
120/// message description.
121pub trait DescribedProtobuf: Protobuf {
122    /// The message description.
123    const DESCRIPTION: MessageDescription<'static>;
124    /// The type URL for this message.
125    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
136/// The `MessageEncode` trait provides a message encoder for type `T`.
137///
138/// `R` is the external resource type, which allows encoding objects with
139/// non-protobuf resources such as file descriptors. Most implementors of this
140/// trait will be generic over all `R`.
141pub trait MessageEncode<T, R>: Sized {
142    /// Writes `item` as a message.
143    fn write_message(item: T, writer: protobuf::MessageWriter<'_, '_, R>);
144
145    /// Computes the size of `item` as a message.
146    ///
147    /// Encoding will panic if the `write_message` call writes a different
148    /// number of bytes than computed by this call.
149    ///
150    /// Takes a mut reference to allow mutating/stabilizing the value so that
151    /// the subsequent call to `write_message` acts on the same value as this
152    /// call.
153    fn compute_message_size(item: &mut T, sizer: protobuf::MessageSizer<'_>);
154}
155
156/// The `MessageEncode` trait provides a message decoder for type `T`.
157///
158/// `R` is the external resource type, which allows decoding objects with
159/// non-protobuf resources such as file descriptors. Most implementors of this
160/// trait will be generic over all `R`.
161pub trait MessageDecode<'a, T, R>: Sized {
162    /// Reads a message into `item`.
163    fn read_message(
164        item: &mut InplaceOption<'_, T>,
165        reader: protobuf::MessageReader<'a, '_, R>,
166    ) -> Result<()>;
167}
168
169/// The `FieldEncode` trait provides a field encoder for type `T`.
170///
171/// `R` is the external resource type, which allows encoding objects with
172/// non-protobuf resources such as file descriptors. Most implementors of this
173/// trait will be generic over all `R`.
174pub trait FieldEncode<T, R>: Sized {
175    /// Writes `item` as a field.
176    fn write_field(item: T, writer: protobuf::FieldWriter<'_, '_, R>);
177
178    /// Computes the size of `item` as a field.
179    ///
180    /// Encoding will panic if the `write_field` call writes a different number
181    /// of bytes than computed by this call.
182    ///
183    /// Takes a mut reference to allow mutating/stabilizing the value so that
184    /// the subsequence call to `write_field` acts on the same value as this
185    /// call.
186    fn compute_field_size(item: &mut T, sizer: protobuf::FieldSizer<'_>);
187
188    /// Returns the encoder for writing multiple instances of this field in a
189    /// packed list, or `None` if there is no packed encoding for this type.
190    fn packed<'a>() -> Option<&'a dyn PackedEncode<T>>
191    where
192        T: 'a,
193    {
194        None
195    }
196
197    /// Returns whether this field should be wrapped in a message when encoded
198    /// nested in a sequence (such as a repeated field).
199    ///
200    /// This is necessary to avoid ambiguity between the repeated inner and
201    /// outer values.
202    fn wrap_in_sequence() -> bool {
203        false
204    }
205
206    /// Writes this field as part of a sequence, wrapping it in a message if
207    /// necessary.
208    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    /// Computes the size of this field as part of a sequence, including the
217    /// size of a wrapping message.
218    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    /// The table encoder entry for this type, used in types from
227    /// [`table::encode`].
228    ///
229    /// This should not be overridden by implementations.
230    const ENTRY: EncoderEntry<T, R> = EncoderEntry::custom::<Self>();
231}
232
233/// Encoder methods for writing packed fields.
234pub trait PackedEncode<T> {
235    /// Writes a slice of data in packed format.
236    fn write_packed(&self, data: &[T], writer: protobuf::PackedWriter<'_, '_>);
237
238    /// Computes the size of the data in packed format.
239    fn compute_packed_size(&self, data: &[T], sizer: protobuf::PackedSizer<'_>);
240
241    /// If `true`, when this type is encoded as part of a sequence, it cannot be
242    /// encoded with a normal repeated encoding and must be packed. This is used
243    /// to determine if a nested repeated sequence needs to be wrapped in a
244    /// message to avoid ambiguity.
245    fn must_pack(&self) -> bool;
246}
247
248/// The `FieldEncode` trait provides a field decoder for type `T`.
249///
250/// `R` is the external resource type, which allows decoding objects with
251/// non-protobuf resources such as file descriptors. Most implementors of this
252/// trait will be generic over all `R`.
253pub trait FieldDecode<'a, T, R>: Sized {
254    /// Reads a field into `item`.
255    fn read_field(
256        item: &mut InplaceOption<'_, T>,
257        reader: protobuf::FieldReader<'a, '_, R>,
258    ) -> Result<()>;
259
260    /// Instantiates `item` with its default value, if there is one.
261    ///
262    /// If an implementation returns `Ok(())`, then it must have set an item.
263    /// Callers of this method may panic otherwise.
264    fn default_field(item: &mut InplaceOption<'_, T>) -> Result<()>;
265
266    /// Unless `packed()::must_pack()` is true, the sequence decoder must detect
267    /// the encoding (packed or not) and call the appropriate method.
268    fn packed<'p, C: CopyExtend<T>>() -> Option<&'p dyn PackedDecode<'a, T, C>>
269    where
270        T: 'p,
271    {
272        None
273    }
274
275    /// Returns whether this field is wrapped in a message when encoded nested
276    /// in a sequence (such as a repeated field).
277    fn wrap_in_sequence() -> bool {
278        false
279    }
280
281    /// Reads this field that was encoded as part of a sequence, unwrapping it
282    /// from a message if necessary.
283    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    /// The table decoder entry for this type, used in types from
295    /// [`table::decode`].
296    ///
297    /// This should not be overridden by implementations.
298    const ENTRY: DecoderEntry<'a, T, R> = DecoderEntry::custom::<Self>();
299}
300
301/// Methods for decoding a packed field.
302pub trait PackedDecode<'a, T, C> {
303    /// Reads from the packed format into `data`.
304    fn read_packed(&self, data: &mut C, reader: &mut protobuf::PackedReader<'a>) -> Result<()>;
305
306    /// If `true`, when this type is decoded as part of a sequence, it must be
307    /// done with `read_packed` and not the field methods.
308    fn must_pack(&self) -> bool;
309}
310
311/// Trait for collections that can be extended by a slice of `T: Copy`.
312pub trait CopyExtend<T> {
313    /// Pushes `item` onto the collection.
314    fn push(&mut self, item: T)
315    where
316        T: Copy;
317
318    /// Extends the collection by `items`.
319    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
340/// Encoder for a wrapper message used when a repeated field is directly nested
341/// inside another repeated field.
342struct 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
376/// Encodes a message with its default encoding.
377pub 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
384/// Decodes a message with its default encoding.
385pub 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
394/// Merges message fields into an existing message.
395pub 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
404/// An empty resources type, used when an encoding does not require any external
405/// resources (such as files or mesh channels).
406pub enum NoResources {}
407
408/// A serialized message, consisting of binary data and a list
409/// of resources.
410#[derive(Debug)]
411pub struct SerializedMessage<R = NoResources> {
412    /// The message data.
413    pub data: Vec<u8>,
414    /// The message resources.
415    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    /// Serializes a message.
429    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    /// Deserializes a message.
438    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/// A decoding error.
456#[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/// The cause of a decoding error.
466#[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    /// Creates a new error.
524    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    /// Returns a new error with an additional type context added.
532    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
567/// Extension trait to add type context to [`Error`].
568pub trait ResultExt {
569    /// Add type `T`'s name to the error.
570    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
579/// A decoding result.
580pub 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    /// Asserts that a type roundtrips through encoding and decoding without
681    /// verifying the actual contents. This is useful for types that have
682    /// a non-deterministic order (e.g., `HashMap`).
683    #[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                // This one is owned because it has to append more data.
1499                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 that decoding a transparent enum where the wire data contains two
1548    /// different variant fields (protobuf "last one wins") does not corrupt
1549    /// memory. The second variant decode must properly drop the first variant
1550    /// before overwriting its storage.
1551    #[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        // Encode Num first, then Str. Concatenating their bytes simulates a
1562        // protobuf message with two oneof fields present (legal per the spec;
1563        // last one wins). This order matters: decoding Str when Num is already
1564        // stored writes a String at offset 0 (because size_of::<String>() ==
1565        // size_of::<Switchy>()), overwriting the full enum. Without the fix,
1566        // the old variant is then dropped with corrupted memory (double-free).
1567        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}