Skip to main content

buffa/
view.rs

1//! Zero-copy borrowed message views.
2//!
3//! Buffa generates two representations for each protobuf message:
4//!
5//! - **Owned** (`MyMessage`): uses `String`, `Vec<u8>`, `Vec<T>` for fields.
6//!   Suitable for building messages, long-lived storage, and mutation.
7//!
8//! - **Borrowed** (`MyMessageView<'a>`): uses `&'a str`, `&'a [u8]`, and
9//!   slice-backed repeated fields. Borrows directly from the input buffer
10//!   for zero-copy deserialization on the read path.
11//!
12//! # Motivation
13//!
14//! In a typical RPC handler, the request is parsed from a buffer, fields are
15//! read, and the buffer is discarded. With owned types, every string and bytes
16//! field requires an allocation + copy. With view types, strings and bytes
17//! borrow directly from the input buffer — no allocation at all.
18//!
19//! This is analogous to how Cap'n Proto's Rust implementation works, and how
20//! Go achieves zero-copy string deserialization via its garbage collector.
21//!
22//! # Usage pattern
23//!
24//! ```rust,ignore
25//! // Decode a view (zero-copy, borrows from `wire_bytes`)
26//! let request = MyRequestView::decode_view(&wire_bytes)?;
27//! println!("name: {}", request.name);  // &str, no allocation
28//!
29//! // Build an owned response
30//! let response = MyResponse {
31//!     id: request.id,
32//!     status: "ok".into(),
33//!     ..Default::default()
34//! };
35//!
36//! // Convert view to owned if needed for storage
37//! let owned: MyRequest = request.to_owned_message();
38//! ```
39//!
40//! # Generated code shape
41//!
42//! For a message like:
43//! ```protobuf
44//! message Person {
45//!   string name = 1;
46//!   int32 id = 2;
47//!   bytes avatar = 3;
48//!   repeated string tags = 4;
49//!   Address address = 5;
50//! }
51//! ```
52//!
53//! Buffa generates:
54//! ```rust,ignore
55//! // Owned type (heap-allocated strings and vecs)
56//! pub struct Person {
57//!     pub name: String,
58//!     pub id: i32,
59//!     pub avatar: Vec<u8>,
60//!     pub tags: Vec<String>,
61//!     pub address: MessageField<Address>,
62//!     #[doc(hidden)] pub __buffa_unknown_fields: UnknownFields,
63//!     #[doc(hidden)] pub __buffa_cached_size: /* internal */,
64//! }
65//!
66//! // Borrowed view type (zero-copy from input buffer)
67//! pub struct PersonView<'a> {
68//!     pub name: &'a str,
69//!     pub id: i32,
70//!     pub avatar: &'a [u8],
71//!     pub tags: RepeatedView<'a, &'a str>,
72//!     pub address: MessageFieldView<AddressView<'a>>,
73//!     pub __buffa_unknown_fields: UnknownFieldsView<'a>,
74//! }
75//! ```
76
77use crate::error::DecodeError;
78use crate::message::Message as _;
79use bytes::Bytes;
80
81/// Trait for zero-copy borrowed message views.
82///
83/// View types borrow from the input buffer and provide read-only access
84/// to message fields without allocation. Each generated `MyMessageView<'a>`
85/// implements this trait.
86///
87/// The lifetime `'a` ties the view to the input buffer — the view cannot
88/// outlive the buffer it was decoded from.
89pub trait MessageView<'a>: Sized {
90    /// The corresponding owned message type.
91    type Owned: crate::Message;
92
93    /// Decode a view from a buffer, borrowing string/bytes fields directly.
94    ///
95    /// The returned view borrows from `buf`'s underlying bytes. The caller
96    /// must ensure the buffer is contiguous (e.g., `&[u8]` or `bytes::Bytes`).
97    fn decode_view(buf: &'a [u8]) -> Result<Self, DecodeError>;
98
99    /// Decode a view with a custom recursion depth limit.
100    ///
101    /// Used by [`DecodeOptions::decode_view`](crate::DecodeOptions::decode_view)
102    /// to pass a non-default recursion budget. The default implementation
103    /// delegates to [`decode_view`](Self::decode_view) (ignoring the limit);
104    /// generated code overrides this to call `_decode_depth(buf, depth)`.
105    fn decode_view_with_limit(buf: &'a [u8], _depth: u32) -> Result<Self, DecodeError> {
106        Self::decode_view(buf)
107    }
108
109    /// Convert this view to the owned message type.
110    ///
111    /// This allocates and copies all borrowed fields.
112    fn to_owned_message(&self) -> Self::Owned;
113}
114
115/// Provides access to a lazily-initialized default view instance.
116///
117/// View types implement this trait so that [`MessageFieldView`] can
118/// dereference to a default when unset, just as [`MessageField`](crate::MessageField)
119/// does for owned types via [`DefaultInstance`](crate::DefaultInstance).
120///
121/// Generated view types like `FooView<'a>` contain only covariant borrows
122/// (`&'a str`, `&'a [u8]`, etc.). A default view contains only `'static`
123/// data (`""`, `&[]`, `0`), so a `&'static FooView<'static>` can be safely
124/// reinterpreted as `&'static FooView<'a>` for any `'a` via covariance.
125///
126/// This trait is implemented for the `'static` instantiation (e.g.,
127/// `FooView<'static>`) and the [`MessageFieldView`] `Deref` impl uses
128/// a lifetime transmute to serve it for any `'a`.
129///
130/// # Safety
131///
132/// Implementors must ensure:
133/// 1. The returned reference points to a validly-initialized default
134///    instance in a `'static` location that is never mutated.
135/// 2. The type is **covariant** in all lifetime parameters — the default
136///    `'static` instance must be safely reinterpretable at any shorter
137///    lifetime.
138pub unsafe trait DefaultViewInstance: Default + 'static {
139    /// Return a reference to the single default view instance.
140    fn default_view_instance() -> &'static Self;
141}
142
143/// A borrowed view of an optional message field.
144///
145/// Analogous to [`MessageField<T>`](crate::MessageField) but for the view
146/// layer. Like `MessageField`, the inner view is **boxed** — recursive
147/// message types (`Foo { NestedMessage { corecursive: Foo } }`) would
148/// otherwise have infinite size. The box is API-transparent: `Deref`
149/// returns `&V`, and `set()` takes `V` by value.
150///
151/// When `V` implements [`HasDefaultViewInstance`], this type implements
152/// [`Deref<Target = V>`](core::ops::Deref), returning a reference to a
153/// static default instance when the field is unset — making view code
154/// identical to owned code for field access:
155///
156/// ```rust,ignore
157/// // Both work the same, regardless of whether `address` is set:
158/// let city = owned_msg.address.city;    // MessageField<Address>
159/// let city = view_msg.address.city;     // MessageFieldView<AddressView>
160/// ```
161///
162/// The lifetime of the contained view type `V` (e.g. `AddressView<'a>`)
163/// ties this to the input buffer — no separate lifetime parameter is
164/// needed here.
165#[derive(Clone, Debug)]
166pub struct MessageFieldView<V> {
167    inner: Option<alloc::boxed::Box<V>>,
168}
169
170impl<V> MessageFieldView<V> {
171    /// An unset field (the default).
172    #[inline]
173    pub const fn unset() -> Self {
174        Self { inner: None }
175    }
176
177    /// A set field with the given view value.
178    #[inline]
179    pub fn set(v: V) -> Self {
180        Self {
181            inner: Some(alloc::boxed::Box::new(v)),
182        }
183    }
184
185    /// Returns `true` if the field has a value.
186    #[inline]
187    pub fn is_set(&self) -> bool {
188        self.inner.is_some()
189    }
190
191    /// Returns `true` if the field has no value.
192    #[inline]
193    pub fn is_unset(&self) -> bool {
194        self.inner.is_none()
195    }
196
197    /// Get a reference to the inner view, or `None` if unset.
198    #[inline]
199    pub fn as_option(&self) -> Option<&V> {
200        self.inner.as_deref()
201    }
202
203    /// Get a mutable reference to the inner view, or `None` if unset.
204    ///
205    /// Used by generated decode code to merge a second occurrence of a
206    /// message field into an existing value (proto merge semantics).
207    #[inline]
208    pub fn as_mut(&mut self) -> Option<&mut V> {
209        self.inner.as_deref_mut()
210    }
211}
212
213impl<V> Default for MessageFieldView<V> {
214    #[inline]
215    fn default() -> Self {
216        Self::unset()
217    }
218}
219
220/// Marker trait linking a lifetime-parameterized view type `V` (e.g.,
221/// `FooView<'a>`) to its `'static` instantiation that implements
222/// [`DefaultViewInstance`]. Generated code implements this for every
223/// view type.
224///
225/// The `default_view_ptr` method returns a raw pointer to avoid forcing
226/// `Self: 'static` — view types have a lifetime parameter that may not
227/// be `'static`, but the default instance only contains `'static` data
228/// and the types are covariant, so the pointer cast is sound.
229///
230/// # Safety
231///
232/// `Self` must be layout-identical to `Self::Static` (i.e., the only
233/// difference is the lifetime parameter), and `Self` must be covariant
234/// in that lifetime.
235pub unsafe trait HasDefaultViewInstance {
236    /// The `'static` instantiation of this view type.
237    type Static: DefaultViewInstance;
238
239    /// Return a pointer to the static default instance, erasing the
240    /// lifetime so it can be used for any `'a`.
241    fn default_view_ptr() -> *const u8 {
242        // Return as a thin `*const u8` to avoid Sized constraints on Self.
243        Self::Static::default_view_instance() as *const Self::Static as *const u8
244    }
245}
246
247impl<V: HasDefaultViewInstance> core::ops::Deref for MessageFieldView<V> {
248    type Target = V;
249
250    #[inline]
251    fn deref(&self) -> &V {
252        match &self.inner {
253            Some(v) => v,
254            // SAFETY: `default_view_ptr` returns a pointer to a `'static`
255            // default instance. The `HasDefaultViewInstance` safety contract
256            // guarantees the type is covariant, so the `'static` instance
257            // is valid at any shorter lifetime. The pointer is non-null and
258            // points to an initialized, immutable, `'static` value.
259            None => unsafe { &*(V::default_view_ptr() as *const V) },
260        }
261    }
262}
263
264/// Wire-equivalent equality: `Unset` equals `Set(v)` when `v` equals the
265/// default instance.
266///
267/// This matches [`MessageField::eq`](crate::MessageField) on the owned side,
268/// so `view_a == view_b` agrees with
269/// `view_a.to_owned_message() == view_b.to_owned_message()`.
270///
271/// The comparison against the default reuses the same covariant-lifetime
272/// pointer cast already established by the [`Deref`](core::ops::Deref) impl.
273impl<V: PartialEq + HasDefaultViewInstance> PartialEq for MessageFieldView<V> {
274    fn eq(&self, other: &Self) -> bool {
275        match (&self.inner, &other.inner) {
276            // Short-circuit: two unset fields are equal regardless of whether
277            // V::PartialEq is reflexive (e.g. a view containing an f64 NaN).
278            (None, None) => true,
279            // At least one side is set. Deref handles None → default.
280            _ => {
281                <Self as core::ops::Deref>::deref(self) == <Self as core::ops::Deref>::deref(other)
282            }
283        }
284    }
285}
286
287impl<V: Eq + HasDefaultViewInstance> Eq for MessageFieldView<V> {}
288
289/// A borrowed view of a repeated field.
290///
291/// For scalar repeated fields, this is backed by a decoded `Vec` (scalars
292/// can't be zero-copy because they require varint decoding). For string and
293/// bytes repeated fields, elements borrow from the input buffer.
294#[derive(Clone, Debug, PartialEq, Eq)]
295pub struct RepeatedView<'a, T> {
296    elements: alloc::vec::Vec<T>,
297    _marker: core::marker::PhantomData<&'a ()>,
298}
299
300impl<'a, T> RepeatedView<'a, T> {
301    /// Create from a vec of decoded elements.
302    pub fn new(elements: alloc::vec::Vec<T>) -> Self {
303        Self {
304            elements,
305            _marker: core::marker::PhantomData,
306        }
307    }
308
309    /// Returns the number of elements.
310    pub fn len(&self) -> usize {
311        self.elements.len()
312    }
313
314    /// Returns `true` if the repeated field contains no elements.
315    pub fn is_empty(&self) -> bool {
316        self.elements.is_empty()
317    }
318
319    /// Append an element (used by generated `decode_view` code).
320    #[doc(hidden)]
321    pub fn push(&mut self, elem: T) {
322        self.elements.push(elem);
323    }
324
325    /// Returns an iterator over the elements.
326    pub fn iter(&self) -> core::slice::Iter<'_, T> {
327        self.elements.iter()
328    }
329}
330
331impl<'a, T> Default for RepeatedView<'a, T> {
332    fn default() -> Self {
333        Self {
334            elements: alloc::vec::Vec::new(),
335            _marker: core::marker::PhantomData,
336        }
337    }
338}
339
340impl<'a, T> core::ops::Deref for RepeatedView<'a, T> {
341    type Target = [T];
342
343    fn deref(&self) -> &[T] {
344        &self.elements
345    }
346}
347
348impl<'a, T> IntoIterator for RepeatedView<'a, T> {
349    type Item = T;
350    type IntoIter = alloc::vec::IntoIter<T>;
351
352    fn into_iter(self) -> Self::IntoIter {
353        self.elements.into_iter()
354    }
355}
356
357impl<'b, 'a, T> IntoIterator for &'b RepeatedView<'a, T> {
358    type Item = &'b T;
359    type IntoIter = core::slice::Iter<'b, T>;
360
361    fn into_iter(self) -> Self::IntoIter {
362        self.elements.iter()
363    }
364}
365
366/// A borrowed view of a map field.
367///
368/// Protobuf `map<K, V>` fields are encoded as repeated sub-messages, each
369/// containing a key (field 1) and value (field 2). This type stores the
370/// decoded entries in a `Vec<(K, V)>`, borrowing string and bytes keys/values
371/// directly from the input buffer.
372///
373/// Lookup is O(n) linear scan, which is appropriate for the typically small
374/// maps found in protobuf messages (metadata labels, headers, etc.).
375/// If duplicate keys appear on the wire, [`get`](MapView::get) returns the
376/// last occurrence (last-write-wins, per the protobuf spec).
377///
378/// For larger maps where O(1) lookup matters, collect into a `HashMap`:
379///
380/// ```ignore
381/// use std::collections::HashMap;
382/// let index: HashMap<&str, &str> = view.labels.into_iter().collect();
383/// ```
384///
385/// Duplicate keys resolve last-write-wins in the collected map (matching
386/// proto map semantics), since `HashMap::from_iter` keeps the last value.
387///
388/// # Allocation
389///
390/// Like [`RepeatedView`], the `Vec` backing store requires allocation.
391/// The individual keys and values borrow from the input buffer where possible
392/// (string keys as `&'a str`, bytes values as `&'a [u8]`).
393#[derive(Clone, Debug, PartialEq, Eq)]
394pub struct MapView<'a, K, V> {
395    entries: alloc::vec::Vec<(K, V)>,
396    _marker: core::marker::PhantomData<&'a ()>,
397}
398
399impl<'a, K, V> MapView<'a, K, V> {
400    /// Returns the number of entries (including duplicates).
401    pub fn len(&self) -> usize {
402        self.entries.len()
403    }
404
405    /// Returns `true` if there are no entries.
406    pub fn is_empty(&self) -> bool {
407        self.entries.is_empty()
408    }
409
410    /// Append a key-value pair (used by generated `decode_view` code).
411    #[doc(hidden)]
412    pub fn push(&mut self, key: K, value: V) {
413        self.entries.push((key, value));
414    }
415
416    /// Iterate over all entries in wire order.
417    ///
418    /// If duplicate keys exist, all occurrences are yielded.
419    pub fn iter(&self) -> core::slice::Iter<'_, (K, V)> {
420        self.entries.iter()
421    }
422
423    /// Iterate over all keys in wire order.
424    pub fn keys(&self) -> impl Iterator<Item = &K> {
425        self.entries.iter().map(|(k, _)| k)
426    }
427
428    /// Iterate over all values in wire order.
429    pub fn values(&self) -> impl Iterator<Item = &V> {
430        self.entries.iter().map(|(_, v)| v)
431    }
432
433    /// Look up a value by key, returning the last occurrence (last-write-wins).
434    ///
435    /// Accepts any type that `K` can borrow as, so `map.get("key")` works
436    /// when `K` is `&str`. O(n) scan.
437    pub fn get<Q>(&self, key: &Q) -> Option<&V>
438    where
439        K: core::borrow::Borrow<Q>,
440        Q: PartialEq + ?Sized,
441    {
442        self.entries
443            .iter()
444            .rev()
445            .find(|(k, _)| k.borrow() == key)
446            .map(|(_, v)| v)
447    }
448
449    /// Returns `true` if an entry with the given key exists.
450    pub fn contains_key<Q>(&self, key: &Q) -> bool
451    where
452        K: core::borrow::Borrow<Q>,
453        Q: PartialEq + ?Sized,
454    {
455        self.entries.iter().any(|(k, _)| k.borrow() == key)
456    }
457}
458
459impl<'a, K, V> Default for MapView<'a, K, V> {
460    fn default() -> Self {
461        Self {
462            entries: alloc::vec::Vec::new(),
463            _marker: core::marker::PhantomData,
464        }
465    }
466}
467
468impl<'b, 'a, K, V> IntoIterator for &'b MapView<'a, K, V> {
469    type Item = &'b (K, V);
470    type IntoIter = core::slice::Iter<'b, (K, V)>;
471
472    fn into_iter(self) -> Self::IntoIter {
473        self.entries.iter()
474    }
475}
476
477impl<'a, K, V> IntoIterator for MapView<'a, K, V> {
478    type Item = (K, V);
479    type IntoIter = alloc::vec::IntoIter<(K, V)>;
480
481    fn into_iter(self) -> Self::IntoIter {
482        self.entries.into_iter()
483    }
484}
485
486/// A borrowed view of unknown fields.
487///
488/// Stores raw byte slices from the input buffer rather than decoded values,
489/// enabling zero-copy round-tripping of unknown fields.
490#[derive(Clone, Debug, Default)]
491pub struct UnknownFieldsView<'a> {
492    /// Raw (tag, value) byte spans from the input buffer.
493    raw_spans: alloc::vec::Vec<&'a [u8]>,
494}
495
496impl<'a> UnknownFieldsView<'a> {
497    /// Creates an empty view.
498    pub fn new() -> Self {
499        Self::default()
500    }
501
502    #[doc(hidden)]
503    pub fn push_raw(&mut self, span: &'a [u8]) {
504        self.raw_spans.push(span);
505    }
506
507    /// Returns `true` if no unknown fields were recorded.
508    pub fn is_empty(&self) -> bool {
509        self.raw_spans.is_empty()
510    }
511
512    /// Total byte length of all unknown field data.
513    pub fn encoded_len(&self) -> usize {
514        self.raw_spans.iter().map(|s| s.len()).sum()
515    }
516
517    /// Convert to an owned [`UnknownFields`](crate::UnknownFields) by parsing all stored raw byte spans.
518    ///
519    /// Each span is a complete (tag + value) record as it appeared on the wire.
520    /// Parsing uses [`crate::encoding::decode_unknown_field`] with the full
521    /// recursion limit so deeply nested group fields are handled correctly.
522    ///
523    /// # Errors
524    ///
525    /// Returns `Err` if any stored span is malformed — which should not occur
526    /// when the view was produced by `decode_view` from valid wire data.
527    pub fn to_owned(&self) -> Result<crate::UnknownFields, crate::DecodeError> {
528        use crate::encoding::{decode_unknown_field, Tag};
529
530        let mut out = crate::UnknownFields::new();
531        for span in &self.raw_spans {
532            let mut cur: &[u8] = span;
533            let tag = Tag::decode(&mut cur)?;
534            let field = decode_unknown_field(tag, &mut cur, crate::RECURSION_LIMIT)?;
535            out.push(field);
536        }
537        Ok(out)
538    }
539}
540
541/// An owned, `'static` container for a decoded message view.
542///
543/// `OwnedView` holds a [`Bytes`] buffer alongside the decoded view, ensuring
544/// the view's borrows remain valid for the container's lifetime. It implements
545/// [`Deref<Target = V>`](core::ops::Deref), so view fields are accessed
546/// directly — no `.get()` or unwrapping needed.
547///
548/// This type is `Send + Sync + 'static`, making it suitable for use across
549/// async boundaries, in tower services, and anywhere a `'static` bound is
550/// required.
551///
552/// # When to use
553///
554/// Use `OwnedView` when you need a zero-copy view that outlives the scope
555/// where the buffer was received — for example, in an RPC handler where the
556/// framework requires `'static` types:
557///
558/// ```rust,ignore
559/// use buffa::view::OwnedView;
560/// use bytes::Bytes;
561///
562/// let bytes: Bytes = receive_request_body().await;
563/// let view = OwnedView::<PersonView>::decode(bytes)?;
564///
565/// // Direct field access via Deref — no .get() needed
566/// println!("name: {}", view.name);
567/// println!("id: {}", view.id);
568///
569/// // Convert to owned if you need to store or mutate
570/// let owned: Person = view.to_owned_message();
571/// ```
572///
573/// For scoped access where the buffer's lifetime is known, use
574/// [`MessageView::decode_view`] directly — it has zero overhead beyond the
575/// decode itself.
576///
577/// # Safety
578///
579/// Internally, `OwnedView` extends the view's lifetime to `'static` via
580/// `transmute`. This is sound because:
581///
582/// 1. [`Bytes`] is reference-counted — its heap data pointer is stable across
583///    moves. The view's borrows always point into valid memory.
584/// 2. [`Bytes`] is immutable — the underlying data cannot be modified while
585///    borrowed.
586/// 3. A manual [`Drop`] impl explicitly drops the view before the bytes,
587///    ensuring no dangling references during cleanup. The view field uses
588///    [`ManuallyDrop`](core::mem::ManuallyDrop) to prevent the automatic
589///    drop from running out of order.
590pub struct OwnedView<V> {
591    // INVARIANT: `view` borrows from `bytes`. The `Drop` impl ensures
592    // `view` is dropped before `bytes`. `ManuallyDrop` prevents the compiler
593    // from dropping `view` automatically — our `Drop` impl handles it.
594    //
595    // CONSTRUCTORS: any constructor added here MUST ensure the view's
596    // borrows point into `self.bytes` (not into caller-owned memory).
597    // The auto-`Send`/`Sync` derivation is only sound under that invariant
598    // — there is no longer a `V: 'static` bound on `Send` to act as a
599    // second gate. See the comment block above `send_sync_assertions` below.
600    view: core::mem::ManuallyDrop<V>,
601    bytes: Bytes,
602}
603
604impl<V> Drop for OwnedView<V> {
605    fn drop(&mut self) {
606        // SAFETY: `view` borrows from `bytes`. We must drop the view before
607        // bytes is dropped. `ManuallyDrop::drop` runs V's destructor in place
608        // without moving it. After this, `bytes` drops automatically via the
609        // compiler-generated drop glue.
610        unsafe {
611            core::mem::ManuallyDrop::drop(&mut self.view);
612        }
613    }
614}
615
616impl<V> OwnedView<V>
617where
618    V: MessageView<'static>,
619{
620    /// Decode a view from a [`Bytes`] buffer.
621    ///
622    /// The view borrows directly from the buffer's data. Because [`Bytes`] is
623    /// reference-counted and its data pointer is stable across moves, the
624    /// view's borrows remain valid for the lifetime of this `OwnedView`.
625    ///
626    /// # Errors
627    ///
628    /// Returns [`DecodeError`] if the buffer contains invalid protobuf data.
629    pub fn decode(bytes: Bytes) -> Result<Self, DecodeError> {
630        // SAFETY: `Bytes` is StableDeref — its heap data never moves or is
631        // freed while we hold the `Bytes` value. We hold it in `self.bytes`,
632        // and drop order guarantees `view` drops first.
633        let view = unsafe {
634            let slice: &'static [u8] = core::mem::transmute::<&[u8], &'static [u8]>(&bytes);
635            V::decode_view(slice)?
636        };
637        Ok(Self {
638            view: core::mem::ManuallyDrop::new(view),
639            bytes,
640        })
641    }
642
643    /// Decode a view with custom [`DecodeOptions`](crate::DecodeOptions)
644    /// (recursion limit, max message size).
645    ///
646    /// # Errors
647    ///
648    /// Returns [`DecodeError`] if the buffer is invalid or exceeds the
649    /// configured limits.
650    pub fn decode_with_options(
651        bytes: Bytes,
652        opts: &crate::DecodeOptions,
653    ) -> Result<Self, DecodeError> {
654        // SAFETY: Same invariants as `decode` — see above.
655        let view = unsafe {
656            let slice: &'static [u8] = core::mem::transmute::<&[u8], &'static [u8]>(&bytes);
657            opts.decode_view::<V>(slice)?
658        };
659        Ok(Self {
660            view: core::mem::ManuallyDrop::new(view),
661            bytes,
662        })
663    }
664
665    /// Create an `OwnedView` from an owned message by encoding then decoding.
666    ///
667    /// This performs a full **encode → decode** round-trip: the message is
668    /// serialized to protobuf bytes, then a zero-copy view is decoded from
669    /// those bytes. This is useful when the original wire bytes are not
670    /// available (e.g., after JSON deserialization or programmatic construction),
671    /// but note the cost: one allocation + O(n) encode + O(n) decode.
672    ///
673    /// For the common case where you already have wire bytes, prefer
674    /// [`decode`](Self::decode) instead.
675    ///
676    /// # Errors
677    ///
678    /// Returns [`DecodeError`] if the re-encoded bytes are somehow invalid
679    /// (should not happen for well-formed messages).
680    pub fn from_owned(msg: &V::Owned) -> Result<Self, DecodeError> {
681        let bytes = Bytes::from(msg.encode_to_vec());
682        Self::decode(bytes)
683    }
684
685    /// Convert the view to the corresponding owned message type.
686    ///
687    /// This allocates and copies all borrowed fields.
688    pub fn to_owned_message(&self) -> V::Owned {
689        self.view.to_owned_message()
690    }
691
692    /// Get a reference to the underlying bytes buffer.
693    pub fn bytes(&self) -> &Bytes {
694        &self.bytes
695    }
696
697    /// Create an `OwnedView` from a buffer and a pre-decoded view.
698    ///
699    /// This avoids re-decoding when you already hold a decoded view and want
700    /// to wrap it for `'static` use.
701    ///
702    /// # Safety
703    ///
704    /// The caller must ensure that **all** borrows in `view` point into the
705    /// data region of `bytes`. In practice, `view` must have been decoded
706    /// from `bytes` (or a sub-slice that `bytes` fully contains). Violating
707    /// this invariant causes undefined behavior (dangling references).
708    pub unsafe fn from_parts(bytes: Bytes, view: V) -> Self {
709        Self {
710            view: core::mem::ManuallyDrop::new(view),
711            bytes,
712        }
713    }
714
715    /// Consume the `OwnedView`, returning the underlying [`Bytes`] buffer.
716    ///
717    /// The view is dropped before the buffer is returned.
718    pub fn into_bytes(mut self) -> Bytes {
719        // SAFETY: Drop the view first (while bytes data is still alive),
720        // then read bytes out via ptr::read, then forget self to prevent
721        // the Drop impl from double-dropping the view.
722        unsafe {
723            core::mem::ManuallyDrop::drop(&mut self.view);
724            let bytes = core::ptr::read(&self.bytes);
725            core::mem::forget(self);
726            bytes
727        }
728    }
729}
730
731impl<V> core::ops::Deref for OwnedView<V> {
732    type Target = V;
733
734    #[inline]
735    fn deref(&self) -> &V {
736        &self.view // Deref through ManuallyDrop is transparent
737    }
738}
739
740impl<V> core::fmt::Debug for OwnedView<V>
741where
742    V: core::fmt::Debug,
743{
744    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
745        (*self.view).fmt(f)
746    }
747}
748
749impl<V> Clone for OwnedView<V>
750where
751    V: Clone,
752{
753    fn clone(&self) -> Self {
754        // SAFETY: `Bytes::clone()` is a refcount bump — both the original and
755        // the clone share the same backing heap allocation. The cloned view's
756        // `'static` references remain valid because they point into data that
757        // is now kept alive by the cloned `Bytes` handle. This would be
758        // unsound if `Bytes::clone()` performed a deep copy to a new address.
759        Self {
760            view: self.view.clone(),
761            bytes: self.bytes.clone(),
762        }
763    }
764}
765
766impl<V> PartialEq for OwnedView<V>
767where
768    V: PartialEq,
769{
770    fn eq(&self, other: &Self) -> bool {
771        *self.view == *other.view
772    }
773}
774
775impl<V> Eq for OwnedView<V> where V: Eq {}
776
777// `OwnedView<V>` is auto-`Send`/`Sync` when `V` is — `ManuallyDrop<V>` and
778// `Bytes` both forward auto-traits. No manual `unsafe impl` is needed, and
779// adding one with a `V: 'static` bound is actively harmful: it is precisely
780// what triggers E0477 when `async fn` is used in a trait impl against an
781// RPITIT `+ Send` return type (rust-lang/rust#128095). The RPITIT desugaring
782// introduces a fresh lifetime for the `'static` in `FooView<'static>`, and
783// then cannot prove that fresh lifetime satisfies `'static` to discharge the
784// manual impl's bound.
785//
786// The bound was defensive — intended to prevent `OwnedView<FooView<'short>>`
787// from being `Send` when the view borrows from something outside `self.bytes`.
788// But that type is already unconstructible: `::decode()` and
789// `::decode_with_options()` are gated on `V: MessageView<'static>`, and the
790// fields are private. The short-lifetime case the bound guards against cannot
791// exist in safe code.
792//
793// Auto-trait soundness: `Bytes` is `Send + Sync`. The view's `&'static [u8]`
794// borrows point into `Bytes`'s heap allocation, which is immutable,
795// `StableDeref`, and moves with the struct. Sending the whole pair to another
796// thread preserves the invariant. The `'static` in `V` being a lie is about
797// *where* the reference points, not about thread safety.
798#[cfg(test)]
799mod send_sync_assertions {
800    use super::*;
801    fn assert_send<T: Send>() {}
802    fn assert_sync<T: Sync>() {}
803
804    // Any `V: Send + Sync` suffices — generated `FooView<'static>` types are
805    // auto-`Send + Sync` via their `&'static str` / `&'static [u8]` fields.
806    #[allow(dead_code)]
807    fn owned_view_is_send_sync<V: Send + Sync>() {
808        assert_send::<OwnedView<V>>();
809        assert_sync::<OwnedView<V>>();
810    }
811
812    // Concrete-type regression: `TinyView` is declared in the `tests` module
813    // below and has the same shape as generated view types (one `&'a str`).
814    #[allow(dead_code)]
815    fn owned_tiny_view_is_send_sync() {
816        assert_send::<OwnedView<super::tests::TinyView<'static>>>();
817        assert_sync::<OwnedView<super::tests::TinyView<'static>>>();
818    }
819}
820
821#[cfg(test)]
822mod tests {
823    use super::*;
824
825    // ── MessageFieldView ─────────────────────────────────────────────────
826
827    #[test]
828    fn message_field_view_default_is_unset() {
829        let v: MessageFieldView<i32> = MessageFieldView::default();
830        assert!(v.is_unset());
831        assert!(!v.is_set());
832        assert_eq!(v.as_option(), None);
833    }
834
835    #[test]
836    fn message_field_view_set_value() {
837        let v = MessageFieldView::set(42);
838        assert!(v.is_set());
839        assert!(!v.is_unset());
840        assert_eq!(v.as_option(), Some(&42));
841    }
842
843    #[test]
844    fn message_field_view_with_non_copy_type() {
845        let v = MessageFieldView::set(alloc::string::String::from("hello"));
846        assert!(v.is_set());
847        assert_eq!(v.as_option().map(|s| s.as_str()), Some("hello"));
848
849        let unset: MessageFieldView<alloc::string::String> = MessageFieldView::unset();
850        assert!(unset.is_unset());
851        assert_eq!(unset.as_option(), None);
852    }
853
854    // ── MessageFieldView Deref ─────────────────────────────────────────
855
856    /// A trivial view type for testing MessageFieldView Deref.
857    #[derive(Clone, Debug, Default, PartialEq)]
858    pub(super) struct TinyView<'a> {
859        pub value: &'a str,
860    }
861
862    // SAFETY: Default TinyView contains only &'static str (""), which is 'static.
863    unsafe impl DefaultViewInstance for TinyView<'static> {
864        fn default_view_instance() -> &'static Self {
865            static INST: crate::__private::OnceBox<TinyView<'static>> =
866                crate::__private::OnceBox::new();
867            INST.get_or_init(|| alloc::boxed::Box::new(TinyView::default()))
868        }
869    }
870
871    // SAFETY: TinyView is covariant in 'a (only contains &'a str).
872    unsafe impl<'a> HasDefaultViewInstance for TinyView<'a> {
873        type Static = TinyView<'static>;
874    }
875
876    #[test]
877    fn message_field_view_deref_set() {
878        let v = MessageFieldView::set(TinyView { value: "hello" });
879        // Deref gives access to the inner view
880        assert_eq!(v.value, "hello");
881    }
882
883    #[test]
884    fn message_field_view_deref_unset_returns_default() {
885        let v: MessageFieldView<TinyView<'_>> = MessageFieldView::unset();
886        // Deref transparently returns the default instance
887        assert_eq!(v.value, "");
888    }
889
890    #[test]
891    fn message_field_view_deref_chained_access() {
892        // Simulates accessing a nested field through an unset sub-message
893        let v: MessageFieldView<TinyView<'_>> = MessageFieldView::unset();
894        let len = v.value.len();
895        assert_eq!(len, 0);
896    }
897
898    // ── MessageFieldView PartialEq (wire-equivalent) ───────────────────
899
900    #[test]
901    fn message_field_view_equality() {
902        // None = Unset, Some(s) = Set(TinyView { value: s }).
903        // TinyView::default() has value == "", so Some("") encodes Set(default).
904        fn mk(c: Option<&str>) -> MessageFieldView<TinyView<'_>> {
905            match c {
906                None => MessageFieldView::unset(),
907                Some(v) => MessageFieldView::set(TinyView { value: v }),
908            }
909        }
910
911        #[rustfmt::skip]
912        let cases: &[(Option<&str>, Option<&str>, bool)] = &[
913            // Wire-equivalent semantics: Unset == Set(default), matching
914            // MessageField::PartialEq on the owned side.
915            (None,      None,        true ),  // Unset == Unset
916            (None,      Some(""),    true ),  // Unset == Set(default)
917            (Some(""),  None,        true ),  // Set(default) == Unset (symmetric)
918            (Some(""),  Some(""),    true ),  // Set(default) == Set(default)
919            (None,      Some("x"),   false),  // Unset != Set(nondefault)
920            (Some("x"), None,        false),  // Set(nondefault) != Unset (symmetric)
921            (Some("x"), Some("x"),   true ),  // Set == Set (same)
922            (Some("x"), Some("y"),   false),  // Set != Set (different)
923        ];
924
925        for &(l, r, expect) in cases {
926            assert_eq!(
927                mk(l) == mk(r),
928                expect,
929                "({l:?} == {r:?}) should be {expect}"
930            );
931        }
932    }
933
934    // ── RepeatedView ─────────────────────────────────────────────────────
935
936    #[test]
937    fn repeated_view_new_and_accessors() {
938        let rv = RepeatedView::new(alloc::vec![10, 20, 30]);
939        assert_eq!(rv.len(), 3);
940        assert!(!rv.is_empty());
941        assert_eq!(&*rv, &[10, 20, 30]);
942    }
943
944    #[test]
945    fn repeated_view_default_is_empty() {
946        let rv: RepeatedView<'_, u8> = RepeatedView::default();
947        assert!(rv.is_empty());
948        assert_eq!(rv.len(), 0);
949    }
950
951    #[test]
952    fn repeated_view_push_and_iter() {
953        let mut rv = RepeatedView::<i32>::default();
954        rv.push(1);
955        rv.push(2);
956        let collected: alloc::vec::Vec<_> = rv.iter().copied().collect();
957        assert_eq!(collected, alloc::vec![1, 2]);
958    }
959
960    #[test]
961    fn repeated_view_with_borrowed_str() {
962        let data = alloc::string::String::from("hello world");
963        let parts: alloc::vec::Vec<&str> = data.split_whitespace().collect();
964        let rv = RepeatedView::new(parts);
965        assert_eq!(rv.len(), 2);
966        assert_eq!(rv[0], "hello");
967        assert_eq!(rv[1], "world");
968    }
969
970    #[test]
971    fn repeated_view_into_iter_by_ref() {
972        let rv = RepeatedView::new(alloc::vec![1, 2, 3]);
973        let sum: i32 = (&rv).into_iter().sum();
974        assert_eq!(sum, 6);
975        // `for x in &rv` syntax works:
976        let mut count = 0;
977        for _ in &rv {
978            count += 1;
979        }
980        assert_eq!(count, 3);
981    }
982
983    #[test]
984    fn repeated_view_into_iter_by_value() {
985        let rv = RepeatedView::new(alloc::vec![
986            alloc::string::String::from("a"),
987            alloc::string::String::from("b"),
988        ]);
989        let collected: alloc::vec::Vec<_> = rv.into_iter().collect();
990        assert_eq!(collected, alloc::vec!["a".to_string(), "b".to_string()]);
991    }
992
993    // ── MapView ──────────────────────────────────────────────────────────
994
995    #[test]
996    fn map_view_get_with_borrow() {
997        let mut mv = MapView::<&str, i32>::default();
998        mv.push("apples", 3);
999        mv.push("bananas", 5);
1000
1001        // Ergonomic: get("key") works via Borrow<str> on &str
1002        assert_eq!(mv.get("apples"), Some(&3));
1003        assert_eq!(mv.get("bananas"), Some(&5));
1004        assert_eq!(mv.get("oranges"), None);
1005
1006        // Old style still works
1007        assert_eq!(mv.get(&"apples"), Some(&3));
1008    }
1009
1010    #[test]
1011    fn map_view_contains_key_with_borrow() {
1012        let mut mv = MapView::<&str, i32>::default();
1013        mv.push("key", 1);
1014
1015        assert!(mv.contains_key("key"));
1016        assert!(!mv.contains_key("missing"));
1017    }
1018
1019    #[test]
1020    fn map_view_get_last_write_wins() {
1021        let mut mv = MapView::<&str, i32>::default();
1022        mv.push("x", 1);
1023        mv.push("x", 2);
1024        assert_eq!(mv.get("x"), Some(&2));
1025    }
1026
1027    #[test]
1028    fn map_view_keys_and_values() {
1029        let mut mv = MapView::<&str, i32>::default();
1030        mv.push("a", 1);
1031        mv.push("b", 2);
1032        mv.push("c", 3);
1033
1034        let keys: alloc::vec::Vec<_> = mv.keys().copied().collect();
1035        assert_eq!(keys, alloc::vec!["a", "b", "c"]);
1036
1037        let values: alloc::vec::Vec<_> = mv.values().copied().collect();
1038        assert_eq!(values, alloc::vec![1, 2, 3]);
1039    }
1040
1041    #[test]
1042    fn map_view_keys_and_values_empty() {
1043        let mv = MapView::<&str, i32>::default();
1044        assert_eq!(mv.keys().count(), 0);
1045        assert_eq!(mv.values().count(), 0);
1046    }
1047
1048    #[test]
1049    fn map_view_into_iter_collect_to_hashmap() {
1050        let mut mv = MapView::<&str, i32>::default();
1051        mv.push("a", 1);
1052        mv.push("b", 2);
1053        mv.push("a", 3); // duplicate — last-write-wins on collect
1054        let m: crate::__private::HashMap<&str, i32> = mv.into_iter().collect();
1055        assert_eq!(m.len(), 2);
1056        assert_eq!(m.get("a"), Some(&3)); // last value kept
1057        assert_eq!(m.get("b"), Some(&2));
1058    }
1059
1060    // ── UnknownFieldsView ────────────────────────────────────────────────
1061
1062    #[test]
1063    fn unknown_fields_view_new_is_empty() {
1064        let uf = UnknownFieldsView::new();
1065        assert!(uf.is_empty());
1066        assert_eq!(uf.encoded_len(), 0);
1067    }
1068
1069    #[test]
1070    fn unknown_fields_view_push_raw_and_encoded_len() {
1071        let mut uf = UnknownFieldsView::new();
1072        uf.push_raw(&[0x08, 0x01]); // field 1, varint 1
1073        uf.push_raw(&[0x10, 0x02]); // field 2, varint 2
1074        assert!(!uf.is_empty());
1075        assert_eq!(uf.encoded_len(), 4);
1076    }
1077
1078    #[test]
1079    fn unknown_fields_view_to_owned_single_field() {
1080        // Build a valid unknown field: tag for field 99, varint wire type,
1081        // value 42.  Tag = (99 << 3) | 0 = 792 = varint bytes [0x98, 0x06].
1082        let span: &[u8] = &[0x98, 0x06, 0x2A];
1083        let mut uf = UnknownFieldsView::new();
1084        uf.push_raw(span);
1085
1086        let owned = uf.to_owned().expect("valid wire data");
1087        assert_eq!(owned.len(), 1);
1088        let field = owned.iter().next().unwrap();
1089        assert_eq!(field.number, 99);
1090        assert_eq!(
1091            field.data,
1092            crate::unknown_fields::UnknownFieldData::Varint(42)
1093        );
1094    }
1095
1096    #[test]
1097    fn unknown_fields_view_to_owned_multiple_fields() {
1098        let mut uf = UnknownFieldsView::new();
1099        // Field 1, varint, value 7:  tag = (1<<3)|0 = 0x08, value = 0x07
1100        uf.push_raw(&[0x08, 0x07]);
1101        // Field 2, fixed32, value 0x01020304:
1102        //   tag = (2<<3)|5 = 0x15, then 4 LE bytes
1103        uf.push_raw(&[0x15, 0x04, 0x03, 0x02, 0x01]);
1104
1105        let owned = uf.to_owned().expect("valid wire data");
1106        assert_eq!(owned.len(), 2);
1107
1108        let mut it = owned.iter();
1109        let f1 = it.next().unwrap();
1110        assert_eq!(f1.number, 1);
1111        assert_eq!(f1.data, crate::unknown_fields::UnknownFieldData::Varint(7));
1112
1113        let f2 = it.next().unwrap();
1114        assert_eq!(f2.number, 2);
1115        assert_eq!(
1116            f2.data,
1117            crate::unknown_fields::UnknownFieldData::Fixed32(0x01020304)
1118        );
1119    }
1120
1121    #[test]
1122    fn unknown_fields_view_to_owned_malformed_returns_error() {
1123        // A truncated tag (high continuation bit, then EOF).
1124        let mut uf = UnknownFieldsView::new();
1125        uf.push_raw(&[0x80]);
1126        assert!(uf.to_owned().is_err());
1127    }
1128
1129    // ── OwnedView ──────────────────────────────────────────────────────
1130
1131    // Minimal types to test OwnedView without depending on generated code.
1132
1133    use crate::message::Message;
1134
1135    /// A trivial "message" for the owned side of the view contract.
1136    #[derive(Clone, Debug, Default, PartialEq)]
1137    struct SimpleMessage {
1138        pub id: i32,
1139        pub name: alloc::string::String,
1140    }
1141
1142    // SAFETY: Returns a lazily-initialized static default instance.
1143    unsafe impl crate::DefaultInstance for SimpleMessage {
1144        fn default_instance() -> &'static Self {
1145            static INST: crate::__private::OnceBox<SimpleMessage> =
1146                crate::__private::OnceBox::new();
1147            INST.get_or_init(|| alloc::boxed::Box::new(SimpleMessage::default()))
1148        }
1149    }
1150
1151    impl crate::Message for SimpleMessage {
1152        fn compute_size(&self) -> u32 {
1153            let mut size = 0u32;
1154            if self.id != 0 {
1155                size += 1 + crate::types::int32_encoded_len(self.id) as u32;
1156            }
1157            if !self.name.is_empty() {
1158                size += 1 + crate::types::string_encoded_len(&self.name) as u32;
1159            }
1160            size
1161        }
1162
1163        fn write_to(&self, buf: &mut impl bytes::BufMut) {
1164            if self.id != 0 {
1165                crate::encoding::Tag::new(1, crate::encoding::WireType::Varint).encode(buf);
1166                crate::types::encode_int32(self.id, buf);
1167            }
1168            if !self.name.is_empty() {
1169                crate::encoding::Tag::new(2, crate::encoding::WireType::LengthDelimited)
1170                    .encode(buf);
1171                crate::types::encode_string(&self.name, buf);
1172            }
1173        }
1174
1175        fn merge_field(
1176            &mut self,
1177            tag: crate::encoding::Tag,
1178            buf: &mut impl bytes::Buf,
1179            _depth: u32,
1180        ) -> Result<(), DecodeError> {
1181            match tag.field_number() {
1182                1 => self.id = crate::types::decode_int32(buf)?,
1183                2 => crate::types::merge_string(&mut self.name, buf)?,
1184                _ => crate::encoding::skip_field(tag, buf)?,
1185            }
1186            Ok(())
1187        }
1188
1189        fn cached_size(&self) -> u32 {
1190            0
1191        }
1192
1193        fn clear(&mut self) {
1194            self.id = 0;
1195            self.name.clear();
1196        }
1197    }
1198
1199    /// A zero-copy view of `SimpleMessage`. Borrows `name` as `&str`.
1200    #[derive(Clone, Debug, Default, PartialEq)]
1201    struct SimpleMessageView<'a> {
1202        pub id: i32,
1203        pub name: &'a str,
1204    }
1205
1206    impl<'a> MessageView<'a> for SimpleMessageView<'a> {
1207        type Owned = SimpleMessage;
1208
1209        fn decode_view(buf: &'a [u8]) -> Result<Self, DecodeError> {
1210            let mut view = SimpleMessageView::default();
1211            let mut cursor: &'a [u8] = buf;
1212            while !cursor.is_empty() {
1213                let tag = crate::encoding::Tag::decode(&mut cursor)?;
1214                match tag.field_number() {
1215                    1 => view.id = crate::types::decode_int32(&mut cursor)?,
1216                    2 => view.name = crate::types::borrow_str(&mut cursor)?,
1217                    _ => crate::encoding::skip_field(tag, &mut cursor)?,
1218                }
1219            }
1220            Ok(view)
1221        }
1222
1223        fn to_owned_message(&self) -> SimpleMessage {
1224            SimpleMessage {
1225                id: self.id,
1226                name: self.name.into(),
1227            }
1228        }
1229    }
1230
1231    /// Encode a SimpleMessage to Bytes for testing.
1232    fn encode_simple(id: i32, name: &str) -> Bytes {
1233        let msg = SimpleMessage {
1234            id,
1235            name: name.into(),
1236        };
1237        Bytes::from(msg.encode_to_vec())
1238    }
1239
1240    #[test]
1241    fn owned_view_decode_and_deref() {
1242        let bytes = encode_simple(42, "hello");
1243        let view = OwnedView::<SimpleMessageView<'static>>::decode(bytes).unwrap();
1244
1245        // Access via Deref — no .get() needed
1246        assert_eq!(view.id, 42);
1247        assert_eq!(view.name, "hello");
1248    }
1249
1250    #[test]
1251    fn owned_view_to_owned_message() {
1252        let bytes = encode_simple(7, "world");
1253        let view = OwnedView::<SimpleMessageView<'static>>::decode(bytes).unwrap();
1254        let owned = view.to_owned_message();
1255
1256        assert_eq!(owned.id, 7);
1257        assert_eq!(owned.name, "world");
1258    }
1259
1260    #[test]
1261    fn owned_view_debug_delegates_to_view() {
1262        let bytes = encode_simple(1, "test");
1263        let view = OwnedView::<SimpleMessageView<'static>>::decode(bytes).unwrap();
1264        let debug = alloc::format!("{:?}", view);
1265        assert!(debug.contains("test"));
1266        assert!(debug.contains("1"));
1267    }
1268
1269    #[test]
1270    fn owned_view_bytes_accessor() {
1271        let bytes = encode_simple(5, "data");
1272        let original_len = bytes.len();
1273        let view = OwnedView::<SimpleMessageView<'static>>::decode(bytes).unwrap();
1274
1275        assert_eq!(view.bytes().len(), original_len);
1276    }
1277
1278    #[test]
1279    fn owned_view_into_bytes_recovers_buffer() {
1280        let bytes = encode_simple(99, "recover");
1281        let expected = bytes.clone();
1282        let view = OwnedView::<SimpleMessageView<'static>>::decode(bytes).unwrap();
1283        let recovered = view.into_bytes();
1284
1285        assert_eq!(recovered, expected);
1286    }
1287
1288    #[test]
1289    fn owned_view_decode_invalid_data_returns_error() {
1290        // Truncated varint
1291        let bad = Bytes::from_static(&[0x08, 0x80]);
1292        let result = OwnedView::<SimpleMessageView<'static>>::decode(bad);
1293        assert!(result.is_err());
1294    }
1295
1296    #[test]
1297    fn owned_view_empty_message() {
1298        let bytes = Bytes::from_static(&[]);
1299        let view = OwnedView::<SimpleMessageView<'static>>::decode(bytes).unwrap();
1300        assert_eq!(view.id, 0);
1301        assert_eq!(view.name, "");
1302    }
1303
1304    #[test]
1305    fn owned_view_is_send_and_sync() {
1306        fn assert_send_sync<T: Send + Sync>() {}
1307        assert_send_sync::<OwnedView<SimpleMessageView<'static>>>();
1308    }
1309
1310    #[test]
1311    fn owned_view_from_owned_roundtrips() {
1312        let msg = SimpleMessage {
1313            id: 99,
1314            name: "roundtrip".into(),
1315        };
1316        let view = OwnedView::<SimpleMessageView<'static>>::from_owned(&msg).expect("from_owned");
1317        assert_eq!(view.id, 99);
1318        assert_eq!(view.name, "roundtrip");
1319
1320        let back = view.to_owned_message();
1321        assert_eq!(back, msg);
1322    }
1323
1324    #[test]
1325    fn owned_view_decode_with_options() {
1326        let bytes = encode_simple(42, "opts");
1327        let opts = crate::DecodeOptions::new().with_max_message_size(1024);
1328        let view =
1329            OwnedView::<SimpleMessageView<'static>>::decode_with_options(bytes, &opts).unwrap();
1330        assert_eq!(view.id, 42);
1331        assert_eq!(view.name, "opts");
1332    }
1333
1334    #[test]
1335    fn owned_view_decode_with_options_rejects_oversized() {
1336        let bytes = encode_simple(42, "too large");
1337        let opts = crate::DecodeOptions::new().with_max_message_size(2);
1338        let result = OwnedView::<SimpleMessageView<'static>>::decode_with_options(bytes, &opts);
1339        assert!(result.is_err());
1340    }
1341
1342    #[test]
1343    fn owned_view_clone_survives_original_drop() {
1344        let bytes = encode_simple(42, "cloned");
1345        let view = OwnedView::<SimpleMessageView<'static>>::decode(bytes).unwrap();
1346        let cloned = view.clone();
1347        drop(view); // drop original — clone must still be valid
1348        assert_eq!(cloned.id, 42);
1349        assert_eq!(cloned.name, "cloned");
1350    }
1351
1352    #[test]
1353    fn owned_view_clone_equality() {
1354        let bytes = encode_simple(42, "eq");
1355        let view = OwnedView::<SimpleMessageView<'static>>::decode(bytes).unwrap();
1356        let cloned = view.clone();
1357        assert_eq!(view, cloned);
1358    }
1359
1360    #[test]
1361    fn owned_view_eq_same_data() {
1362        let a = OwnedView::<SimpleMessageView<'static>>::decode(encode_simple(1, "x")).unwrap();
1363        let b = OwnedView::<SimpleMessageView<'static>>::decode(encode_simple(1, "x")).unwrap();
1364        assert_eq!(a, b);
1365    }
1366
1367    #[test]
1368    fn owned_view_ne_different_data() {
1369        let a = OwnedView::<SimpleMessageView<'static>>::decode(encode_simple(1, "x")).unwrap();
1370        let b = OwnedView::<SimpleMessageView<'static>>::decode(encode_simple(2, "y")).unwrap();
1371        assert_ne!(a, b);
1372    }
1373
1374    #[test]
1375    fn owned_view_into_bytes_after_clone() {
1376        let bytes = encode_simple(42, "test");
1377        let expected = bytes.clone();
1378        let view = OwnedView::<SimpleMessageView<'static>>::decode(bytes).unwrap();
1379        let cloned = view.clone();
1380        drop(view); // drop original first
1381        let recovered = cloned.into_bytes();
1382        assert_eq!(recovered, expected);
1383    }
1384
1385    #[test]
1386    fn owned_view_drop_count() {
1387        use core::sync::atomic::{AtomicUsize, Ordering};
1388
1389        static DROP_COUNT: AtomicUsize = AtomicUsize::new(0);
1390
1391        /// A wrapper view that counts drops.
1392        struct DropCountingView<'a> {
1393            inner: SimpleMessageView<'a>,
1394        }
1395
1396        impl Drop for DropCountingView<'_> {
1397            fn drop(&mut self) {
1398                DROP_COUNT.fetch_add(1, Ordering::SeqCst);
1399            }
1400        }
1401
1402        impl<'a> MessageView<'a> for DropCountingView<'a> {
1403            type Owned = SimpleMessage;
1404
1405            fn decode_view(buf: &'a [u8]) -> Result<Self, DecodeError> {
1406                Ok(DropCountingView {
1407                    inner: SimpleMessageView::decode_view(buf)?,
1408                })
1409            }
1410
1411            fn to_owned_message(&self) -> SimpleMessage {
1412                self.inner.to_owned_message()
1413            }
1414        }
1415
1416        // Test normal drop: view drops exactly once.
1417        DROP_COUNT.store(0, Ordering::SeqCst);
1418        {
1419            let bytes = encode_simple(1, "drop");
1420            let _view = OwnedView::<DropCountingView<'static>>::decode(bytes).unwrap();
1421        }
1422        assert_eq!(DROP_COUNT.load(Ordering::SeqCst), 1, "normal drop");
1423
1424        // Test into_bytes: view drops exactly once.
1425        DROP_COUNT.store(0, Ordering::SeqCst);
1426        {
1427            let bytes = encode_simple(2, "into");
1428            let view = OwnedView::<DropCountingView<'static>>::decode(bytes).unwrap();
1429            let _bytes = view.into_bytes();
1430        }
1431        assert_eq!(DROP_COUNT.load(Ordering::SeqCst), 1, "into_bytes drop");
1432    }
1433
1434    #[test]
1435    fn owned_view_name_borrows_from_bytes_buffer() {
1436        let bytes = encode_simple(42, "borrowed");
1437        let view = OwnedView::<SimpleMessageView<'static>>::decode(bytes).unwrap();
1438        let buf = view.bytes();
1439        let buf_start = buf.as_ptr() as usize;
1440        let buf_end = buf_start + buf.len();
1441        let name_ptr = view.name.as_ptr() as usize;
1442        assert!(
1443            (buf_start..buf_end).contains(&name_ptr),
1444            "view.name should point into the Bytes buffer"
1445        );
1446    }
1447
1448    #[test]
1449    fn owned_view_concurrent_read() {
1450        use alloc::sync::Arc;
1451
1452        let bytes = encode_simple(42, "concurrent");
1453        let view = Arc::new(OwnedView::<SimpleMessageView<'static>>::decode(bytes).unwrap());
1454        let handles: alloc::vec::Vec<_> = (0..4)
1455            .map(|_| {
1456                let v = Arc::clone(&view);
1457                std::thread::spawn(move || {
1458                    assert_eq!(v.id, 42);
1459                    assert_eq!(v.name, "concurrent");
1460                })
1461            })
1462            .collect();
1463        for h in handles {
1464            h.join().unwrap();
1465        }
1466    }
1467
1468    #[test]
1469    fn owned_view_from_parts_roundtrip() {
1470        let bytes = encode_simple(42, "parts");
1471        // Decode a view from the bytes, then wrap via from_parts.
1472        // SAFETY: `view` was decoded from `bytes`.
1473        let view = unsafe {
1474            let slice: &'static [u8] = core::mem::transmute::<&[u8], &'static [u8]>(&bytes);
1475            let decoded = SimpleMessageView::decode_view(slice).unwrap();
1476            OwnedView::<SimpleMessageView<'static>>::from_parts(bytes, decoded)
1477        };
1478        assert_eq!(view.id, 42);
1479        assert_eq!(view.name, "parts");
1480    }
1481}