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//! # Reborrowing from `OwnedView`
41//!
42//! [`OwnedView<V>`](OwnedView) wraps a decoded view with the lifetime erased
43//! to `'static`. The inner view is reached through
44//! [`OwnedView::reborrow`], which ties the borrow to the `OwnedView` itself —
45//! field reads, assigning the view to a binding, passing it to a function
46//! with a non-`'static` lifetime parameter, and returning a borrowed field
47//! all go through the same call:
48//!
49//! ```no_run
50//! # use buffa::view::OwnedView;
51//! # use buffa::__doctest_fixtures::PersonView;
52//! // reborrow ties the returned borrow to the OwnedView's lifetime.
53//! fn handler<'a>(req: &'a OwnedView<PersonView<'static>>) -> &'a str {
54//!     req.reborrow().name
55//! }
56//! ```
57//!
58//! The view is deliberately not exposed as `&V` (e.g. via `Deref`): `V` is
59//! `FooView<'static>`, so its borrowed fields would *appear* `'static` to the
60//! compiler and could outlive the buffer they point into. `reborrow` narrows
61//! that synthetic `'static` down to the `OwnedView`'s real lifetime. Generated
62//! code also provides a per-message `FooOwnedView` wrapper with field accessor
63//! methods, so handler code rarely needs to call `reborrow` directly. See
64//! [`OwnedView`] for details.
65//!
66//! # Generated code shape
67//!
68//! For a message like:
69//! ```protobuf
70//! message Person {
71//!   string name = 1;
72//!   int32 id = 2;
73//!   bytes avatar = 3;
74//!   repeated string tags = 4;
75//!   Address address = 5;
76//! }
77//! ```
78//!
79//! Buffa generates:
80//! ```rust,ignore
81//! // Owned type (heap-allocated strings and vecs)
82//! pub struct Person {
83//!     pub name: String,
84//!     pub id: i32,
85//!     pub avatar: Vec<u8>,
86//!     pub tags: Vec<String>,
87//!     pub address: MessageField<Address>,
88//!     #[doc(hidden)] pub __buffa_unknown_fields: UnknownFields,
89//! }
90//!
91//! // Borrowed view type (zero-copy from input buffer)
92//! pub struct PersonView<'a> {
93//!     pub name: &'a str,
94//!     pub id: i32,
95//!     pub avatar: &'a [u8],
96//!     pub tags: RepeatedView<'a, &'a str>,
97//!     pub address: MessageFieldView<AddressView<'a>>,
98//!     pub __buffa_unknown_fields: UnknownFieldsView<'a>,
99//! }
100//! ```
101
102use crate::error::DecodeError;
103use crate::message::Message as _;
104use bytes::{BufMut, Bytes};
105
106/// Trait for zero-copy borrowed message views.
107///
108/// View types borrow from the input buffer and provide read-only access
109/// to message fields without allocation. Each generated `MyMessageView<'a>`
110/// implements this trait.
111///
112/// The lifetime `'a` ties the view to the input buffer — the view cannot
113/// outlive the buffer it was decoded from.
114pub trait MessageView<'a>: Sized {
115    /// The corresponding owned message type.
116    type Owned: crate::Message;
117
118    /// Decode a view from a buffer, borrowing string/bytes fields directly.
119    ///
120    /// The returned view borrows from `buf`'s underlying bytes. The caller
121    /// must ensure the buffer is contiguous (e.g., `&[u8]` or `bytes::Bytes`).
122    ///
123    /// Decoding validates the whole message tree eagerly. For
124    /// decode-on-access of large sub-message trees, see the opt-in
125    /// [`LazyMessageView`] family (`lazy_views` codegen option).
126    ///
127    /// Generated impls construct a default [`DecodeContext`](crate::DecodeContext)
128    /// and delegate to [`decode_view_ctx`](Self::decode_view_ctx). (Kept
129    /// required, without a `Self: Default` bound, so generic callers stay
130    /// bound-free.)
131    fn decode_view(buf: &'a [u8]) -> Result<Self, DecodeError>;
132
133    /// Decode a view under custom decode limits.
134    ///
135    /// Used by [`DecodeOptions::decode_view`](crate::DecodeOptions::decode_view)
136    /// to pass a non-default recursion depth and unknown-field allowance.
137    /// The default implementation delegates to
138    /// [`decode_view`](Self::decode_view) and **ignores the context** —
139    /// a hand-written `MessageView` that recurses or preserves unknown
140    /// fields must override this method to honor the limits configured on
141    /// `DecodeOptions`. Implementing
142    /// [`merge_view_field`](Self::merge_view_field) is **not sufficient**:
143    /// without this override, `DecodeOptions` limits never reach your
144    /// field arms. The one-line override is
145    /// `Self::decode_view_ctx(buf, ctx)` (when `Self: Default`). Generated
146    /// code always overrides it that way.
147    ///
148    /// Not to be confused with [`decode_view_ctx`](Self::decode_view_ctx),
149    /// which is the provided decoder that *honors* the context; this method
150    /// is the override point `DecodeOptions` calls.
151    fn decode_view_with_ctx(
152        buf: &'a [u8],
153        _ctx: crate::DecodeContext<'_>,
154    ) -> Result<Self, DecodeError> {
155        Self::decode_view(buf)
156    }
157
158    /// Decode a view under an explicit [`DecodeContext`](crate::DecodeContext)
159    /// (remaining recursion depth and unknown-field allowance), driving the
160    /// provided tag loop over [`merge_view_field`](Self::merge_view_field).
161    ///
162    /// This is the bridge a hand-written impl uses to wire its required
163    /// `decode_view` to its required `merge_view_field`:
164    ///
165    /// ```rust,ignore
166    /// fn decode_view(buf: &'a [u8]) -> Result<Self, buffa::DecodeError> {
167    ///     let limit = core::cell::Cell::new(buffa::DEFAULT_UNKNOWN_FIELD_LIMIT);
168    ///     Self::decode_view_ctx(
169    ///         buf,
170    ///         buffa::DecodeContext::new(buffa::RECURSION_LIMIT, &limit),
171    ///     )
172    /// }
173    /// ```
174    ///
175    /// Also called by generated sub-message decode arms with a descended
176    /// context. Not to be confused with
177    /// [`decode_view_with_ctx`](Self::decode_view_with_ctx), the
178    /// `DecodeOptions` override point whose *default* ignores the context.
179    ///
180    /// # Errors
181    ///
182    /// Returns a [`DecodeError`] on malformed input, a wire-type mismatch, or
183    /// when a configured decode limit (recursion depth, unknown-field
184    /// allowance) is exceeded.
185    fn decode_view_ctx(buf: &'a [u8], ctx: crate::DecodeContext<'_>) -> Result<Self, DecodeError>
186    where
187        Self: Default,
188    {
189        let mut view = Self::default();
190        view.merge_into_view(buf, ctx)?;
191        Ok(view)
192    }
193
194    /// Merge fields from `buf` into this view (proto merge semantics):
195    /// repeated fields append, singular fields last-wins, singular message
196    /// fields merge recursively.
197    ///
198    /// The per-message work is the field `match` in
199    /// [`merge_view_field`](Self::merge_view_field); this provided method
200    /// owns the tag loop that every generated view previously restated.
201    /// Each iteration consumes the field's tag itself, so the loop makes
202    /// progress even if an arm consumes no payload bytes.
203    ///
204    /// # Errors
205    ///
206    /// Returns a [`DecodeError`] on malformed input, a wire-type mismatch, or
207    /// when a configured decode limit (recursion depth, unknown-field
208    /// allowance) is exceeded.
209    fn merge_into_view(
210        &mut self,
211        buf: &'a [u8],
212        ctx: crate::DecodeContext<'_>,
213    ) -> Result<(), DecodeError> {
214        let mut cur: &'a [u8] = buf;
215        while !cur.is_empty() {
216            // Captured so unknown fields can preserve their raw byte span
217            // (`before_tag.len() - cur.len()` after the payload is consumed).
218            let before_tag = cur;
219            let tag = crate::encoding::Tag::decode(&mut cur)?;
220            cur = self.merge_view_field(tag, cur, before_tag, ctx)?;
221        }
222        Ok(())
223    }
224
225    /// Decode one field's payload into this view (generated per message).
226    ///
227    /// `cur` is the input positioned just past `tag`; the implementation
228    /// returns the remaining input after the field's payload. The
229    /// pass-by-value/return shape (rather than `&mut &'a [u8]`) keeps each
230    /// arm's `&mut` borrow of the slice local to that arm — sub-message
231    /// arms can hand `cur` slices to recursive decode calls without
232    /// fighting a long-lived outer `&mut` reborrow. `before_tag` is the
233    /// input including the tag bytes, for raw-span unknown-field capture.
234    ///
235    /// Hand-written views must supply this (it is the one method the
236    /// provided decode loop requires). A view that instead overrides both
237    /// [`decode_view`](Self::decode_view) and
238    /// [`decode_view_with_ctx`](Self::decode_view_with_ctx) to decode by hand
239    /// never reaches the provided loop, so it can satisfy the trait with a
240    /// one-line `Ok(cur)` stub. The canonical shape is a match on
241    /// `tag.field_number()`:
242    ///
243    /// ```rust,ignore
244    /// fn merge_view_field(
245    ///     &mut self,
246    ///     tag: buffa::encoding::Tag,
247    ///     cur: &'a [u8],
248    ///     _before_tag: &'a [u8],
249    ///     ctx: buffa::DecodeContext<'_>,
250    /// ) -> Result<&'a [u8], buffa::DecodeError> {
251    ///     let mut cur = cur;
252    ///     match tag.field_number() {
253    ///         1 => self.id = buffa::types::decode_int32(&mut cur)?,
254    ///         2 => self.name = buffa::types::borrow_str(&mut cur)?,
255    ///         _ => buffa::encoding::skip_field_depth(tag, &mut cur, ctx.depth())?,
256    ///     }
257    ///     Ok(cur)
258    /// }
259    /// ```
260    ///
261    /// Views that preserve unknown fields capture the raw span — tag
262    /// included — via `before_tag` (the span length is measured *after* the
263    /// payload is consumed) and store it with
264    /// [`UnknownFieldsView::push_record`], which charges the context's
265    /// unknown-field allowance per field (including fields nested in
266    /// unknown groups) so that [`to_owned_message`](Self::to_owned_message)
267    /// cannot exhaust it later; the provided loop stays message-agnostic:
268    ///
269    /// ```rust,ignore
270    /// _ => {
271    ///     buffa::encoding::skip_field_depth(tag, &mut cur, ctx.depth())?;
272    ///     let span_len = before_tag.len() - cur.len();
273    ///     self.unknown_fields.push_record(before_tag, span_len, ctx)?;
274    /// }
275    /// ```
276    ///
277    /// The returned slice must be a suffix of `cur` (and hence of
278    /// `before_tag`): the provided loop continues from it, and the
279    /// unknown-field span is measured as `before_tag.len() - cur.len()`, which
280    /// underflows and panics if the returned slice is longer than the input.
281    ///
282    /// # Errors
283    ///
284    /// Returns a [`DecodeError`] on malformed payloads or wire-type
285    /// mismatches.
286    fn merge_view_field(
287        &mut self,
288        tag: crate::encoding::Tag,
289        cur: &'a [u8],
290        before_tag: &'a [u8],
291        ctx: crate::DecodeContext<'_>,
292    ) -> Result<&'a [u8], DecodeError>;
293
294    /// Convert this view to the owned message type.
295    ///
296    /// This allocates and copies all borrowed fields. Equivalent to
297    /// [`to_owned_from_source(None)`](Self::to_owned_from_source).
298    ///
299    /// For views produced by [`decode_view`](Self::decode_view) (or the
300    /// other wire-decoding entry points), this cannot fail: decoding
301    /// charged the unknown-field allowance with exactly the slots that
302    /// re-materializing preserved unknown fields consumes, every span was
303    /// parsed off the wire, and re-materialization replays under the field
304    /// budget and group-nesting depth recorded at decode time. The `Result`
305    /// remains for hand-written view impls and for views holding manually
306    /// pushed ([`UnknownFieldsView::push_raw`]) unknown-field spans.
307    ///
308    /// # Errors
309    ///
310    /// Returns an error if re-materializing preserved unknown fields fails —
311    /// possible only for views not produced by wire decoding, as described
312    /// above.
313    fn to_owned_message(&self) -> Result<Self::Owned, DecodeError>;
314
315    /// Convert this view to the owned message type, optionally slicing
316    /// `bytes::Bytes`-typed fields from `source` instead of copying.
317    ///
318    /// When `source` is the [`Bytes`] buffer this view was decoded from,
319    /// owned fields configured for `bytes::Bytes` (via the `bytes_fields`
320    /// codegen option) are produced via [`Bytes::slice_ref`] — a refcount
321    /// bump, no allocation or copy. Borrowed fields that fall outside
322    /// `source` (e.g. on a manually-constructed view) and the `None` case
323    /// fall back to [`Bytes::copy_from_slice`].
324    ///
325    /// Generated view types override this; the default delegates to
326    /// [`to_owned_message`](Self::to_owned_message) so hand-written impls
327    /// need only provide that method.
328    ///
329    /// # Errors
330    ///
331    /// Same contract as [`to_owned_message`](Self::to_owned_message).
332    fn to_owned_from_source(&self, source: Option<&Bytes>) -> Result<Self::Owned, DecodeError> {
333        let _ = source;
334        self.to_owned_message()
335    }
336}
337
338/// Exposes the real lifetime of an [`OwnedView`]'s borrows.
339///
340/// `OwnedView<V>` stores `V` with a `'static` lifetime — the actual borrows
341/// point into its internal [`Bytes`] buffer. `ViewReborrow` lets
342/// [`OwnedView::reborrow`] return a reference typed as `&'b V::Reborrowed<'b>`,
343/// tying the borrow to `&'b self` so the compiler can reason about it correctly.
344///
345/// Codegen emits `impl ViewReborrow` automatically for every generated view
346/// type. Hand-written view types must provide it manually if
347/// [`OwnedView::reborrow`] is needed.
348///
349/// # Soundness
350///
351/// `ViewReborrow` is a **safe** trait. Soundness is established mechanically
352/// by the compiler at each impl site: the [`reborrow`](Self::reborrow) method
353/// body coerces a `&'b Self` (where `Self = FooView<'static>`) to
354/// `&'b Self::Reborrowed<'b>` (= `&'b FooView<'b>`). Rust accepts this only
355/// when `FooView` is **covariant** in its lifetime parameter — a covariant
356/// `FooView<'static>` is a subtype of `FooView<'b>` and the coercion is a
357/// standard subtyping move. Invariant fields (`Cell<&'a T>`, `&'a mut T`,
358/// `fn(&'a T)`) make the type invariant in `'a`; the trait body then fails
359/// to compile and the impl is rejected — which is exactly what should
360/// happen, because narrowing the lifetime of an invariant view *would* be
361/// unsound.
362///
363/// Hand-written impls cannot accidentally introduce undefined behaviour
364/// without writing `unsafe` themselves: the canonical body is just `this`,
365/// which the type checker accepts iff the variance permits the coercion.
366#[rustversion::attr(
367    since(1.78),
368    diagnostic::on_unimplemented(
369        message = "`{Self}` does not implement `ViewReborrow` — required by `OwnedView::reborrow`",
370        note = "for a generated view type, this impl is emitted automatically by codegen",
371        note = "for a hand-written view type `MyView<'a>`, add:\n    impl ViewReborrow for MyView<'static> {{\n        type Reborrowed<'b> = MyView<'b>;\n        fn reborrow<'b>(this: &'b Self) -> &'b Self::Reborrowed<'b> {{ this }}\n    }}",
372        note = "your `MessageView` impl must be parametric over the lifetime — `impl<'a> MessageView<'a> for MyView<'a>` — so that both `Self: MessageView<'static>` and `Reborrowed<'b>: MessageView<'b>` hold",
373        note = "`MyView` must be covariant in its lifetime — fields like `&'a T` and `MessageFieldView<...>` are covariant; `Cell<&'a T>` and `&'a mut T` are not, and the trait body `{{ this }}` will fail to compile for invariant types"
374    )
375)]
376pub trait ViewReborrow: MessageView<'static> {
377    /// The same view type with its lifetime shortened to `'b`.
378    type Reborrowed<'b>: MessageView<'b, Owned = <Self as MessageView<'static>>::Owned>
379    where
380        Self: 'b;
381
382    /// Coerce `&'b Self` (= `&'b FooView<'static>`) to
383    /// `&'b Self::Reborrowed<'b>` (= `&'b FooView<'b>`). The canonical body
384    /// is just `this`; the compiler accepts it via standard lifetime
385    /// variance for covariant view types.
386    ///
387    /// Called by [`OwnedView::reborrow`]; users shouldn't need to call this
388    /// method directly.
389    fn reborrow<'b>(this: &'b Self) -> &'b Self::Reborrowed<'b>;
390}
391
392/// Implement [`ViewReborrow`] for a generated view type.
393///
394/// Emitted by generated code (one invocation per view struct); the trait's
395/// `on_unimplemented` note shows the equivalent expansion for hand-written
396/// views.
397///
398/// ```rust,ignore
399/// buffa::impl_view_reborrow!(MyMessageView);
400/// ```
401#[macro_export]
402macro_rules! impl_view_reborrow {
403    ($ty:ident) => {
404        impl $crate::ViewReborrow for $ty<'static> {
405            type Reborrowed<'b> = $ty<'b>;
406            fn reborrow<'b>(this: &'b Self) -> &'b Self::Reborrowed<'b> {
407                this
408            }
409        }
410    };
411}
412
413/// Links an owned message type to its generated zero-copy view types.
414///
415/// For a message `Foo`, generated code implements this trait as
416/// `View<'a> = FooView<'a>` (the borrowed view) and
417/// `ViewHandle = FooOwnedView` (the self-contained `'static` handle). The
418/// trait lets code that is generic over an owned message name those types —
419/// for example an RPC framework that decodes `M::View<'_>` from a request
420/// body it owns, or holds `M::ViewHandle` items in a stream — without
421/// per-message glue on the consumer's side.
422///
423/// The associated types intentionally carry only structural bounds:
424///
425/// - [`View<'a>`](Self::View) is the message's view, with
426///   [`Owned`](MessageView::Owned)` = Self`.
427/// - [`ViewHandle`](Self::ViewHandle) is convertible from, and exposes via
428///   [`AsRef`], the corresponding `OwnedView<Self::View<'static>>`, so
429///   generic code can reach [`reborrow`](OwnedView::reborrow),
430///   [`bytes`](OwnedView::bytes), and
431///   [`to_owned_message`](OwnedView::to_owned_message) without naming the
432///   concrete wrapper. The wrapper's per-field accessor methods remain
433///   inherent on the concrete type.
434///
435/// Generic code that wants to reborrow through the handle
436/// (`handle.as_ref().reborrow()`) adds `M::View<'static>: ViewReborrow` as a
437/// bound at the use site; every generated view satisfies it. (The bound
438/// cannot live on the trait itself: a `where Self::View<'static>:
439/// ViewReborrow` clause currently trips a GAT normalization error, E0308
440/// "expected `MessageView<'a>`, found `MessageView<'static>`".)
441///
442/// # Implementing
443///
444/// Implementations are generated alongside the view and owned-view wrapper
445/// (and are therefore gated with them). Hand-written implementations are only
446/// needed for hand-written view types and must follow the same shape.
447#[rustversion::attr(
448    since(1.78),
449    diagnostic::on_unimplemented(
450        message = "`{Self}` does not implement `HasMessageView` — its message-view family was not generated or is not enabled",
451        note = "the `HasMessageView` impl is emitted next to each message's view types: \
452                regenerate the crate that defines `{Self}` with buffa 0.7.0 or newer and \
453                views enabled — `generate_views(true)` (on by default) in a buffa-build / \
454                buffa-codegen config, or `views=true` for protoc-gen-buffa",
455        note = "if the defining crate feature-gates its generated impls, enabling its views \
456                feature is enough — no regeneration needed"
457    )
458)]
459pub trait HasMessageView: crate::Message + Sized {
460    /// The zero-copy view of `Self`, borrowing from a buffer with lifetime
461    /// `'a`.
462    type View<'a>: MessageView<'a, Owned = Self> + Send + Sync;
463
464    /// The generated `'static` owned-view handle for `Self`
465    /// (`FooOwnedView`).
466    type ViewHandle: From<OwnedView<Self::View<'static>>>
467        + AsRef<OwnedView<Self::View<'static>>>
468        + Send
469        + Sync
470        + 'static;
471
472    /// Decode a borrowed [`View`](Self::View) from a byte slice.
473    ///
474    /// Convenience for generic code: lets a caller bounded only on
475    /// `M: HasMessageView` write `M::decode_view(buf)` instead of the
476    /// associated-type path
477    /// `<M as HasMessageView>::View::decode_view(buf)`. The returned view
478    /// borrows from `buf`. Reading the returned view (e.g.
479    /// [`to_owned_message`](MessageView::to_owned_message)) requires
480    /// [`MessageView`] in scope.
481    ///
482    /// Like the underlying [`MessageView::decode_view`], this does not
483    /// enforce `max_message_size`; use
484    /// [`decode_view_with_options`](Self::decode_view_with_options) for that.
485    ///
486    /// # Errors
487    ///
488    /// Returns [`DecodeError`] if the buffer contains invalid protobuf data.
489    #[inline]
490    fn decode_view(buf: &[u8]) -> Result<Self::View<'_>, DecodeError> {
491        <Self::View<'_> as MessageView<'_>>::decode_view(buf)
492    }
493
494    /// Decode a borrowed [`View`](Self::View) under custom
495    /// [`DecodeOptions`](crate::DecodeOptions) (recursion limit, max message
496    /// size, unknown-field limit).
497    ///
498    /// Convenience for generic code; equivalent to
499    /// [`DecodeOptions::decode_view::<M::View<'_>>`](crate::DecodeOptions::decode_view).
500    ///
501    /// # Errors
502    ///
503    /// Returns [`DecodeError`] if the buffer is invalid or exceeds the
504    /// configured limits.
505    #[inline]
506    fn decode_view_with_options<'a>(
507        buf: &'a [u8],
508        opts: &crate::DecodeOptions,
509    ) -> Result<Self::View<'a>, DecodeError> {
510        opts.decode_view(buf)
511    }
512
513    /// Decode a [`ViewHandle`](Self::ViewHandle) from a [`Bytes`] buffer.
514    ///
515    /// Convenience for generic code; equivalent to decoding an
516    /// [`OwnedView<Self::View<'static>>`](OwnedView) and converting it with
517    /// `From`.
518    ///
519    /// # Errors
520    ///
521    /// Returns [`DecodeError`] if the buffer contains invalid protobuf data.
522    fn decode_view_handle(bytes: Bytes) -> Result<Self::ViewHandle, DecodeError> {
523        Ok(Self::ViewHandle::from(
524            OwnedView::<Self::View<'static>>::decode(bytes)?,
525        ))
526    }
527
528    /// Decode a [`ViewHandle`](Self::ViewHandle) with custom
529    /// [`DecodeOptions`](crate::DecodeOptions) (recursion limit, max message
530    /// size).
531    ///
532    /// # Errors
533    ///
534    /// Returns [`DecodeError`] if the buffer is invalid or exceeds the
535    /// configured limits.
536    fn decode_view_handle_with_options(
537        bytes: Bytes,
538        opts: &crate::DecodeOptions,
539    ) -> Result<Self::ViewHandle, DecodeError> {
540        Ok(Self::ViewHandle::from(
541            OwnedView::<Self::View<'static>>::decode_with_options(bytes, opts)?,
542        ))
543    }
544}
545
546/// Produce a [`Bytes`] for a borrowed slice, preferring a zero-copy
547/// [`Bytes::slice_ref`] into `source` when the slice lies within it.
548///
549/// Used by generated [`MessageView::to_owned_from_source`] for
550/// `bytes_fields`. Empty slices return [`Bytes::new`]; slices outside
551/// `source` (or `source = None`) fall back to [`Bytes::copy_from_slice`].
552#[doc(hidden)]
553#[inline]
554pub fn bytes_from_source(source: Option<&Bytes>, slice: &[u8]) -> Bytes {
555    if slice.is_empty() {
556        return Bytes::new();
557    }
558    if let Some(b) = source {
559        // Mirrors `slice_ref`'s own containment precondition so we fall back
560        // to copy (rather than panic) for slices outside `source`.
561        let b_start = b.as_ptr() as usize;
562        let s_start = slice.as_ptr() as usize;
563        if let (Some(b_end), Some(s_end)) = (
564            b_start.checked_add(b.len()),
565            s_start.checked_add(slice.len()),
566        ) {
567            if s_start >= b_start && s_end <= b_end {
568                return b.slice_ref(slice);
569            }
570        }
571    }
572    Bytes::copy_from_slice(slice)
573}
574
575/// Serialize a [`MessageView`] directly from its borrowed fields.
576///
577/// Symmetric with [`Message`](crate::Message)'s two-pass
578/// `compute_size` / `write_to` model, but the `&'a str` / `&'a [u8]` /
579/// [`MapView`] / [`RepeatedView`] fields are written by borrow — no
580/// owned-struct intermediary, no per-field `String`/`Vec<u8>` allocations.
581///
582/// Generated `*View<'a>` types implement this trait whenever views are
583/// generated (`generate_views(true)`, the default). Serialization state
584/// lives in the external [`SizeCache`](crate::SizeCache), not the view —
585/// view structs hold no interior mutability and remain `Send + Sync`.
586///
587/// ## When to use
588///
589/// Reach for `ViewEncode` when the source data is already in memory and
590/// you would otherwise allocate an owned message just to encode-then-drop
591/// it — e.g. an RPC handler serializing from app state. If you already
592/// hold the owned message, use [`Message::encode`](crate::Message::encode)
593/// instead; the wire output is identical.
594///
595/// ```rust,ignore
596/// let view = PersonView {
597///     name: "borrowed",
598///     tags: ["a", "b"].iter().copied().collect(),
599///     ..Default::default()
600/// };
601/// let bytes = view.encode_to_vec();
602/// ```
603#[rustversion::attr(
604    since(1.78),
605    diagnostic::on_unimplemented(
606        message = "`{Self}` does not implement `ViewEncode` — view types were not generated for this message",
607        note = "ViewEncode is implemented on every generated `*View<'a>` type; enable `generate_views(true)` (on by default) in your buffa-build / buffa-codegen config"
608    )
609)]
610pub trait ViewEncode<'a>: MessageView<'a> {
611    /// Compute the encoded byte size of this view, recording nested
612    /// sub-message sizes in `cache` for [`write_to`](Self::write_to)
613    /// to consume.
614    ///
615    /// Most callers should use [`encode`](Self::encode) instead, which runs
616    /// both passes with a fresh cache.
617    fn compute_size(&self, cache: &mut crate::SizeCache) -> u32;
618
619    /// Write this view's encoded bytes to a buffer, consuming
620    /// nested-message sizes from `cache` (populated by a prior
621    /// [`compute_size`](Self::compute_size) call on the same cache).
622    ///
623    /// Most callers should use [`encode`](Self::encode) instead.
624    fn write_to(&self, cache: &mut crate::SizeCache, buf: &mut impl BufMut);
625
626    /// Compute size, then write. Primary view-encode entry point.
627    fn encode(&self, buf: &mut impl BufMut) {
628        let mut cache = crate::SizeCache::new();
629        self.compute_size(&mut cache);
630        self.write_to(&mut cache, buf);
631    }
632
633    /// Encode using a caller-supplied [`SizeCache`](crate::SizeCache), for
634    /// reuse across many encodes in a hot loop. Clears the cache first.
635    fn encode_with_cache(&self, cache: &mut crate::SizeCache, buf: &mut impl BufMut) {
636        cache.clear();
637        self.compute_size(cache);
638        self.write_to(cache, buf);
639    }
640
641    /// Compute the encoded byte size of this view.
642    ///
643    /// Walks the view tree, discarding the intermediate
644    /// [`SizeCache`](crate::SizeCache). If you also intend to encode,
645    /// prefer [`encode`](Self::encode) or [`encode_to_vec`](Self::encode_to_vec)
646    /// — they do a single size pass and reuse the cache for the write.
647    #[must_use]
648    fn encoded_len(&self) -> u32 {
649        self.compute_size(&mut crate::SizeCache::new())
650    }
651
652    /// Encode this view as a length-delimited byte sequence.
653    fn encode_length_delimited(&self, buf: &mut impl BufMut) {
654        let mut cache = crate::SizeCache::new();
655        let len = self.compute_size(&mut cache);
656        crate::encoding::encode_varint(len as u64, buf);
657        self.write_to(&mut cache, buf);
658    }
659
660    /// Encode this view to a new `Vec<u8>`.
661    #[must_use]
662    fn encode_to_vec(&self) -> alloc::vec::Vec<u8> {
663        let mut cache = crate::SizeCache::new();
664        let size = self.compute_size(&mut cache) as usize;
665        let mut buf = alloc::vec::Vec::with_capacity(size);
666        self.write_to(&mut cache, &mut buf);
667        buf
668    }
669
670    /// Encode this view to a new [`bytes::Bytes`].
671    #[must_use]
672    fn encode_to_bytes(&self) -> Bytes {
673        let mut cache = crate::SizeCache::new();
674        let size = self.compute_size(&mut cache) as usize;
675        let mut buf = bytes::BytesMut::with_capacity(size);
676        self.write_to(&mut cache, &mut buf);
677        buf.freeze()
678    }
679}
680
681/// Provides access to a lazily-initialized default view instance.
682///
683/// View types implement this trait so that [`MessageFieldView`] can
684/// dereference to a default when unset, just as [`MessageField`](crate::MessageField)
685/// does for owned types via [`DefaultInstance`](crate::DefaultInstance).
686///
687/// Generated view types like `FooView<'a>` contain only covariant borrows
688/// (`&'a str`, `&'a [u8]`, etc.). A default view holds only `'static` data
689/// (`""`, `&[]`, `0`), so an implementation stores a single
690/// `&'static FooView<'static>` and returns it at the caller's lifetime via
691/// ordinary covariant subtyping — the compiler verifies covariance at the
692/// `impl` site, so no `unsafe` is required.
693///
694/// # Recommended implementation
695///
696/// The pattern codegen uses (and the recommended pattern for hand-written
697/// view types) stores the instance in a static
698/// [`once_cell::race::OnceBox`] (re-exported as
699/// `::buffa::__private::OnceBox`):
700///
701/// ```rust,ignore
702/// impl<'v> DefaultViewInstance for MyView<'v> {
703///     fn default_view_instance<'a>() -> &'a Self
704///     where
705///         Self: 'a,
706///     {
707///         static VALUE: ::buffa::__private::OnceBox<MyView<'static>>
708///             = ::buffa::__private::OnceBox::new();
709///         VALUE.get_or_init(|| Box::new(<MyView<'static>>::default()))
710///     }
711/// }
712/// ```
713///
714/// The return expression has type `&'static MyView<'static>`; the compiler
715/// coerces it to `&'a MyView<'v>` iff `MyView` is covariant in `'v` —
716/// non-covariant view types fail to compile here rather than risk an
717/// unsound cast.
718///
719/// # Non-covariant types are rejected
720///
721/// A type that is invariant in its lifetime parameter cannot satisfy the
722/// recommended pattern, because the `&'static T<'static> → &'a T<'v>`
723/// coercion is refused:
724///
725/// ```compile_fail
726/// # use core::marker::PhantomData;
727/// // `fn(&'v ()) -> &'v ()` is invariant in 'v, making `Invariant<'v>` invariant.
728/// struct Invariant<'v>(PhantomData<fn(&'v ()) -> &'v ()>);
729/// static INST: Invariant<'static> = Invariant(PhantomData);
730///
731/// impl<'v> buffa::view::DefaultViewInstance for Invariant<'v> {
732///     fn default_view_instance<'a>() -> &'a Self where Self: 'a {
733///         // error: lifetime may not live long enough
734///         //   note: requirement occurs because of the type `Invariant<'_>`,
735///         //         which makes the generic argument `'_` invariant
736///         &INST
737///     }
738/// }
739/// ```
740pub trait DefaultViewInstance {
741    /// Return a reference to the single default view instance.
742    ///
743    /// The lifetime `'a` is caller-chosen up to `Self: 'a`, so a
744    /// `FooView<'v>` can serve its `'static` default at any `'a ≤ 'v`.
745    fn default_view_instance<'a>() -> &'a Self
746    where
747        Self: 'a;
748}
749
750/// Implement [`DefaultViewInstance`] for a generated view type via a
751/// lazily-initialized `OnceBox<FooView<'static>>` singleton.
752///
753/// Emitted by generated code (one invocation per view struct). The static
754/// holds the `'static` instantiation; returning it at any shorter `'a` is
755/// sound because view lifetimes are covariant.
756///
757/// ```rust,ignore
758/// buffa::impl_default_view_instance!(MyMessageView);
759/// ```
760#[macro_export]
761macro_rules! impl_default_view_instance {
762    ($ty:ident) => {
763        impl<'v> $crate::DefaultViewInstance for $ty<'v> {
764            fn default_view_instance<'a>() -> &'a Self
765            where
766                Self: 'a,
767            {
768                static VALUE: $crate::__private::OnceBox<$ty<'static>> =
769                    $crate::__private::OnceBox::new();
770                VALUE.get_or_init(|| {
771                    $crate::alloc::boxed::Box::new(
772                        <$ty<'static> as ::core::default::Default>::default(),
773                    )
774                })
775            }
776        }
777    };
778}
779
780/// A borrowed view of an optional message field.
781///
782/// Analogous to [`MessageField<T>`](crate::MessageField) but for the view
783/// layer. Like `MessageField`, the inner view is **boxed** — recursive
784/// message types (`Foo { NestedMessage { corecursive: Foo } }`) would
785/// otherwise have infinite size. The box is API-transparent: `Deref`
786/// returns `&V`, and `set()` takes `V` by value.
787///
788/// When `V` implements [`DefaultViewInstance`], this type implements
789/// [`Deref<Target = V>`](core::ops::Deref), returning a reference to a
790/// static default instance when the field is unset — making view code
791/// identical to owned code for field access:
792///
793/// ```rust,ignore
794/// // Both work the same, regardless of whether `address` is set:
795/// let city = owned_msg.address.city;    // MessageField<Address>
796/// let city = view_msg.address.city;     // MessageFieldView<AddressView>
797/// ```
798///
799/// The lifetime of the contained view type `V` (e.g. `AddressView<'a>`)
800/// ties this to the input buffer — no separate lifetime parameter is
801/// needed here.
802#[derive(Clone, Debug)]
803pub struct MessageFieldView<V> {
804    inner: Option<alloc::boxed::Box<V>>,
805}
806
807impl<V> MessageFieldView<V> {
808    /// An unset field (the default).
809    #[inline]
810    pub const fn unset() -> Self {
811        Self { inner: None }
812    }
813
814    /// A set field with the given view value.
815    #[inline]
816    pub fn set(v: V) -> Self {
817        Self {
818            inner: Some(alloc::boxed::Box::new(v)),
819        }
820    }
821
822    /// Alias for [`set`](Self::set), mirroring owned
823    /// [`MessageField::some`](crate::MessageField::some).
824    #[inline]
825    pub fn some(v: V) -> Self {
826        Self::set(v)
827    }
828
829    /// Returns `true` if the field has a value.
830    #[inline]
831    pub const fn is_set(&self) -> bool {
832        self.inner.is_some()
833    }
834
835    /// Returns `true` if the field has no value.
836    #[inline]
837    pub const fn is_unset(&self) -> bool {
838        self.inner.is_none()
839    }
840
841    /// Get a reference to the inner view, or `None` if unset.
842    #[inline]
843    pub fn as_option(&self) -> Option<&V> {
844        self.inner.as_deref()
845    }
846
847    /// Get a mutable reference to the inner view, or `None` if unset.
848    ///
849    /// Used by generated decode code to merge a second occurrence of a
850    /// message field into an existing value (proto merge semantics).
851    #[inline]
852    pub fn as_mut(&mut self) -> Option<&mut V> {
853        self.inner.as_deref_mut()
854    }
855}
856
857impl<'a, V: ViewEncode<'a>> MessageFieldView<V> {
858    /// Forward to the inner view's [`compute_size`](ViewEncode::compute_size),
859    /// or `0` if unset. Generated `compute_size` calls this for nested-message
860    /// fields, mirroring [`MessageField`](crate::MessageField) on the owned side.
861    #[inline]
862    pub fn compute_size(&self, cache: &mut crate::SizeCache) -> u32 {
863        self.inner.as_deref().map_or(0, |v| v.compute_size(cache))
864    }
865
866    /// Forward to the inner view's [`write_to`](ViewEncode::write_to);
867    /// no-op if unset.
868    #[inline]
869    pub fn write_to(&self, cache: &mut crate::SizeCache, buf: &mut impl BufMut) {
870        if let Some(v) = self.inner.as_deref() {
871            v.write_to(cache, buf);
872        }
873    }
874}
875
876impl<V> Default for MessageFieldView<V> {
877    #[inline]
878    fn default() -> Self {
879        Self::unset()
880    }
881}
882
883impl<V> From<V> for MessageFieldView<V> {
884    #[inline]
885    fn from(v: V) -> Self {
886        Self::set(v)
887    }
888}
889
890impl<V: DefaultViewInstance> core::ops::Deref for MessageFieldView<V> {
891    type Target = V;
892
893    #[inline]
894    fn deref(&self) -> &V {
895        self.inner
896            .as_deref()
897            .unwrap_or_else(V::default_view_instance)
898    }
899}
900
901/// Wire-equivalent equality: `Unset` equals `Set(v)` when `v` equals the
902/// default instance.
903///
904/// This matches [`MessageField::eq`](crate::MessageField) on the owned side,
905/// so `view_a == view_b` agrees with
906/// `view_a.to_owned_message() == view_b.to_owned_message()`.
907///
908/// The comparison against the default routes through the
909/// [`Deref`](core::ops::Deref) impl.
910impl<V: PartialEq + DefaultViewInstance> PartialEq for MessageFieldView<V> {
911    fn eq(&self, other: &Self) -> bool {
912        match (&self.inner, &other.inner) {
913            // Short-circuit: two unset fields are equal regardless of whether
914            // V::PartialEq is reflexive (e.g. a view containing an f64 NaN).
915            (None, None) => true,
916            // At least one side is set. Deref handles None → default.
917            _ => {
918                <Self as core::ops::Deref>::deref(self) == <Self as core::ops::Deref>::deref(other)
919            }
920        }
921    }
922}
923
924impl<V: Eq + DefaultViewInstance> Eq for MessageFieldView<V> {}
925
926// ---------------------------------------------------------------------------
927// Lazy views (generated under the `lazy_views` codegen option)
928// ---------------------------------------------------------------------------
929
930/// The trait implemented by generated lazy view types (`FooLazyView<'a>`).
931///
932/// Lazy views are a separate, additive type family generated alongside the
933/// eager `FooView` family under the `lazy_views` codegen option. Where
934/// [`MessageView`]'s contract is "decode succeeded ⇒ the whole tree was
935/// validated", a lazy view's [`decode_lazy`](Self::decode_lazy) performs a
936/// single non-recursive scan over the message's own fields: scalar, string,
937/// and bytes fields are borrowed exactly as in the eager view, while nested
938/// and repeated message fields are *recorded* as undecoded byte ranges (see
939/// [`LazyMessageFieldView`] / [`LazyRepeatedView`]) and decoded only on
940/// access. Deferred validation is therefore visible in the type and trait
941/// bound — generic code over `MessageView` never silently inherits it.
942pub trait LazyMessageView<'a>: Sized {
943    /// The corresponding owned message type.
944    type Owned: crate::Message;
945
946    /// Decode a lazy view from `buf`: one scan over the message's own
947    /// fields, deferring nested message fields.
948    ///
949    /// # Errors
950    ///
951    /// Returns [`DecodeError`] if the message's *own* fields are malformed.
952    /// Deferred sub-message bytes are **not** validated here; they surface
953    /// errors on access.
954    fn decode_lazy(buf: &'a [u8]) -> Result<Self, DecodeError>;
955
956    /// Decode a lazy view under custom decode limits.
957    ///
958    /// Used by [`DecodeOptions::decode_lazy_view`](crate::DecodeOptions::decode_lazy_view).
959    /// The budgets remaining at each deferred field's position are recorded
960    /// and charged when that field is accessed, so custom limits flow through
961    /// deferred decoding. The default implementation delegates to
962    /// [`decode_lazy`](Self::decode_lazy) and **ignores the context**;
963    /// generated code always overrides it.
964    ///
965    /// # Errors
966    ///
967    /// Same contract as [`decode_lazy`](Self::decode_lazy), plus
968    /// [`DecodeError::RecursionLimitExceeded`] /
969    /// [`DecodeError::UnknownFieldLimitExceeded`] when `ctx`'s budgets are
970    /// exhausted by the message's own fields.
971    fn decode_lazy_with_ctx(
972        buf: &'a [u8],
973        ctx: crate::DecodeContext<'_>,
974    ) -> Result<Self, DecodeError> {
975        let _ = ctx;
976        Self::decode_lazy(buf)
977    }
978
979    /// Merge fields decoded from `buf` into this view (proto merge
980    /// semantics: singular scalars last-wins, repeated append, deferred
981    /// message fragments accumulate).
982    ///
983    /// Used by [`LazyMessageFieldView::get`] to reassemble a field whose
984    /// value was split across multiple wire occurrences — application code
985    /// rarely calls this directly.
986    ///
987    /// # Errors
988    ///
989    /// Same contract as [`decode_lazy_with_ctx`](Self::decode_lazy_with_ctx).
990    fn merge_lazy(
991        &mut self,
992        buf: &'a [u8],
993        ctx: crate::DecodeContext<'_>,
994    ) -> Result<(), DecodeError>;
995
996    /// Convert this view to the owned message type.
997    ///
998    /// This decodes every deferred sub-message, so it is where deferred
999    /// validation errors surface. Each deferred subtree decodes under its
1000    /// own replayed unknown-field allowance (see
1001    /// [`LazyMessageFieldView::get`]), so the conversion's total
1002    /// unknown-field records are bounded per subtree, not globally as in an
1003    /// eager decode.
1004    ///
1005    /// # Errors
1006    ///
1007    /// Returns the [`DecodeError`] that accessing a malformed or
1008    /// over-budget deferred field would have reported. Unlike
1009    /// [`MessageView::to_owned_message`], this conversion can genuinely
1010    /// fail for a wire-decoded lazy view: deferred subtrees were never
1011    /// validated (or charged against the unknown-field allowance) at
1012    /// decode time, so their errors surface here.
1013    fn to_owned_message(&self) -> Result<Self::Owned, DecodeError>;
1014}
1015
1016/// Fragments of one singular message field. `Many` only arises when an
1017/// encoder split the field across occurrences, keeping the common
1018/// single-occurrence path allocation-free.
1019#[derive(Clone)]
1020enum LazyFragments<'a> {
1021    None,
1022    One(&'a [u8]),
1023    Many(alloc::vec::Vec<&'a [u8]>),
1024}
1025
1026/// A deferred view of a singular message field on a lazy view.
1027///
1028/// Unlike [`MessageFieldView`] — which eagerly decodes (and boxes) the
1029/// sub-message during decode — this stores only the field's undecoded wire
1030/// bytes and decodes a fresh `V` on each [`get`](Self::get), so decoding the
1031/// enclosing message does not allocate or recurse into sub-messages the
1032/// caller never reads.
1033///
1034/// `get` returns a freshly-decoded view each call (views are thin borrows,
1035/// so this is cheap) and does not cache — bind the result when reading
1036/// several fields.
1037///
1038/// # Merge semantics
1039///
1040/// A singular message field may legally appear more than once on the wire;
1041/// decoders must merge the occurrences. This type stores each occurrence's
1042/// bytes as a separate fragment and [`get`](Self::get) replays them in order
1043/// (decode the first, [`LazyMessageView::merge_lazy`] the rest), so the
1044/// result matches the eager and owned decoders.
1045///
1046/// # Deferred validation and budgets
1047///
1048/// The fragment bytes are *not* validated when the enclosing view is
1049/// decoded; a malformed sub-message surfaces as a [`DecodeError`] from
1050/// [`get`](Self::get). The recursion budget and unknown-field allowance
1051/// remaining when the field was recorded are stored alongside the fragments,
1052/// and each access replays them as a fresh per-subtree budget (see
1053/// [`get`](Self::get) for the approximation this implies). Deep lazy chains
1054/// fail with [`DecodeError::RecursionLimitExceeded`] at the same boundary as
1055/// the eager decoder, and custom limits passed to the enclosing
1056/// [`decode_lazy_with_ctx`](LazyMessageView::decode_lazy_with_ctx) flow
1057/// through.
1058///
1059/// # Re-encoding
1060///
1061/// `ViewEncode` on the enclosing lazy view replays the recorded fragments
1062/// byte-for-byte **without validating them** — re-encoding a never-accessed
1063/// malformed field round-trips its bytes silently.
1064pub struct LazyMessageFieldView<'a, V> {
1065    raw: LazyFragments<'a>,
1066    depth: u32,
1067    allowance: usize,
1068    _marker: core::marker::PhantomData<fn() -> V>,
1069}
1070
1071impl<'a, V> LazyMessageFieldView<'a, V> {
1072    /// An unset field (the default).
1073    #[inline]
1074    pub const fn unset() -> Self {
1075        Self {
1076            raw: LazyFragments::None,
1077            // Sentinels: the first `push_fragment` lowers these to its
1078            // recorded budgets, so custom limits above the defaults aren't
1079            // clamped.
1080            depth: u32::MAX,
1081            allowance: usize::MAX,
1082            _marker: core::marker::PhantomData,
1083        }
1084    }
1085
1086    /// A set field carrying the sub-message's undecoded wire bytes, with the
1087    /// default recursion and unknown-field budgets for access.
1088    #[inline]
1089    pub const fn from_bytes(raw: &'a [u8]) -> Self {
1090        Self {
1091            raw: LazyFragments::One(raw),
1092            depth: crate::RECURSION_LIMIT,
1093            allowance: crate::DEFAULT_UNKNOWN_FIELD_LIMIT,
1094            _marker: core::marker::PhantomData,
1095        }
1096    }
1097
1098    /// Append one wire occurrence of the field (used by generated
1099    /// `decode_lazy`). Fragments accumulate in wire order; [`get`](Self::get)
1100    /// merges them. `ctx` carries the recursion budget and unknown-field
1101    /// allowance remaining at the record site; the smallest pushed budgets
1102    /// are charged on access.
1103    #[doc(hidden)]
1104    #[inline]
1105    pub fn push_fragment(&mut self, raw: &'a [u8], ctx: crate::DecodeContext<'_>) {
1106        self.depth = self.depth.min(ctx.depth());
1107        self.allowance = self.allowance.min(ctx.remaining_unknown_fields());
1108        self.raw = match core::mem::replace(&mut self.raw, LazyFragments::None) {
1109            LazyFragments::None => LazyFragments::One(raw),
1110            LazyFragments::One(first) => LazyFragments::Many(alloc::vec![first, raw]),
1111            LazyFragments::Many(mut frags) => {
1112                frags.push(raw);
1113                LazyFragments::Many(frags)
1114            }
1115        };
1116    }
1117
1118    /// Whether the field is present.
1119    #[inline]
1120    pub const fn is_set(&self) -> bool {
1121        !matches!(self.raw, LazyFragments::None)
1122    }
1123
1124    /// Whether the field has no value.
1125    #[inline]
1126    pub const fn is_unset(&self) -> bool {
1127        matches!(self.raw, LazyFragments::None)
1128    }
1129
1130    /// The undecoded wire fragments, in wire order (empty if unset).
1131    ///
1132    /// A singular message field that appeared exactly once on the wire — the
1133    /// common case — yields one fragment. Encoders that split the field
1134    /// across multiple occurrences yield one fragment per occurrence;
1135    /// [`get`](Self::get) merges them per proto semantics.
1136    #[inline]
1137    pub fn fragments(&self) -> &[&'a [u8]] {
1138        match &self.raw {
1139            LazyFragments::None => &[],
1140            LazyFragments::One(raw) => core::slice::from_ref(raw),
1141            LazyFragments::Many(frags) => frags,
1142        }
1143    }
1144}
1145
1146impl<'a, V: LazyMessageView<'a>> LazyMessageFieldView<'a, V> {
1147    /// Decode and return the sub-message view, or `None` if unset.
1148    ///
1149    /// Multiple wire fragments are merged per proto semantics (see the type
1150    /// docs). The view is re-decoded on every call; there is no cache — bind
1151    /// the result when reading several fields. Note the shape difference
1152    /// from [`LazyRepeatedView::get`], which returns `Option<Result<V, _>>`.
1153    ///
1154    /// Each access rebuilds a fresh decode context from the budgets recorded
1155    /// at decode time, so every deferred subtree independently gets the full
1156    /// recorded unknown-field allowance rather than sharing one pool with
1157    /// its siblings (the original decode call's shared allowance is gone by
1158    /// access time). The unknown-field limit is therefore a *per-subtree*
1159    /// bound on the lazy path, not the global decode-time cap the eager
1160    /// decoder enforces: a full traversal can materialize unknown-field
1161    /// records proportional to input size, where eager
1162    /// [`decode_view`](crate::DecodeOptions::decode_view) rejects such input
1163    /// up front. Prefer the eager path for untrusted input if that global
1164    /// bound matters.
1165    ///
1166    /// # Errors
1167    ///
1168    /// Returns [`DecodeError`] if the deferred bytes are not a valid
1169    /// encoding of `V` — validation happens here, not when the enclosing
1170    /// view was decoded — [`DecodeError::RecursionLimitExceeded`] when the
1171    /// recursion budget recorded at decode time is exhausted, or
1172    /// [`DecodeError::UnknownFieldLimitExceeded`] when the unknown-field
1173    /// allowance recorded at decode time is exhausted.
1174    #[inline]
1175    pub fn get(&self) -> Result<Option<V>, DecodeError> {
1176        let allowance = core::cell::Cell::new(self.allowance);
1177        let ctx = crate::DecodeContext::new(self.depth, &allowance);
1178        match &self.raw {
1179            LazyFragments::None => Ok(None),
1180            LazyFragments::One(raw) => V::decode_lazy_with_ctx(raw, ctx).map(Some),
1181            LazyFragments::Many(frags) => {
1182                // `Many` always holds ≥ 2 fragments (see `push_fragment`);
1183                // the guard is belt-and-suspenders.
1184                let mut iter = frags.iter();
1185                let Some(first) = iter.next() else {
1186                    return Ok(None);
1187                };
1188                let mut view = V::decode_lazy_with_ctx(first, ctx)?;
1189                for frag in iter {
1190                    view.merge_lazy(frag, ctx)?;
1191                }
1192                Ok(Some(view))
1193            }
1194        }
1195    }
1196
1197    /// Like [`get`](Self::get), but an unset field decodes to the default
1198    /// view — the lazy analogue of [`MessageFieldView`]'s deref-to-default,
1199    /// for the common read path:
1200    ///
1201    /// ```rust,ignore
1202    /// let city = view.address.get_or_default()?.city;
1203    /// ```
1204    ///
1205    /// # Errors
1206    ///
1207    /// Same as [`get`](Self::get).
1208    #[inline]
1209    pub fn get_or_default(&self) -> Result<V, DecodeError>
1210    where
1211        V: Default,
1212    {
1213        Ok(self.get()?.unwrap_or_default())
1214    }
1215}
1216
1217impl<V> Clone for LazyMessageFieldView<'_, V> {
1218    #[inline]
1219    fn clone(&self) -> Self {
1220        Self {
1221            raw: self.raw.clone(),
1222            depth: self.depth,
1223            allowance: self.allowance,
1224            _marker: core::marker::PhantomData,
1225        }
1226    }
1227}
1228impl<V> Default for LazyMessageFieldView<'_, V> {
1229    #[inline]
1230    fn default() -> Self {
1231        Self::unset()
1232    }
1233}
1234impl<V> core::fmt::Debug for LazyMessageFieldView<'_, V> {
1235    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1236        f.debug_struct("LazyMessageFieldView")
1237            .field("is_set", &self.is_set())
1238            .field("fragments", &self.fragments().len())
1239            .finish()
1240    }
1241}
1242
1243/// A deferred view of a repeated message field on a lazy view.
1244///
1245/// Holds the wire byte-slice of each element (cheap pointers) and decodes a
1246/// fresh element view on access ([`get`](Self::get)) or iteration
1247/// ([`iter`](Self::iter)), instead of eagerly decoding every element into a
1248/// `Vec` like [`RepeatedView`].
1249///
1250/// Element bytes are *not* validated when the enclosing view is decoded; a
1251/// malformed element surfaces as a [`DecodeError`] from `get`/`iter`. Unlike
1252/// [`RepeatedView`], this type is not slice-backed: there is no `Deref` or
1253/// indexing, use `get`/`iter`/`len`. Budgets and re-encoding behave as on
1254/// [`LazyMessageFieldView`].
1255pub struct LazyRepeatedView<'a, V> {
1256    elements: alloc::vec::Vec<&'a [u8]>,
1257    depth: u32,
1258    allowance: usize,
1259    _marker: core::marker::PhantomData<fn() -> V>,
1260}
1261
1262impl<'a, V> LazyRepeatedView<'a, V> {
1263    /// An empty repeated field.
1264    #[inline]
1265    pub fn new() -> Self {
1266        Self {
1267            elements: alloc::vec::Vec::new(),
1268            // Sentinels — see `LazyMessageFieldView::unset`.
1269            depth: u32::MAX,
1270            allowance: usize::MAX,
1271            _marker: core::marker::PhantomData,
1272        }
1273    }
1274
1275    /// Number of elements.
1276    #[inline]
1277    pub fn len(&self) -> usize {
1278        self.elements.len()
1279    }
1280
1281    /// Whether the field has no elements.
1282    #[inline]
1283    pub fn is_empty(&self) -> bool {
1284        self.elements.is_empty()
1285    }
1286
1287    /// The undecoded wire bytes of each element, in wire order.
1288    #[inline]
1289    pub fn raw_elements(&self) -> &[&'a [u8]] {
1290        &self.elements
1291    }
1292
1293    /// Append an element's undecoded bytes (used by generated `decode_lazy`).
1294    /// `ctx` carries the recursion budget and unknown-field allowance
1295    /// remaining at the record site; the smallest pushed budgets are charged
1296    /// on access.
1297    #[doc(hidden)]
1298    #[inline]
1299    pub fn push_bytes(&mut self, raw: &'a [u8], ctx: crate::DecodeContext<'_>) {
1300        self.depth = self.depth.min(ctx.depth());
1301        self.allowance = self.allowance.min(ctx.remaining_unknown_fields());
1302        self.elements.push(raw);
1303    }
1304}
1305
1306/// Decode one deferred element under a fresh context carrying the budgets
1307/// recorded at decode time. Each access decodes independently, so each gets
1308/// the full recorded allowance — a per-subtree bound, not the eager
1309/// decoder's shared global pool (see [`LazyMessageFieldView::get`]).
1310#[inline]
1311fn decode_deferred<'a, V: LazyMessageView<'a>>(
1312    raw: &'a [u8],
1313    depth: u32,
1314    allowance: usize,
1315) -> Result<V, DecodeError> {
1316    let cell = core::cell::Cell::new(allowance);
1317    V::decode_lazy_with_ctx(raw, crate::DecodeContext::new(depth, &cell))
1318}
1319
1320impl<'a, V: LazyMessageView<'a>> LazyRepeatedView<'a, V> {
1321    /// Decode the element at `index`, or `None` if out of range.
1322    ///
1323    /// Re-decodes on every call (no cache) — bind the result when reading
1324    /// multiple fields, and avoid calling it inside a tight loop over the
1325    /// same index. Note the shape difference from
1326    /// [`LazyMessageFieldView::get`], which returns `Result<Option<V>, _>`.
1327    #[inline]
1328    pub fn get(&self, index: usize) -> Option<Result<V, DecodeError>> {
1329        self.elements
1330            .get(index)
1331            .map(|b| decode_deferred(b, self.depth, self.allowance))
1332    }
1333
1334    /// Like [`get`](Self::get) with the layers flipped to match
1335    /// [`LazyMessageFieldView::get`]'s `Result<Option<_>, _>` shape:
1336    /// out-of-range yields `Ok(None)`.
1337    ///
1338    /// # Errors
1339    ///
1340    /// Same as [`get`](Self::get).
1341    #[inline]
1342    pub fn try_get(&self, index: usize) -> Result<Option<V>, DecodeError> {
1343        self.get(index).transpose()
1344    }
1345
1346    /// Iterate the elements, decoding each on the fly.
1347    ///
1348    /// Yields `Result<V, DecodeError>` — element bytes are validated here,
1349    /// not when the enclosing view was decoded. Each pass over the iterator
1350    /// re-decodes the elements (no cache).
1351    #[inline]
1352    pub fn iter(&self) -> LazyRepeatedIter<'_, 'a, V> {
1353        LazyRepeatedIter {
1354            inner: self.elements.iter(),
1355            depth: self.depth,
1356            allowance: self.allowance,
1357            _marker: core::marker::PhantomData,
1358        }
1359    }
1360}
1361
1362impl<'s, 'a, V: LazyMessageView<'a>> IntoIterator for &'s LazyRepeatedView<'a, V> {
1363    type Item = Result<V, DecodeError>;
1364    type IntoIter = LazyRepeatedIter<'s, 'a, V>;
1365
1366    #[inline]
1367    fn into_iter(self) -> Self::IntoIter {
1368        self.iter()
1369    }
1370}
1371
1372/// Iterator over a [`LazyRepeatedView`], decoding each element on `next`.
1373#[derive(Clone, Debug)]
1374pub struct LazyRepeatedIter<'s, 'a, V> {
1375    inner: core::slice::Iter<'s, &'a [u8]>,
1376    depth: u32,
1377    allowance: usize,
1378    _marker: core::marker::PhantomData<fn() -> V>,
1379}
1380
1381impl<'a, V: LazyMessageView<'a>> Iterator for LazyRepeatedIter<'_, 'a, V> {
1382    type Item = Result<V, DecodeError>;
1383
1384    #[inline]
1385    fn next(&mut self) -> Option<Self::Item> {
1386        self.inner
1387            .next()
1388            .map(|b| decode_deferred(b, self.depth, self.allowance))
1389    }
1390
1391    #[inline]
1392    fn size_hint(&self) -> (usize, Option<usize>) {
1393        self.inner.size_hint()
1394    }
1395}
1396
1397impl<'a, V: LazyMessageView<'a>> DoubleEndedIterator for LazyRepeatedIter<'_, 'a, V> {
1398    #[inline]
1399    fn next_back(&mut self) -> Option<Self::Item> {
1400        self.inner
1401            .next_back()
1402            .map(|b| decode_deferred(b, self.depth, self.allowance))
1403    }
1404}
1405
1406impl<'a, V: LazyMessageView<'a>> ExactSizeIterator for LazyRepeatedIter<'_, 'a, V> {}
1407
1408impl<V> Clone for LazyRepeatedView<'_, V> {
1409    #[inline]
1410    fn clone(&self) -> Self {
1411        Self {
1412            elements: self.elements.clone(),
1413            depth: self.depth,
1414            allowance: self.allowance,
1415            _marker: core::marker::PhantomData,
1416        }
1417    }
1418}
1419impl<V> Default for LazyRepeatedView<'_, V> {
1420    #[inline]
1421    fn default() -> Self {
1422        Self::new()
1423    }
1424}
1425impl<V> core::fmt::Debug for LazyRepeatedView<'_, V> {
1426    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1427        f.debug_struct("LazyRepeatedView")
1428            .field("len", &self.len())
1429            .finish()
1430    }
1431}
1432
1433/// A borrowed view of a repeated field.
1434///
1435/// For scalar repeated fields, this is backed by a decoded `Vec` (scalars
1436/// can't be zero-copy because they require varint decoding). For string and
1437/// bytes repeated fields, elements borrow from the input buffer.
1438#[derive(Clone, Debug, PartialEq, Eq)]
1439pub struct RepeatedView<'a, T> {
1440    elements: alloc::vec::Vec<T>,
1441    _marker: core::marker::PhantomData<&'a ()>,
1442}
1443
1444impl<'a, T> RepeatedView<'a, T> {
1445    /// Create from a vec of decoded elements.
1446    pub fn new(elements: alloc::vec::Vec<T>) -> Self {
1447        Self {
1448            elements,
1449            _marker: core::marker::PhantomData,
1450        }
1451    }
1452
1453    /// Returns the number of elements.
1454    pub fn len(&self) -> usize {
1455        self.elements.len()
1456    }
1457
1458    /// Returns `true` if the repeated field contains no elements.
1459    pub fn is_empty(&self) -> bool {
1460        self.elements.is_empty()
1461    }
1462
1463    /// Append an element (used by generated `decode_view` code).
1464    #[doc(hidden)]
1465    pub fn push(&mut self, elem: T) {
1466        self.elements.push(elem);
1467    }
1468
1469    /// Reserve capacity for at least `additional` more elements (used by
1470    /// generated `decode_view` code as a pre-allocation hint for packed
1471    /// repeated scalars). For varint elements the hint is an upper bound
1472    /// (every element occupies at least one byte on the wire); for fixed-
1473    /// size elements it is the exact remaining element count.
1474    #[doc(hidden)]
1475    pub fn reserve(&mut self, additional: usize) {
1476        self.elements.reserve(additional);
1477    }
1478
1479    /// Returns an iterator over the elements.
1480    pub fn iter(&self) -> core::slice::Iter<'_, T> {
1481        self.elements.iter()
1482    }
1483}
1484
1485impl<'a, T> Default for RepeatedView<'a, T> {
1486    fn default() -> Self {
1487        Self {
1488            elements: alloc::vec::Vec::new(),
1489            _marker: core::marker::PhantomData,
1490        }
1491    }
1492}
1493
1494impl<'a, T> core::ops::Deref for RepeatedView<'a, T> {
1495    type Target = [T];
1496
1497    fn deref(&self) -> &[T] {
1498        &self.elements
1499    }
1500}
1501
1502impl<'a, T> IntoIterator for RepeatedView<'a, T> {
1503    type Item = T;
1504    type IntoIter = alloc::vec::IntoIter<T>;
1505
1506    fn into_iter(self) -> Self::IntoIter {
1507        self.elements.into_iter()
1508    }
1509}
1510
1511impl<'b, 'a, T> IntoIterator for &'b RepeatedView<'a, T> {
1512    type Item = &'b T;
1513    type IntoIter = core::slice::Iter<'b, T>;
1514
1515    fn into_iter(self) -> Self::IntoIter {
1516        self.elements.iter()
1517    }
1518}
1519
1520impl<'a, T> From<alloc::vec::Vec<T>> for RepeatedView<'a, T> {
1521    fn from(elements: alloc::vec::Vec<T>) -> Self {
1522        Self::new(elements)
1523    }
1524}
1525
1526impl<'a, T> FromIterator<T> for RepeatedView<'a, T> {
1527    fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
1528        Self::new(iter.into_iter().collect())
1529    }
1530}
1531
1532/// A borrowed view of a map field.
1533///
1534/// Protobuf `map<K, V>` fields are encoded as repeated sub-messages, each
1535/// containing a key (field 1) and value (field 2). This type stores the
1536/// decoded entries in a `Vec<(K, V)>`, borrowing string and bytes keys/values
1537/// directly from the input buffer.
1538///
1539/// Lookup is O(n) linear scan, which is appropriate for the typically small
1540/// maps found in protobuf messages (metadata labels, headers, etc.).
1541/// If duplicate keys appear on the wire, [`get`](MapView::get) returns the
1542/// last occurrence (last-write-wins, per the protobuf spec).
1543///
1544/// For larger maps where O(1) lookup matters, collect into a `HashMap`:
1545///
1546/// ```ignore
1547/// use std::collections::HashMap;
1548/// let index: HashMap<&str, &str> = view.labels.into_iter().collect();
1549/// ```
1550///
1551/// Duplicate keys resolve last-write-wins in the collected map (matching
1552/// proto map semantics), since `HashMap::from_iter` keeps the last value.
1553///
1554/// # Allocation
1555///
1556/// Like [`RepeatedView`], the `Vec` backing store requires allocation.
1557/// The individual keys and values borrow from the input buffer where possible
1558/// (string keys as `&'a str`, bytes values as `&'a [u8]`).
1559#[derive(Clone, Debug, PartialEq, Eq)]
1560pub struct MapView<'a, K, V> {
1561    entries: alloc::vec::Vec<(K, V)>,
1562    _marker: core::marker::PhantomData<&'a ()>,
1563}
1564
1565impl<'a, K, V> MapView<'a, K, V> {
1566    /// Construct from a `Vec` of entries, for [`ViewEncode`] use.
1567    ///
1568    /// Duplicate keys are kept and all encoded — valid protobuf wire data
1569    /// (decoders apply last-write-wins). Mirrors [`RepeatedView::new`].
1570    pub fn new(entries: alloc::vec::Vec<(K, V)>) -> Self {
1571        Self {
1572            entries,
1573            _marker: core::marker::PhantomData,
1574        }
1575    }
1576
1577    /// Returns the number of entries (including duplicates).
1578    pub fn len(&self) -> usize {
1579        self.entries.len()
1580    }
1581
1582    /// Returns `true` if there are no entries.
1583    pub fn is_empty(&self) -> bool {
1584        self.entries.is_empty()
1585    }
1586
1587    /// Append a key-value pair (used by generated `decode_view` code).
1588    #[doc(hidden)]
1589    pub fn push(&mut self, key: K, value: V) {
1590        self.entries.push((key, value));
1591    }
1592
1593    /// Iterate over all entries in wire order.
1594    ///
1595    /// If duplicate keys exist, all occurrences are yielded.
1596    pub fn iter(&self) -> core::slice::Iter<'_, (K, V)> {
1597        self.entries.iter()
1598    }
1599
1600    /// Iterate over all keys in wire order.
1601    pub fn keys(&self) -> impl Iterator<Item = &K> {
1602        self.entries.iter().map(|(k, _)| k)
1603    }
1604
1605    /// Iterate over all values in wire order.
1606    pub fn values(&self) -> impl Iterator<Item = &V> {
1607        self.entries.iter().map(|(_, v)| v)
1608    }
1609
1610    /// Look up a value by key, returning the last occurrence (last-write-wins).
1611    ///
1612    /// Accepts any type that `K` can borrow as, so `map.get("key")` works
1613    /// when `K` is `&str`. O(n) scan.
1614    pub fn get<Q>(&self, key: &Q) -> Option<&V>
1615    where
1616        K: core::borrow::Borrow<Q>,
1617        Q: PartialEq + ?Sized,
1618    {
1619        self.entries
1620            .iter()
1621            .rev()
1622            .find(|(k, _)| k.borrow() == key)
1623            .map(|(_, v)| v)
1624    }
1625
1626    /// Returns `true` if an entry with the given key exists.
1627    pub fn contains_key<Q>(&self, key: &Q) -> bool
1628    where
1629        K: core::borrow::Borrow<Q>,
1630        Q: PartialEq + ?Sized,
1631    {
1632        self.entries.iter().any(|(k, _)| k.borrow() == key)
1633    }
1634
1635    /// Iterate over key-value pairs with duplicate keys removed.
1636    ///
1637    /// Each distinct key is yielded **exactly once, at the position of its
1638    /// last wire occurrence, carrying that occurrence's value** — i.e.
1639    /// last-write-wins, mirroring the merge semantics that an owned
1640    /// `HashMap` decode applies. Callers that need first-occurrence position
1641    /// should use [`iter`](Self::iter) and filter themselves.
1642    ///
1643    /// Used by the generated view `Serialize` impl: a JSON object cannot
1644    /// hold duplicate keys, but `MapView` preserves all wire entries
1645    /// (including malformed duplicates), so the JSON encode path must
1646    /// deduplicate. The implementation is allocation-free and O(n²) — for
1647    /// each entry, scan the remaining entries for a later occurrence of the
1648    /// same key. Duplicate map keys are invalid per the protobuf encoding
1649    /// spec and only arise in adversarial or conformance-test wire data, so
1650    /// `n` is effectively always small.
1651    pub fn iter_unique(&self) -> impl Iterator<Item = &(K, V)>
1652    where
1653        K: PartialEq,
1654    {
1655        let entries = &self.entries;
1656        entries.iter().enumerate().filter_map(move |(i, entry)| {
1657            if entries[i + 1..]
1658                .iter()
1659                .any(|(later_k, _)| *later_k == entry.0)
1660            {
1661                None
1662            } else {
1663                Some(entry)
1664            }
1665        })
1666    }
1667
1668    /// Count of distinct keys (`iter_unique().count()`).
1669    pub fn len_unique(&self) -> usize
1670    where
1671        K: PartialEq,
1672    {
1673        self.iter_unique().count()
1674    }
1675}
1676
1677impl<'a, K, V> From<alloc::vec::Vec<(K, V)>> for MapView<'a, K, V> {
1678    fn from(entries: alloc::vec::Vec<(K, V)>) -> Self {
1679        Self::new(entries)
1680    }
1681}
1682
1683/// Duplicate keys are kept and all encoded; see [`MapView::new`].
1684impl<'a, K, V> FromIterator<(K, V)> for MapView<'a, K, V> {
1685    fn from_iter<I: IntoIterator<Item = (K, V)>>(iter: I) -> Self {
1686        Self::new(iter.into_iter().collect())
1687    }
1688}
1689
1690impl<'a, K, V> Default for MapView<'a, K, V> {
1691    fn default() -> Self {
1692        Self {
1693            entries: alloc::vec::Vec::new(),
1694            _marker: core::marker::PhantomData,
1695        }
1696    }
1697}
1698
1699impl<'b, 'a, K, V> IntoIterator for &'b MapView<'a, K, V> {
1700    type Item = &'b (K, V);
1701    type IntoIter = core::slice::Iter<'b, (K, V)>;
1702
1703    fn into_iter(self) -> Self::IntoIter {
1704        self.entries.iter()
1705    }
1706}
1707
1708impl<'a, K, V> IntoIterator for MapView<'a, K, V> {
1709    type Item = (K, V);
1710    type IntoIter = alloc::vec::IntoIter<(K, V)>;
1711
1712    fn into_iter(self) -> Self::IntoIter {
1713        self.entries.into_iter()
1714    }
1715}
1716
1717/// A borrowed view of unknown fields.
1718///
1719/// Stores raw byte slices from the input buffer rather than decoded values,
1720/// enabling zero-copy round-tripping of unknown fields. Each stored span
1721/// holds **one or more consecutive** complete `(tag, value)` records:
1722/// adjacent unknown fields are coalesced into a single span, so a long run
1723/// of unknown fields costs one `Vec` slot rather than one per field.
1724/// Coalescing bounds the view's memory only — the decode-time
1725/// unknown-field allowance is still charged per field (see
1726/// [`push_record`](Self::push_record)).
1727#[derive(Clone, Default)]
1728pub struct UnknownFieldsView<'a> {
1729    /// Raw byte spans from the input buffer, each one or more complete
1730    /// `(tag, value)` records.
1731    raw_spans: alloc::vec::Vec<&'a [u8]>,
1732    /// The input-buffer tail starting at the first byte of the last span,
1733    /// kept so [`push_record`](Self::push_record) can extend that span over
1734    /// an adjacent record by re-slicing `last_tail` — never by widening the
1735    /// narrowed span reference, which would be provenance-unsound.
1736    last_tail: Option<&'a [u8]>,
1737    /// Total slots charged against the decode-time unknown-field allowance
1738    /// across every [`push_record`](Self::push_record) — exactly the number
1739    /// of `UnknownField`s [`to_owned`](Self::to_owned) re-materializes, so
1740    /// replay runs under precisely this budget and cannot exhaust it.
1741    to_owned_budget: usize,
1742    /// Deepest group nesting across all pushed records — the recursion
1743    /// depth [`to_owned`](Self::to_owned)'s replay needs, regardless of the
1744    /// (possibly larger) recursion limit the view was decoded under.
1745    to_owned_depth: u32,
1746    /// Set by [`push_raw`](Self::push_raw): the view holds spans that were
1747    /// never charged at decode time, so [`to_owned`](Self::to_owned) grants
1748    /// the default limits on top of the tracked budget and can fail.
1749    manual_spans: bool,
1750}
1751
1752// Manual impl: `last_tail` is an internal coalescing cursor that extends to
1753// the end of the input buffer — deriving Debug would dump the remaining
1754// message bytes on every `{:?}` print.
1755impl core::fmt::Debug for UnknownFieldsView<'_> {
1756    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1757        f.debug_struct("UnknownFieldsView")
1758            .field("raw_spans", &self.raw_spans)
1759            .finish_non_exhaustive()
1760    }
1761}
1762
1763impl<'a> UnknownFieldsView<'a> {
1764    /// Creates an empty view.
1765    pub fn new() -> Self {
1766        Self::default()
1767    }
1768
1769    #[doc(hidden)]
1770    pub fn push_raw(&mut self, span: &'a [u8]) {
1771        self.raw_spans.push(span);
1772        // A manually pushed span has no known position in the input buffer,
1773        // so coalescing must not extend it — and it was never charged
1774        // against a decode allowance, so to_owned falls back to the default
1775        // limits for it.
1776        self.last_tail = None;
1777        self.manual_spans = true;
1778    }
1779
1780    /// Record one unknown wire record of `span_len` bytes starting at the
1781    /// head of `tail`, where `tail` extends from the record's first byte to
1782    /// the end of the input buffer.
1783    ///
1784    /// Every record charges `ctx`'s unknown-field allowance with exactly the
1785    /// slots [`to_owned`](Self::to_owned) will re-materialize it into — one
1786    /// for the record's field plus, for group records, one per nested field.
1787    /// The charge total (and the deepest group nesting) is accumulated on
1788    /// the view as the conversion replay budget, so a view that decoded
1789    /// successfully always converts.
1790    ///
1791    /// If the record starts exactly where the previous one ended, the
1792    /// previous span is extended in place instead of pushing a new one —
1793    /// coalescing saves memory (no allocation, no `Vec` slot), not
1794    /// allowance.
1795    ///
1796    /// # Errors
1797    ///
1798    /// Returns [`DecodeError::UnknownFieldLimitExceeded`] when the allowance
1799    /// is exhausted, or [`DecodeError::UnexpectedEof`] if `span_len` exceeds
1800    /// `tail`.
1801    #[doc(hidden)]
1802    pub fn push_record(
1803        &mut self,
1804        tail: &'a [u8],
1805        span_len: usize,
1806        ctx: crate::DecodeContext<'_>,
1807    ) -> Result<(), crate::DecodeError> {
1808        if span_len > tail.len() {
1809            return Err(crate::DecodeError::UnexpectedEof);
1810        }
1811        let charge = crate::encoding::register_unknown_record(&tail[..span_len], ctx)?;
1812        self.to_owned_budget = self.to_owned_budget.saturating_add(charge.fields);
1813        self.to_owned_depth = self.to_owned_depth.max(charge.depth);
1814        if let (Some(last), Some(prev_tail)) = (self.raw_spans.last_mut(), self.last_tail) {
1815            let prev_len = last.len();
1816            // Contiguous if the new record begins exactly one past the end
1817            // of the previous span. Both checks are plain pointer/length
1818            // comparisons; the extension below re-slices `prev_tail`, whose
1819            // provenance covers the combined range.
1820            if prev_tail.len() >= prev_len + span_len
1821                && core::ptr::eq(prev_tail[prev_len..].as_ptr(), tail.as_ptr())
1822            {
1823                *last = &prev_tail[..prev_len + span_len];
1824                return Ok(());
1825            }
1826        }
1827        self.raw_spans.push(&tail[..span_len]);
1828        self.last_tail = Some(tail);
1829        Ok(())
1830    }
1831
1832    /// Returns `true` if no unknown fields were recorded.
1833    pub fn is_empty(&self) -> bool {
1834        self.raw_spans.is_empty()
1835    }
1836
1837    /// Total byte length of all unknown field data.
1838    pub fn encoded_len(&self) -> usize {
1839        self.raw_spans.iter().map(|s| s.len()).sum()
1840    }
1841
1842    /// Write all unknown-field bytes verbatim. Each span holds one or more
1843    /// complete `(tag, value)` records as they appeared on the wire, so
1844    /// concatenating the spans produces a valid encoding.
1845    pub fn write_to(&self, buf: &mut impl BufMut) {
1846        for span in &self.raw_spans {
1847            buf.put_slice(span);
1848        }
1849    }
1850
1851    /// Convert to an owned [`UnknownFields`](crate::UnknownFields) by parsing all stored raw byte spans.
1852    ///
1853    /// Each span holds one or more consecutive (tag + value) records as they
1854    /// appeared on the wire. Parsing uses
1855    /// [`crate::encoding::decode_unknown_field`] under exactly the budget
1856    /// [`push_record`](Self::push_record) charged at decode time — the same
1857    /// field count and group-nesting depth — so replay cannot exhaust
1858    /// either. Views holding manually pushed spans (via
1859    /// [`push_raw`](Self::push_raw)) additionally get
1860    /// [`DEFAULT_UNKNOWN_FIELD_LIMIT`](crate::DEFAULT_UNKNOWN_FIELD_LIMIT)
1861    /// slots and the full [`RECURSION_LIMIT`](crate::RECURSION_LIMIT), since
1862    /// those spans were never charged.
1863    /// A coalesced span re-materializes one owned `UnknownField` per
1864    /// record, so this conversion is where a long run of unknown fields
1865    /// actually allocates.
1866    ///
1867    /// # Errors
1868    ///
1869    /// Returns `Err` if a stored span is malformed or exceeds the replay
1870    /// budget. Neither can occur when the view was produced by wire
1871    /// decoding — every span was parsed off the wire, and the budget equals
1872    /// what decoding charged — so any view that decoded successfully
1873    /// converts successfully. Only views holding
1874    /// [`push_raw`](Self::push_raw) spans can fail here.
1875    pub fn to_owned(&self) -> Result<crate::UnknownFields, crate::DecodeError> {
1876        use crate::encoding::{decode_unknown_field, Tag};
1877
1878        let (budget, depth) = if self.manual_spans {
1879            (
1880                self.to_owned_budget
1881                    .saturating_add(crate::DEFAULT_UNKNOWN_FIELD_LIMIT),
1882                self.to_owned_depth.max(crate::RECURSION_LIMIT),
1883            )
1884        } else {
1885            (self.to_owned_budget, self.to_owned_depth)
1886        };
1887        let limit = core::cell::Cell::new(budget);
1888        let ctx = crate::DecodeContext::new(depth, &limit);
1889        let mut out = crate::UnknownFields::new();
1890        for span in &self.raw_spans {
1891            let mut cur: &[u8] = span;
1892            while !cur.is_empty() {
1893                let tag = Tag::decode(&mut cur)?;
1894                let field = decode_unknown_field(tag, &mut cur, ctx)?;
1895                out.push(field);
1896            }
1897        }
1898        Ok(out)
1899    }
1900}
1901
1902/// An owned, `'static` container for a decoded message view.
1903///
1904/// `OwnedView` holds a [`Bytes`] buffer alongside the decoded view, ensuring
1905/// the view's borrows remain valid for the container's lifetime. The inner
1906/// view is reached through [`reborrow()`](OwnedView::reborrow), which returns
1907/// it with a lifetime tied to `&self`.
1908///
1909/// This type is `Send + Sync + 'static`, making it suitable for use across
1910/// async boundaries, in tower services, and anywhere a `'static` bound is
1911/// required.
1912///
1913/// # When to use
1914///
1915/// Use `OwnedView` when you need a zero-copy view that outlives the scope
1916/// where the buffer was received — for example, in an RPC handler where the
1917/// framework requires `'static` types:
1918///
1919/// ```rust,ignore
1920/// use buffa::view::OwnedView;
1921/// use bytes::Bytes;
1922///
1923/// let bytes: Bytes = receive_request_body().await;
1924/// let view = OwnedView::<PersonView>::decode(bytes)?;
1925///
1926/// // Field access through reborrow — the borrow is tied to `view`.
1927/// let person = view.reborrow();
1928/// println!("name: {}", person.name);
1929/// println!("id: {}", person.id);
1930///
1931/// // Convert to owned if you need to store or mutate
1932/// let owned: Person = view.to_owned_message()?;
1933/// ```
1934///
1935/// Generated code additionally provides a per-message `FooOwnedView` wrapper
1936/// around `OwnedView<FooView<'static>>` with per-field accessor methods
1937/// (`owned.name()`, `owned.id()`, …), so most handler code never touches
1938/// `OwnedView` or `reborrow` directly.
1939///
1940/// For scoped access where the buffer's lifetime is known, use
1941/// [`MessageView::decode_view`] directly — it has zero overhead beyond the
1942/// decode itself.
1943///
1944/// # Why field access goes through `reborrow`
1945///
1946/// `OwnedView` stores `V = FooView<'static>`: the view's borrows really point
1947/// into `self`'s [`Bytes`] buffer, and the `'static` is a synthetic lifetime
1948/// established by the constructor. Exposing `&V` directly (for example via a
1949/// `Deref` impl) would let borrowed fields *appear* `'static` to the
1950/// compiler and escape the `OwnedView`'s scope, dangling once it drops.
1951/// [`reborrow()`](OwnedView::reborrow) narrows the synthetic `'static` down
1952/// to the `OwnedView`'s real lifetime, so the borrow checker enforces the
1953/// actual validity of every field borrow:
1954///
1955/// ```no_run
1956/// # use buffa::view::OwnedView;
1957/// # use buffa::__doctest_fixtures::PersonView;
1958/// // Inline reads: reborrow once, then use plain field access.
1959/// fn log(owned: &OwnedView<PersonView<'static>>) {
1960///     let person = owned.reborrow();
1961///     println!("{}", person.name);
1962/// }
1963///
1964/// // Returning a borrowed field: the result is tied to the OwnedView.
1965/// fn name<'a>(owned: &'a OwnedView<PersonView<'static>>) -> &'a str {
1966///     owned.reborrow().name  // &'a str tied to the OwnedView's lifetime
1967/// }
1968/// ```
1969///
1970/// View fields are not reachable directly on the handle — this fails to
1971/// compile rather than handing out a `'static` borrow into the buffer:
1972///
1973/// ```compile_fail,E0609
1974/// # use buffa::view::OwnedView;
1975/// # use buffa::__doctest_fixtures::PersonView;
1976/// fn field(owned: &OwnedView<PersonView<'static>>) -> &'static str {
1977///     owned.name // error[E0609]: no field `name` on type `&OwnedView<...>`
1978/// }
1979/// ```
1980///
1981/// # Safety
1982///
1983/// Internally, `OwnedView` extends the view's lifetime to `'static` via
1984/// `transmute` in its constructors. This is sound because:
1985///
1986/// 1. [`Bytes`] is reference-counted — its heap data pointer is stable across
1987///    moves. The view's borrows always point into valid memory.
1988/// 2. [`Bytes`] is immutable — the underlying data cannot be modified while
1989///    borrowed.
1990/// 3. A manual [`Drop`] impl explicitly drops the view before the bytes,
1991///    ensuring no dangling references during cleanup. The view field uses
1992///    [`ManuallyDrop`](core::mem::ManuallyDrop) to prevent the automatic
1993///    drop from running out of order.
1994///
1995/// [`reborrow`](OwnedView::reborrow) is a plain Rust subtype coercion (no
1996/// `unsafe`, no pointer cast): the [`ViewReborrow`] trait method coerces
1997/// `&'b FooView<'static>` into `&'b FooView<'b>` via standard lifetime
1998/// variance for covariant view types. See [`ViewReborrow`]'s docs for the
1999/// soundness argument.
2000pub struct OwnedView<V> {
2001    // INVARIANT: `view` borrows from `bytes`. The `Drop` impl ensures
2002    // `view` is dropped before `bytes`. `ManuallyDrop` prevents the compiler
2003    // from dropping `view` automatically — our `Drop` impl handles it.
2004    //
2005    // CONSTRUCTORS: any constructor added here MUST ensure the view's
2006    // borrows point into `self.bytes` (not into caller-owned memory).
2007    // The auto-`Send`/`Sync` derivation is only sound under that invariant
2008    // — there is no longer a `V: 'static` bound on `Send` to act as a
2009    // second gate. See the comment block above `send_sync_assertions` below.
2010    view: core::mem::ManuallyDrop<V>,
2011    bytes: Bytes,
2012}
2013
2014impl<V> Drop for OwnedView<V> {
2015    fn drop(&mut self) {
2016        // SAFETY: `view` borrows from `bytes`. We must drop the view before
2017        // bytes is dropped. `ManuallyDrop::drop` runs V's destructor in place
2018        // without moving it. After this, `bytes` drops automatically via the
2019        // compiler-generated drop glue.
2020        unsafe {
2021            core::mem::ManuallyDrop::drop(&mut self.view);
2022        }
2023    }
2024}
2025
2026impl<V> OwnedView<V>
2027where
2028    V: MessageView<'static>,
2029{
2030    /// Decode a view from a [`Bytes`] buffer.
2031    ///
2032    /// The view borrows directly from the buffer's data. Because [`Bytes`] is
2033    /// reference-counted and its data pointer is stable across moves, the
2034    /// view's borrows remain valid for the lifetime of this `OwnedView`.
2035    ///
2036    /// # Errors
2037    ///
2038    /// Returns [`DecodeError`] if the buffer contains invalid protobuf data.
2039    pub fn decode(bytes: Bytes) -> Result<Self, DecodeError> {
2040        // SAFETY: `Bytes` is StableDeref — its heap data never moves or is
2041        // freed while we hold the `Bytes` value. We hold it in `self.bytes`,
2042        // and drop order guarantees `view` drops first.
2043        let view = unsafe {
2044            let slice: &'static [u8] = core::mem::transmute::<&[u8], &'static [u8]>(&bytes);
2045            V::decode_view(slice)?
2046        };
2047        Ok(Self {
2048            view: core::mem::ManuallyDrop::new(view),
2049            bytes,
2050        })
2051    }
2052
2053    /// Decode a view with custom [`DecodeOptions`](crate::DecodeOptions)
2054    /// (recursion limit, max message size).
2055    ///
2056    /// # Errors
2057    ///
2058    /// Returns [`DecodeError`] if the buffer is invalid or exceeds the
2059    /// configured limits.
2060    pub fn decode_with_options(
2061        bytes: Bytes,
2062        opts: &crate::DecodeOptions,
2063    ) -> Result<Self, DecodeError> {
2064        // SAFETY: Same invariants as `decode` — see above.
2065        let view = unsafe {
2066            let slice: &'static [u8] = core::mem::transmute::<&[u8], &'static [u8]>(&bytes);
2067            opts.decode_view::<V>(slice)?
2068        };
2069        Ok(Self {
2070            view: core::mem::ManuallyDrop::new(view),
2071            bytes,
2072        })
2073    }
2074
2075    /// Create an `OwnedView` from an owned message by encoding then decoding.
2076    ///
2077    /// This performs a full **encode → decode** round-trip: the message is
2078    /// serialized to protobuf bytes, then a zero-copy view is decoded from
2079    /// those bytes. This is useful when the original wire bytes are not
2080    /// available (e.g., after JSON deserialization or programmatic construction),
2081    /// but note the cost: one allocation + O(n) encode + O(n) decode.
2082    ///
2083    /// For the common case where you already have wire bytes, prefer
2084    /// [`decode`](Self::decode) instead.
2085    ///
2086    /// # Errors
2087    ///
2088    /// Returns [`DecodeError`] if the re-encoded bytes are somehow invalid
2089    /// (should not happen for well-formed messages).
2090    pub fn from_owned(msg: &V::Owned) -> Result<Self, DecodeError> {
2091        let bytes = Bytes::from(msg.encode_to_vec());
2092        Self::decode(bytes)
2093    }
2094
2095    /// Convert the view to the corresponding owned message type.
2096    ///
2097    /// `bytes::Bytes`-typed fields are produced via [`Bytes::slice_ref`]
2098    /// into the retained buffer (zero-copy); other borrowed fields are
2099    /// allocated and copied.
2100    ///
2101    /// # Errors
2102    ///
2103    /// Returns an error if re-materializing preserved unknown fields fails
2104    /// (see [`MessageView::to_owned_message`]).
2105    pub fn to_owned_message(&self) -> Result<V::Owned, DecodeError> {
2106        self.view.to_owned_from_source(Some(&self.bytes))
2107    }
2108
2109    /// Get a reference to the underlying bytes buffer.
2110    pub fn bytes(&self) -> &Bytes {
2111        &self.bytes
2112    }
2113
2114    /// Create an `OwnedView` from a buffer and a pre-decoded view.
2115    ///
2116    /// This avoids re-decoding when you already hold a decoded view and want
2117    /// to wrap it for `'static` use.
2118    ///
2119    /// # Safety
2120    ///
2121    /// The caller must ensure that **all** borrows in `view` point into the
2122    /// data region of `bytes`. In practice, `view` must have been decoded
2123    /// from `bytes` (or a sub-slice that `bytes` fully contains). Violating
2124    /// this invariant causes undefined behavior (dangling references).
2125    pub unsafe fn from_parts(bytes: Bytes, view: V) -> Self {
2126        Self {
2127            view: core::mem::ManuallyDrop::new(view),
2128            bytes,
2129        }
2130    }
2131
2132    /// Consume the `OwnedView`, returning the underlying [`Bytes`] buffer.
2133    ///
2134    /// The view is dropped before the buffer is returned.
2135    pub fn into_bytes(mut self) -> Bytes {
2136        // SAFETY: Drop the view first (while bytes data is still alive),
2137        // then read bytes out via ptr::read, then forget self to prevent
2138        // the Drop impl from double-dropping the view.
2139        unsafe {
2140            core::mem::ManuallyDrop::drop(&mut self.view);
2141            let bytes = core::ptr::read(&self.bytes);
2142            core::mem::forget(self);
2143            bytes
2144        }
2145    }
2146
2147    /// Reborrow the view with a lifetime tied to `&'b self`.
2148    ///
2149    /// `OwnedView<V>` stores `V` with a `'static` lifetime — the actual borrows
2150    /// point into `self`'s internal [`Bytes`] buffer and are only valid while
2151    /// `self` is alive. `reborrow` makes that real lifetime visible to the borrow
2152    /// checker: the returned `&'b V::Reborrowed<'b>` cannot outlive `&'b self`.
2153    ///
2154    /// # Example
2155    ///
2156    /// ```no_run
2157    /// # use buffa::view::OwnedView;
2158    /// # use buffa::__doctest_fixtures::PersonView;
2159    /// fn handler<'a>(req: &'a OwnedView<PersonView<'static>>) -> &'a str {
2160    ///     // The explicit annotation is for emphasis; inference works without it.
2161    ///     // If you need to name the lifetime, store the reborrow in a `let` first.
2162    ///     let req_view: &PersonView<'a> = req.reborrow();
2163    ///     req_view.name  // zero-copy from the OwnedView's buffer
2164    /// }
2165    /// ```
2166    ///
2167    /// The returned reference is tied to `&'b self` — the borrow checker
2168    /// prevents the reborrowed view from outliving the `OwnedView`:
2169    ///
2170    /// ```compile_fail,E0597
2171    /// # use buffa::view::OwnedView;
2172    /// # use buffa::__doctest_fixtures::PersonView;
2173    /// let name: &str;
2174    /// {
2175    ///     // SAFETY: empty Bytes, no borrows — safe to construct directly.
2176    ///     let owned = unsafe {
2177    ///         OwnedView::<PersonView<'static>>::from_parts(
2178    ///             ::buffa::bytes::Bytes::new(),
2179    ///             PersonView::default(),
2180    ///         )
2181    ///     };
2182    ///     name = owned.reborrow().name; // error[E0597]: `owned` does not live long enough
2183    /// }
2184    /// println!("{name}"); // name is dangling — borrow checker rejects this
2185    /// ```
2186    ///
2187    /// # How it works
2188    ///
2189    /// The trait method [`ViewReborrow::reborrow`] is a plain Rust subtype
2190    /// coercion: `&'b V` (where `V = FooView<'static>`) flows into the
2191    /// return slot `&'b V::Reborrowed<'b>` (= `&'b FooView<'b>`). Variance
2192    /// makes this safe — covariant view types narrow `'static` down to
2193    /// `'b` automatically. No `unsafe`, no pointer cast, no layout
2194    /// assertions. `OwnedView`'s own invariant (every borrow in `view`
2195    /// points into `self.bytes`, established by `decode` or upheld by the
2196    /// `unsafe from_parts` caller) guarantees the pointed-to data lives
2197    /// at least as long as `'b`.
2198    #[must_use = "reborrow returns a tied-lifetime view; discarding it is a no-op"]
2199    pub fn reborrow<'b>(&'b self) -> &'b V::Reborrowed<'b>
2200    where
2201        V: ViewReborrow,
2202    {
2203        V::reborrow(&self.view)
2204    }
2205}
2206
2207// Deliberately NO `Deref<Target = V>` impl: `V` is `FooView<'static>`, so a
2208// `&V` return would expose the synthetic `'static` on every borrowed field
2209// and let it escape the OwnedView's scope (dangling once the buffer drops).
2210// All access goes through `reborrow()`, which ties the borrow to `&self`.
2211
2212impl<V> core::fmt::Debug for OwnedView<V>
2213where
2214    V: core::fmt::Debug,
2215{
2216    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
2217        (*self.view).fmt(f)
2218    }
2219}
2220
2221impl<V> Clone for OwnedView<V>
2222where
2223    V: Clone,
2224{
2225    fn clone(&self) -> Self {
2226        // SAFETY: `Bytes::clone()` is a refcount bump — both the original and
2227        // the clone share the same backing heap allocation. The cloned view's
2228        // `'static` references remain valid because they point into data that
2229        // is now kept alive by the cloned `Bytes` handle. This would be
2230        // unsound if `Bytes::clone()` performed a deep copy to a new address.
2231        Self {
2232            view: self.view.clone(),
2233            bytes: self.bytes.clone(),
2234        }
2235    }
2236}
2237
2238impl<V> PartialEq for OwnedView<V>
2239where
2240    V: PartialEq,
2241{
2242    fn eq(&self, other: &Self) -> bool {
2243        *self.view == *other.view
2244    }
2245}
2246
2247impl<V> Eq for OwnedView<V> where V: Eq {}
2248
2249/// Serialize an `OwnedView<V>` by delegating to the inner view's `Serialize`
2250/// impl.
2251///
2252/// Equivalent to serializing `owned_view.reborrow()` directly, so
2253/// `serde_json::to_string(&owned_view)` works on the handle itself. When
2254/// `V` is a buffa-generated view with `generate_json` enabled, this produces
2255/// protobuf JSON; the impl itself just forwards to whatever `V::serialize`
2256/// does.
2257///
2258/// Only available when the `json` feature is enabled.
2259#[cfg(feature = "json")]
2260impl<V: ::serde::Serialize> ::serde::Serialize for OwnedView<V> {
2261    fn serialize<S: ::serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
2262        ::serde::Serialize::serialize(&*self.view, s)
2263    }
2264}
2265
2266// `OwnedView<V>` is auto-`Send`/`Sync` when `V` is — `ManuallyDrop<V>` and
2267// `Bytes` both forward auto-traits. No manual `unsafe impl` is needed, and
2268// adding one with a `V: 'static` bound is actively harmful: it is precisely
2269// what triggers E0477 when `async fn` is used in a trait impl against an
2270// RPITIT `+ Send` return type (rust-lang/rust#128095). The RPITIT desugaring
2271// introduces a fresh lifetime for the `'static` in `FooView<'static>`, and
2272// then cannot prove that fresh lifetime satisfies `'static` to discharge the
2273// manual impl's bound.
2274//
2275// The bound was defensive — intended to prevent `OwnedView<FooView<'short>>`
2276// from being `Send` when the view borrows from something outside `self.bytes`.
2277// But that type is already unconstructible: `::decode()` and
2278// `::decode_with_options()` are gated on `V: MessageView<'static>`, and the
2279// fields are private. The short-lifetime case the bound guards against cannot
2280// exist in safe code.
2281//
2282// Auto-trait soundness: `Bytes` is `Send + Sync`. The view's `&'static [u8]`
2283// borrows point into `Bytes`'s heap allocation, which is immutable,
2284// `StableDeref`, and moves with the struct. Sending the whole pair to another
2285// thread preserves the invariant. The `'static` in `V` being a lie is about
2286// *where* the reference points, not about thread safety.
2287#[cfg(test)]
2288mod send_sync_assertions {
2289    use super::*;
2290    fn assert_send<T: Send>() {}
2291    fn assert_sync<T: Sync>() {}
2292
2293    // Any `V: Send + Sync` suffices — generated `FooView<'static>` types are
2294    // auto-`Send + Sync` via their `&'static str` / `&'static [u8]` fields.
2295    #[allow(dead_code)]
2296    fn owned_view_is_send_sync<V: Send + Sync>() {
2297        assert_send::<OwnedView<V>>();
2298        assert_sync::<OwnedView<V>>();
2299    }
2300
2301    // Concrete-type regression: `TinyView` is declared in the `tests` module
2302    // below and has the same shape as generated view types (one `&'a str`).
2303    #[allow(dead_code)]
2304    fn owned_tiny_view_is_send_sync() {
2305        assert_send::<OwnedView<super::tests::TinyView<'static>>>();
2306        assert_sync::<OwnedView<super::tests::TinyView<'static>>>();
2307    }
2308
2309    // `ViewReborrow::Reborrowed<'b>` must also be Send + Sync so that a
2310    // reborrowed view can be passed across threads (e.g. into a Tokio task).
2311    #[allow(dead_code)]
2312    fn reborrowed_view_is_send_sync<V>()
2313    where
2314        V: ViewReborrow + Send + Sync,
2315        for<'b> V::Reborrowed<'b>: Send + Sync,
2316    {
2317        assert_send::<OwnedView<V>>();
2318        assert_sync::<OwnedView<V>>();
2319    }
2320}
2321
2322#[cfg(test)]
2323mod tests {
2324    use super::*;
2325
2326    // ── MessageFieldView ─────────────────────────────────────────────────
2327
2328    #[test]
2329    fn message_field_view_default_is_unset() {
2330        let v: MessageFieldView<i32> = MessageFieldView::default();
2331        assert!(v.is_unset());
2332        assert!(!v.is_set());
2333        assert_eq!(v.as_option(), None);
2334    }
2335
2336    #[test]
2337    fn message_field_view_set_value() {
2338        let v = MessageFieldView::set(42);
2339        assert!(v.is_set());
2340        assert!(!v.is_unset());
2341        assert_eq!(v.as_option(), Some(&42));
2342    }
2343
2344    #[test]
2345    fn message_field_view_with_non_copy_type() {
2346        let v = MessageFieldView::set(alloc::string::String::from("hello"));
2347        assert!(v.is_set());
2348        assert_eq!(v.as_option().map(|s| s.as_str()), Some("hello"));
2349
2350        let unset: MessageFieldView<alloc::string::String> = MessageFieldView::unset();
2351        assert!(unset.is_unset());
2352        assert_eq!(unset.as_option(), None);
2353    }
2354
2355    // ── MessageFieldView Deref ─────────────────────────────────────────
2356
2357    /// A trivial view type for testing MessageFieldView Deref.
2358    #[derive(Clone, Debug, Default, PartialEq)]
2359    pub(super) struct TinyView<'a> {
2360        pub value: &'a str,
2361    }
2362
2363    // Via the exported macro, which doubles as its unit test (hygiene and
2364    // `$crate` path resolution).
2365    crate::impl_default_view_instance!(TinyView);
2366
2367    #[test]
2368    fn impl_default_view_instance_macro_returns_singleton() {
2369        let a: &TinyView<'_> = TinyView::default_view_instance();
2370        let b: &TinyView<'_> = TinyView::default_view_instance();
2371        assert!(core::ptr::eq(a, b), "singleton must be a single allocation");
2372        assert_eq!(a, &TinyView::default());
2373    }
2374
2375    #[test]
2376    fn message_field_view_deref_set() {
2377        let v = MessageFieldView::set(TinyView { value: "hello" });
2378        // Deref gives access to the inner view
2379        assert_eq!(v.value, "hello");
2380    }
2381
2382    #[test]
2383    fn message_field_view_deref_unset_returns_default() {
2384        let v: MessageFieldView<TinyView<'_>> = MessageFieldView::unset();
2385        // Deref transparently returns the default instance
2386        assert_eq!(v.value, "");
2387    }
2388
2389    #[test]
2390    fn message_field_view_deref_chained_access() {
2391        // Simulates accessing a nested field through an unset sub-message
2392        let v: MessageFieldView<TinyView<'_>> = MessageFieldView::unset();
2393        let len = v.value.len();
2394        assert_eq!(len, 0);
2395    }
2396
2397    // ── MessageFieldView PartialEq (wire-equivalent) ───────────────────
2398
2399    #[test]
2400    fn message_field_view_equality() {
2401        // None = Unset, Some(s) = Set(TinyView { value: s }).
2402        // TinyView::default() has value == "", so Some("") encodes Set(default).
2403        fn mk(c: Option<&str>) -> MessageFieldView<TinyView<'_>> {
2404            match c {
2405                None => MessageFieldView::unset(),
2406                Some(v) => MessageFieldView::set(TinyView { value: v }),
2407            }
2408        }
2409
2410        #[rustfmt::skip]
2411        let cases: &[(Option<&str>, Option<&str>, bool)] = &[
2412            // Wire-equivalent semantics: Unset == Set(default), matching
2413            // MessageField::PartialEq on the owned side.
2414            (None,      None,        true ),  // Unset == Unset
2415            (None,      Some(""),    true ),  // Unset == Set(default)
2416            (Some(""),  None,        true ),  // Set(default) == Unset (symmetric)
2417            (Some(""),  Some(""),    true ),  // Set(default) == Set(default)
2418            (None,      Some("x"),   false),  // Unset != Set(nondefault)
2419            (Some("x"), None,        false),  // Set(nondefault) != Unset (symmetric)
2420            (Some("x"), Some("x"),   true ),  // Set == Set (same)
2421            (Some("x"), Some("y"),   false),  // Set != Set (different)
2422        ];
2423
2424        for &(l, r, expect) in cases {
2425            assert_eq!(
2426                mk(l) == mk(r),
2427                expect,
2428                "({l:?} == {r:?}) should be {expect}"
2429            );
2430        }
2431    }
2432
2433    // ── RepeatedView ─────────────────────────────────────────────────────
2434
2435    #[test]
2436    fn repeated_view_new_and_accessors() {
2437        let rv = RepeatedView::new(alloc::vec![10, 20, 30]);
2438        assert_eq!(rv.len(), 3);
2439        assert!(!rv.is_empty());
2440        assert_eq!(&*rv, &[10, 20, 30]);
2441    }
2442
2443    #[test]
2444    fn repeated_view_default_is_empty() {
2445        let rv: RepeatedView<'_, u8> = RepeatedView::default();
2446        assert!(rv.is_empty());
2447        assert_eq!(rv.len(), 0);
2448    }
2449
2450    #[test]
2451    fn repeated_view_push_and_iter() {
2452        let mut rv = RepeatedView::<i32>::default();
2453        rv.push(1);
2454        rv.push(2);
2455        let collected: alloc::vec::Vec<_> = rv.iter().copied().collect();
2456        assert_eq!(collected, alloc::vec![1, 2]);
2457    }
2458
2459    // ── UnknownFieldsView::push_record (coalescing + limit) ────────────
2460
2461    /// A test context at full depth with `n` unknown-field slots, leaking
2462    /// the cell so the context can outlive this helper.
2463    fn record_ctx(n: usize) -> crate::DecodeContext<'static> {
2464        let limit = alloc::boxed::Box::leak(alloc::boxed::Box::new(core::cell::Cell::new(n)));
2465        crate::DecodeContext::new(crate::RECURSION_LIMIT, limit)
2466    }
2467
2468    #[test]
2469    fn push_record_coalesces_adjacent_records() {
2470        // Buffer holds three consecutive 2-byte records: they coalesce into
2471        // a single span, but each still consumes one allowance slot.
2472        let buf: &[u8] = &[0x08, 0x00, 0x08, 0x01, 0x08, 0x02];
2473        let ctx = record_ctx(3);
2474        let mut ufv = UnknownFieldsView::new();
2475        ufv.push_record(&buf[0..], 2, ctx).unwrap();
2476        ufv.push_record(&buf[2..], 2, ctx).unwrap();
2477        ufv.push_record(&buf[4..], 2, ctx).unwrap();
2478        assert_eq!(ufv.encoded_len(), 6);
2479        assert_eq!(ufv.raw_spans.len(), 1, "coalesced into one span");
2480        let mut out = alloc::vec::Vec::new();
2481        ufv.write_to(&mut out);
2482        assert_eq!(out, buf);
2483        assert_eq!(ctx.remaining_unknown_fields(), 0, "one slot per record");
2484    }
2485
2486    #[test]
2487    fn push_record_non_adjacent_records_use_separate_slots() {
2488        let buf: &[u8] = &[0x08, 0x00, 0xFF, 0x08, 0x01];
2489        let ctx = record_ctx(2);
2490        let mut ufv = UnknownFieldsView::new();
2491        ufv.push_record(&buf[0..], 2, ctx).unwrap();
2492        // Skip buf[2] — the next record is not adjacent to the previous one.
2493        ufv.push_record(&buf[3..], 2, ctx).unwrap();
2494        assert_eq!(ufv.encoded_len(), 4);
2495        assert_eq!(ctx.remaining_unknown_fields(), 0, "two slots consumed");
2496    }
2497
2498    #[test]
2499    fn push_record_enforces_limit_per_record() {
2500        // Before the per-record accounting fix, a coalesced run consumed
2501        // one slot at decode and one slot per record at conversion, so an
2502        // over-limit contiguous run decoded as a view and then failed to
2503        // convert. Now it fails at push time.
2504        let buf: &[u8] = &[0x08, 0x00, 0x08, 0x01, 0x08, 0x02];
2505        let ctx = record_ctx(1);
2506        let mut ufv = UnknownFieldsView::new();
2507        ufv.push_record(&buf[0..], 2, ctx).unwrap();
2508        // Non-adjacent record (the one at buf[2..4] was skipped): new span.
2509        assert_eq!(
2510            ufv.push_record(&buf[4..], 2, ctx),
2511            Err(crate::DecodeError::UnknownFieldLimitExceeded)
2512        );
2513        // Coalescing saves a span slot, not allowance: at zero remaining
2514        // even an adjacent record is rejected, keeping the decode-time
2515        // count equal to the count to_owned re-materializes.
2516        assert_eq!(
2517            ufv.push_record(&buf[2..], 2, ctx),
2518            Err(crate::DecodeError::UnknownFieldLimitExceeded)
2519        );
2520    }
2521
2522    #[test]
2523    fn push_record_charges_group_records_per_nested_field() {
2524        // One group record (field 1) holding two nested varint fields:
2525        // to_owned materializes three UnknownFields (group + 2 nested), so
2526        // decode must charge three slots.
2527        let buf: &[u8] = &[0x0b, 0x08, 0x00, 0x08, 0x01, 0x0c];
2528        let ctx = record_ctx(2);
2529        let mut ufv = UnknownFieldsView::new();
2530        assert_eq!(
2531            ufv.push_record(buf, buf.len(), ctx),
2532            Err(crate::DecodeError::UnknownFieldLimitExceeded)
2533        );
2534
2535        let ctx = record_ctx(3);
2536        let mut ufv = UnknownFieldsView::new();
2537        ufv.push_record(buf, buf.len(), ctx).unwrap();
2538        assert_eq!(ctx.remaining_unknown_fields(), 0, "group + 2 nested");
2539        let owned = ufv.to_owned().expect("decode allowance covers replay");
2540        assert_eq!(owned.iter().count(), 1, "one top-level group field");
2541    }
2542
2543    #[test]
2544    fn push_record_charges_nested_groups_recursively() {
2545        // group 1 { varint; group 2 { varint } } — four materializable
2546        // fields, so four slots.
2547        let buf: &[u8] = &[0x0b, 0x08, 0x00, 0x13, 0x08, 0x01, 0x14, 0x0c];
2548        let ctx = record_ctx(3);
2549        let mut ufv = UnknownFieldsView::new();
2550        assert_eq!(
2551            ufv.push_record(buf, buf.len(), ctx),
2552            Err(crate::DecodeError::UnknownFieldLimitExceeded)
2553        );
2554
2555        let ctx = record_ctx(4);
2556        let mut ufv = UnknownFieldsView::new();
2557        ufv.push_record(buf, buf.len(), ctx).unwrap();
2558        assert_eq!(ctx.remaining_unknown_fields(), 0);
2559        ufv.to_owned().expect("decode allowance covers replay");
2560    }
2561
2562    #[test]
2563    fn push_raw_disables_coalescing_for_next_record() {
2564        let buf: &[u8] = &[0x08, 0x00, 0x08, 0x01];
2565        let ctx = record_ctx(2);
2566        let mut ufv = UnknownFieldsView::new();
2567        ufv.push_raw(&buf[0..2]);
2568        // Adjacent on the wire, but push_raw cleared the tail, so this must
2569        // open a fresh span (a manual span has no trusted buffer position).
2570        ufv.push_record(&buf[2..], 2, ctx).unwrap();
2571        assert_eq!(ctx.remaining_unknown_fields(), 1);
2572        assert_eq!(ufv.encoded_len(), 4);
2573    }
2574
2575    #[test]
2576    fn push_record_rejects_span_past_tail_end() {
2577        let buf: &[u8] = &[0x08, 0x00];
2578        let ctx = record_ctx(1);
2579        let mut ufv = UnknownFieldsView::new();
2580        assert_eq!(
2581            ufv.push_record(buf, 3, ctx),
2582            Err(crate::DecodeError::UnexpectedEof)
2583        );
2584    }
2585
2586    #[test]
2587    fn coalesced_span_to_owned_parses_every_record() {
2588        let buf: &[u8] = &[0x08, 0x00, 0x08, 0x01, 0x08, 0x02];
2589        let ctx = record_ctx(3);
2590        let mut ufv = UnknownFieldsView::new();
2591        for i in 0..3 {
2592            ufv.push_record(&buf[2 * i..], 2, ctx).unwrap();
2593        }
2594        let owned = ufv.to_owned().unwrap();
2595        assert_eq!(owned.iter().count(), 3, "all records parsed");
2596    }
2597
2598    #[test]
2599    fn decode_time_allowance_always_covers_to_owned() {
2600        // The invariant push_record's accounting exists for: any run that
2601        // decodes within the allowance converts within the captured
2602        // allowance. Here the record count exactly exhausts the limit and
2603        // the run coalesces into one span.
2604        let buf: &[u8] = &[0x08, 0x00, 0x08, 0x01, 0x08, 0x02];
2605        let ctx = record_ctx(3);
2606        let mut ufv = UnknownFieldsView::new();
2607        for i in 0..3 {
2608            ufv.push_record(&buf[2 * i..], 2, ctx).unwrap();
2609        }
2610        assert_eq!(ufv.raw_spans.len(), 1, "coalesced into one span");
2611        assert_eq!(ctx.remaining_unknown_fields(), 0, "limit exactly used");
2612        let owned = ufv.to_owned().expect("decode succeeded, so convert must");
2613        assert_eq!(owned.iter().count(), 3);
2614    }
2615
2616    #[test]
2617    fn to_owned_of_manual_view_uses_default_allowance() {
2618        // push_raw spans are never charged at decode time; to_owned grants
2619        // the default limit for them.
2620        let mut ufv = UnknownFieldsView::new();
2621        ufv.push_raw(&[0x08, 0x00]);
2622        let owned = ufv.to_owned().unwrap();
2623        assert_eq!(owned.iter().count(), 1);
2624    }
2625
2626    #[test]
2627    fn to_owned_covers_records_pushed_under_different_contexts() {
2628        // The replay budget is the accumulated charge total, not a snapshot
2629        // of any single context's remaining allowance — so a view merged
2630        // across decode passes with unrelated contexts still converts.
2631        let buf: &[u8] = &[0x08, 0x00, 0x08, 0x01, 0x08, 0x02];
2632        let mut ufv = UnknownFieldsView::new();
2633        let tight = record_ctx(1);
2634        ufv.push_record(&buf[0..], 2, tight).unwrap();
2635        let fresh = record_ctx(2);
2636        ufv.push_record(&buf[2..], 2, fresh).unwrap();
2637        ufv.push_record(&buf[4..], 2, fresh).unwrap();
2638        let owned = ufv.to_owned().expect("every push succeeded");
2639        assert_eq!(owned.iter().count(), 3);
2640    }
2641
2642    #[test]
2643    fn to_owned_replays_deep_groups_decoded_under_raised_recursion_limit() {
2644        // Replay depth comes from the nesting tracked at decode time, not
2645        // the fixed RECURSION_LIMIT — a group nested deeper than the
2646        // default (decodable only under a raised recursion limit) must
2647        // still convert.
2648        let deep = crate::RECURSION_LIMIT as usize + 20;
2649        let mut buf = alloc::vec![0x0bu8; deep]; // StartGroup ×deep
2650        buf.resize(2 * deep, 0x0c); // EndGroup ×deep
2651        let ctx = record_ctx(deep);
2652        let mut ufv = UnknownFieldsView::new();
2653        ufv.push_record(&buf, buf.len(), ctx).unwrap();
2654        assert_eq!(ctx.remaining_unknown_fields(), 0, "one slot per group");
2655        ufv.to_owned().expect("decode succeeded, so convert must");
2656    }
2657
2658    #[test]
2659    fn to_owned_of_malformed_manual_span_fails() {
2660        // The replay error path stays live for manually built views: a
2661        // push_raw span that is not a complete record fails to parse.
2662        let mut ufv = UnknownFieldsView::new();
2663        ufv.push_raw(&[0xFF]);
2664        assert!(ufv.to_owned().is_err());
2665    }
2666
2667    #[test]
2668    fn to_owned_of_manual_flood_over_default_limit_fails() {
2669        // The replay limit stays live for manually built views: push_raw
2670        // spans get the default allowance, no more — the memory-
2671        // amplification bound survives even though wire-decoded views can
2672        // no longer hit it.
2673        let n = crate::DEFAULT_UNKNOWN_FIELD_LIMIT + 1;
2674        let mut buf = alloc::vec::Vec::with_capacity(2 * n);
2675        for _ in 0..n {
2676            buf.extend_from_slice(&[0x08, 0x00]);
2677        }
2678        let mut ufv = UnknownFieldsView::new();
2679        ufv.push_raw(&buf);
2680        assert_eq!(
2681            ufv.to_owned(),
2682            Err(crate::DecodeError::UnknownFieldLimitExceeded)
2683        );
2684    }
2685
2686    #[test]
2687    fn repeated_view_reserve_grows_capacity() {
2688        let mut rv = RepeatedView::<u32>::default();
2689        rv.reserve(64);
2690        assert!(rv.elements.capacity() >= 64);
2691        // Reserve must not produce visible elements.
2692        assert!(rv.is_empty());
2693        // reserve(0) is a no-op and must not panic.
2694        rv.reserve(0);
2695        // Reserve after pushes adds capacity above current len.
2696        rv.push(1);
2697        rv.push(2);
2698        rv.reserve(100);
2699        assert_eq!(rv.len(), 2);
2700        assert!(rv.elements.capacity() >= 102);
2701        // Subsequent reserve calls must not corrupt the existing elements.
2702        let collected: alloc::vec::Vec<_> = rv.iter().copied().collect();
2703        assert_eq!(collected, alloc::vec![1, 2]);
2704    }
2705
2706    #[test]
2707    fn repeated_view_with_borrowed_str() {
2708        let data = alloc::string::String::from("hello world");
2709        let parts: alloc::vec::Vec<&str> = data.split_whitespace().collect();
2710        let rv = RepeatedView::new(parts);
2711        assert_eq!(rv.len(), 2);
2712        assert_eq!(rv[0], "hello");
2713        assert_eq!(rv[1], "world");
2714    }
2715
2716    #[test]
2717    fn repeated_view_into_iter_by_ref() {
2718        let rv = RepeatedView::new(alloc::vec![1, 2, 3]);
2719        let sum: i32 = (&rv).into_iter().sum();
2720        assert_eq!(sum, 6);
2721        // `for x in &rv` syntax works:
2722        let mut count = 0;
2723        for _ in &rv {
2724            count += 1;
2725        }
2726        assert_eq!(count, 3);
2727    }
2728
2729    #[test]
2730    fn repeated_view_into_iter_by_value() {
2731        let rv = RepeatedView::new(alloc::vec![
2732            alloc::string::String::from("a"),
2733            alloc::string::String::from("b"),
2734        ]);
2735        let collected: alloc::vec::Vec<_> = rv.into_iter().collect();
2736        assert_eq!(collected, alloc::vec!["a".to_string(), "b".to_string()]);
2737    }
2738
2739    // ── MapView ──────────────────────────────────────────────────────────
2740
2741    #[test]
2742    fn map_view_get_with_borrow() {
2743        let mut mv = MapView::<&str, i32>::default();
2744        mv.push("apples", 3);
2745        mv.push("bananas", 5);
2746
2747        // Ergonomic: get("key") works via Borrow<str> on &str
2748        assert_eq!(mv.get("apples"), Some(&3));
2749        assert_eq!(mv.get("bananas"), Some(&5));
2750        assert_eq!(mv.get("oranges"), None);
2751
2752        // Old style still works
2753        assert_eq!(mv.get(&"apples"), Some(&3));
2754    }
2755
2756    #[test]
2757    fn map_view_contains_key_with_borrow() {
2758        let mut mv = MapView::<&str, i32>::default();
2759        mv.push("key", 1);
2760
2761        assert!(mv.contains_key("key"));
2762        assert!(!mv.contains_key("missing"));
2763    }
2764
2765    #[test]
2766    fn map_view_get_last_write_wins() {
2767        let mut mv = MapView::<&str, i32>::default();
2768        mv.push("x", 1);
2769        mv.push("x", 2);
2770        assert_eq!(mv.get("x"), Some(&2));
2771    }
2772
2773    #[test]
2774    fn map_view_iter_unique_dedups_last_write_wins() {
2775        let mut mv = MapView::<&str, i32>::default();
2776        mv.push("a", 1);
2777        mv.push("b", 2);
2778        mv.push("a", 3); // duplicate key — only this entry survives for "a"
2779        mv.push("c", 4);
2780        mv.push("b", 5); // duplicate key — only this entry survives for "b"
2781
2782        assert_eq!(mv.len(), 5, "iter() preserves all wire entries");
2783        assert_eq!(mv.len_unique(), 3, "len_unique() counts distinct keys");
2784
2785        let unique: alloc::vec::Vec<_> = mv.iter_unique().collect();
2786        assert_eq!(unique, [&("a", 3), &("c", 4), &("b", 5)]);
2787    }
2788
2789    #[test]
2790    fn map_view_iter_unique_all_duplicates() {
2791        let mut mv = MapView::<&str, i32>::default();
2792        mv.push("a", 1);
2793        mv.push("a", 2);
2794        mv.push("a", 3);
2795        assert_eq!(mv.len_unique(), 1);
2796        assert_eq!(
2797            mv.iter_unique().collect::<alloc::vec::Vec<_>>(),
2798            [&("a", 3)]
2799        );
2800    }
2801
2802    #[test]
2803    fn map_view_iter_unique_no_duplicates() {
2804        let mut mv = MapView::<i32, &str>::default();
2805        mv.push(1, "x");
2806        mv.push(2, "y");
2807        assert_eq!(mv.len_unique(), 2);
2808        assert_eq!(
2809            mv.iter_unique().collect::<alloc::vec::Vec<_>>(),
2810            [&(1, "x"), &(2, "y")]
2811        );
2812    }
2813
2814    #[test]
2815    fn map_view_iter_unique_empty() {
2816        let mv = MapView::<&str, i32>::default();
2817        assert_eq!(mv.len_unique(), 0);
2818        assert_eq!(mv.iter_unique().count(), 0);
2819    }
2820
2821    #[test]
2822    fn map_view_keys_and_values() {
2823        let mut mv = MapView::<&str, i32>::default();
2824        mv.push("a", 1);
2825        mv.push("b", 2);
2826        mv.push("c", 3);
2827
2828        let keys: alloc::vec::Vec<_> = mv.keys().copied().collect();
2829        assert_eq!(keys, alloc::vec!["a", "b", "c"]);
2830
2831        let values: alloc::vec::Vec<_> = mv.values().copied().collect();
2832        assert_eq!(values, alloc::vec![1, 2, 3]);
2833    }
2834
2835    #[test]
2836    fn map_view_keys_and_values_empty() {
2837        let mv = MapView::<&str, i32>::default();
2838        assert_eq!(mv.keys().count(), 0);
2839        assert_eq!(mv.values().count(), 0);
2840    }
2841
2842    #[test]
2843    fn map_view_into_iter_collect_to_hashmap() {
2844        let mut mv = MapView::<&str, i32>::default();
2845        mv.push("a", 1);
2846        mv.push("b", 2);
2847        mv.push("a", 3); // duplicate — last-write-wins on collect
2848        let m: crate::__private::HashMap<&str, i32> = mv.into_iter().collect();
2849        assert_eq!(m.len(), 2);
2850        assert_eq!(m.get("a"), Some(&3)); // last value kept
2851        assert_eq!(m.get("b"), Some(&2));
2852    }
2853
2854    // ── bytes_from_source ────────────────────────────────────────────────
2855
2856    #[test]
2857    fn bytes_from_source_none_copies() {
2858        let data: &[u8] = b"hello";
2859        let out = bytes_from_source(None, data);
2860        assert_eq!(&out[..], data);
2861        assert_ne!(out.as_ptr(), data.as_ptr()); // distinct allocation
2862    }
2863
2864    #[test]
2865    fn bytes_from_source_some_within_is_slice_ref() {
2866        let parent = Bytes::copy_from_slice(b"hello world");
2867        let slice = &parent[6..11];
2868        let out = bytes_from_source(Some(&parent), slice);
2869        assert_eq!(&out[..], b"world");
2870        // slice_ref shares the same backing storage — same pointer.
2871        assert_eq!(out.as_ptr(), slice.as_ptr());
2872    }
2873
2874    #[test]
2875    fn bytes_from_source_some_outside_falls_back_to_copy() {
2876        let parent = Bytes::copy_from_slice(b"hello");
2877        let outside: &[u8] = b"world"; // static, not in `parent`
2878        let out = bytes_from_source(Some(&parent), outside);
2879        assert_eq!(&out[..], b"world");
2880        assert_ne!(out.as_ptr(), outside.as_ptr());
2881    }
2882
2883    #[test]
2884    fn bytes_from_source_empty_returns_new() {
2885        let parent = Bytes::copy_from_slice(b"hello");
2886        assert!(bytes_from_source(Some(&parent), &[]).is_empty());
2887        assert!(bytes_from_source(None, &[]).is_empty());
2888    }
2889
2890    #[test]
2891    fn bytes_from_source_full_range() {
2892        let parent = Bytes::copy_from_slice(b"hello");
2893        let out = bytes_from_source(Some(&parent), &parent[..]);
2894        assert_eq!(out.as_ptr(), parent.as_ptr());
2895        assert_eq!(out.len(), parent.len());
2896    }
2897
2898    // ── UnknownFieldsView ────────────────────────────────────────────────
2899
2900    #[test]
2901    fn unknown_fields_view_new_is_empty() {
2902        let uf = UnknownFieldsView::new();
2903        assert!(uf.is_empty());
2904        assert_eq!(uf.encoded_len(), 0);
2905    }
2906
2907    #[test]
2908    fn unknown_fields_view_push_raw_and_encoded_len() {
2909        let mut uf = UnknownFieldsView::new();
2910        uf.push_raw(&[0x08, 0x01]); // field 1, varint 1
2911        uf.push_raw(&[0x10, 0x02]); // field 2, varint 2
2912        assert!(!uf.is_empty());
2913        assert_eq!(uf.encoded_len(), 4);
2914    }
2915
2916    #[test]
2917    fn unknown_fields_view_to_owned_single_field() {
2918        // Build a valid unknown field: tag for field 99, varint wire type,
2919        // value 42.  Tag = (99 << 3) | 0 = 792 = varint bytes [0x98, 0x06].
2920        let span: &[u8] = &[0x98, 0x06, 0x2A];
2921        let mut uf = UnknownFieldsView::new();
2922        uf.push_raw(span);
2923
2924        let owned = uf.to_owned().expect("valid wire data");
2925        assert_eq!(owned.len(), 1);
2926        let field = owned.iter().next().unwrap();
2927        assert_eq!(field.number, 99);
2928        assert_eq!(
2929            field.data,
2930            crate::unknown_fields::UnknownFieldData::Varint(42)
2931        );
2932    }
2933
2934    #[test]
2935    fn unknown_fields_view_to_owned_multiple_fields() {
2936        let mut uf = UnknownFieldsView::new();
2937        // Field 1, varint, value 7:  tag = (1<<3)|0 = 0x08, value = 0x07
2938        uf.push_raw(&[0x08, 0x07]);
2939        // Field 2, fixed32, value 0x01020304:
2940        //   tag = (2<<3)|5 = 0x15, then 4 LE bytes
2941        uf.push_raw(&[0x15, 0x04, 0x03, 0x02, 0x01]);
2942
2943        let owned = uf.to_owned().expect("valid wire data");
2944        assert_eq!(owned.len(), 2);
2945
2946        let mut it = owned.iter();
2947        let f1 = it.next().unwrap();
2948        assert_eq!(f1.number, 1);
2949        assert_eq!(f1.data, crate::unknown_fields::UnknownFieldData::Varint(7));
2950
2951        let f2 = it.next().unwrap();
2952        assert_eq!(f2.number, 2);
2953        assert_eq!(
2954            f2.data,
2955            crate::unknown_fields::UnknownFieldData::Fixed32(0x01020304)
2956        );
2957    }
2958
2959    #[test]
2960    fn unknown_fields_view_to_owned_malformed_returns_error() {
2961        // A truncated tag (high continuation bit, then EOF).
2962        let mut uf = UnknownFieldsView::new();
2963        uf.push_raw(&[0x80]);
2964        assert!(uf.to_owned().is_err());
2965    }
2966
2967    // ── OwnedView ──────────────────────────────────────────────────────
2968
2969    // Minimal types to test OwnedView without depending on generated code.
2970
2971    use crate::message::Message;
2972
2973    /// A trivial "message" for the owned side of the view contract.
2974    #[derive(Clone, Debug, Default, PartialEq)]
2975    struct SimpleMessage {
2976        pub id: i32,
2977        pub name: alloc::string::String,
2978    }
2979
2980    impl crate::DefaultInstance for SimpleMessage {
2981        fn default_instance() -> &'static Self {
2982            static INST: crate::__private::OnceBox<SimpleMessage> =
2983                crate::__private::OnceBox::new();
2984            INST.get_or_init(|| alloc::boxed::Box::new(SimpleMessage::default()))
2985        }
2986    }
2987
2988    impl crate::Message for SimpleMessage {
2989        fn compute_size(&self, _cache: &mut crate::SizeCache) -> u32 {
2990            let mut size = 0u32;
2991            if self.id != 0 {
2992                size += 1 + crate::types::int32_encoded_len(self.id) as u32;
2993            }
2994            if !self.name.is_empty() {
2995                size += 1 + crate::types::string_encoded_len(&self.name) as u32;
2996            }
2997            size
2998        }
2999
3000        fn write_to(&self, _cache: &mut crate::SizeCache, buf: &mut impl bytes::BufMut) {
3001            if self.id != 0 {
3002                crate::encoding::Tag::new(1, crate::encoding::WireType::Varint).encode(buf);
3003                crate::types::encode_int32(self.id, buf);
3004            }
3005            if !self.name.is_empty() {
3006                crate::encoding::Tag::new(2, crate::encoding::WireType::LengthDelimited)
3007                    .encode(buf);
3008                crate::types::encode_string(&self.name, buf);
3009            }
3010        }
3011
3012        fn merge_field(
3013            &mut self,
3014            tag: crate::encoding::Tag,
3015            buf: &mut impl bytes::Buf,
3016            _ctx: crate::DecodeContext<'_>,
3017        ) -> Result<(), DecodeError> {
3018            match tag.field_number() {
3019                1 => self.id = crate::types::decode_int32(buf)?,
3020                2 => crate::types::merge_string(&mut self.name, buf)?,
3021                _ => crate::encoding::skip_field(tag, buf)?,
3022            }
3023            Ok(())
3024        }
3025
3026        fn clear(&mut self) {
3027            self.id = 0;
3028            self.name.clear();
3029        }
3030    }
3031
3032    /// A zero-copy view of `SimpleMessage`. Borrows `name` as `&str`.
3033    #[derive(Clone, Debug, Default, PartialEq)]
3034    struct SimpleMessageView<'a> {
3035        pub id: i32,
3036        pub name: &'a str,
3037    }
3038
3039    // Via the exported macro, which doubles as its unit test.
3040    crate::impl_view_reborrow!(SimpleMessageView);
3041
3042    impl<'a> MessageView<'a> for SimpleMessageView<'a> {
3043        type Owned = SimpleMessage;
3044        fn merge_view_field(
3045            &mut self,
3046            _tag: crate::encoding::Tag,
3047            cur: &'a [u8],
3048            _before_tag: &'a [u8],
3049            _ctx: crate::DecodeContext<'_>,
3050        ) -> Result<&'a [u8], DecodeError> {
3051            Ok(cur)
3052        }
3053
3054        fn decode_view(buf: &'a [u8]) -> Result<Self, DecodeError> {
3055            let mut view = SimpleMessageView::default();
3056            let mut cursor: &'a [u8] = buf;
3057            while !cursor.is_empty() {
3058                let tag = crate::encoding::Tag::decode(&mut cursor)?;
3059                match tag.field_number() {
3060                    1 => view.id = crate::types::decode_int32(&mut cursor)?,
3061                    2 => view.name = crate::types::borrow_str(&mut cursor)?,
3062                    _ => crate::encoding::skip_field(tag, &mut cursor)?,
3063                }
3064            }
3065            Ok(view)
3066        }
3067
3068        fn to_owned_message(&self) -> Result<SimpleMessage, DecodeError> {
3069            Ok(SimpleMessage {
3070                id: self.id,
3071                name: self.name.into(),
3072            })
3073        }
3074    }
3075
3076    impl<'a> ViewEncode<'a> for SimpleMessageView<'a> {
3077        fn compute_size(&self, _cache: &mut crate::SizeCache) -> u32 {
3078            let mut size = 0u32;
3079            if self.id != 0 {
3080                size += 1 + crate::types::int32_encoded_len(self.id) as u32;
3081            }
3082            if !self.name.is_empty() {
3083                size += 1 + crate::types::string_encoded_len(self.name) as u32;
3084            }
3085            size
3086        }
3087
3088        fn write_to(&self, _cache: &mut crate::SizeCache, buf: &mut impl bytes::BufMut) {
3089            if self.id != 0 {
3090                crate::encoding::Tag::new(1, crate::encoding::WireType::Varint).encode(buf);
3091                crate::types::encode_int32(self.id, buf);
3092            }
3093            if !self.name.is_empty() {
3094                crate::encoding::Tag::new(2, crate::encoding::WireType::LengthDelimited)
3095                    .encode(buf);
3096                crate::types::encode_string(self.name, buf);
3097            }
3098        }
3099    }
3100
3101    /// Encode a SimpleMessage to Bytes for testing.
3102    fn encode_simple(id: i32, name: &str) -> Bytes {
3103        let msg = SimpleMessage {
3104            id,
3105            name: name.into(),
3106        };
3107        Bytes::from(msg.encode_to_vec())
3108    }
3109
3110    #[test]
3111    fn owned_view_decode_and_reborrow() {
3112        let bytes = encode_simple(42, "hello");
3113        let view = OwnedView::<SimpleMessageView<'static>>::decode(bytes).unwrap();
3114
3115        // Field access via reborrow — the borrow is tied to `view`.
3116        assert_eq!(view.reborrow().id, 42);
3117        assert_eq!(view.reborrow().name, "hello");
3118    }
3119
3120    #[test]
3121    fn owned_view_to_owned_message() {
3122        let bytes = encode_simple(7, "world");
3123        let view = OwnedView::<SimpleMessageView<'static>>::decode(bytes).unwrap();
3124        let owned = view.to_owned_message().unwrap();
3125
3126        assert_eq!(owned.id, 7);
3127        assert_eq!(owned.name, "world");
3128    }
3129
3130    #[test]
3131    fn owned_view_debug_delegates_to_view() {
3132        let bytes = encode_simple(1, "test");
3133        let view = OwnedView::<SimpleMessageView<'static>>::decode(bytes).unwrap();
3134        let debug = alloc::format!("{:?}", view);
3135        assert!(debug.contains("test"));
3136        assert!(debug.contains("1"));
3137    }
3138
3139    #[test]
3140    fn owned_view_bytes_accessor() {
3141        let bytes = encode_simple(5, "data");
3142        let original_len = bytes.len();
3143        let view = OwnedView::<SimpleMessageView<'static>>::decode(bytes).unwrap();
3144
3145        assert_eq!(view.bytes().len(), original_len);
3146    }
3147
3148    #[test]
3149    fn owned_view_into_bytes_recovers_buffer() {
3150        let bytes = encode_simple(99, "recover");
3151        let expected = bytes.clone();
3152        let view = OwnedView::<SimpleMessageView<'static>>::decode(bytes).unwrap();
3153        let recovered = view.into_bytes();
3154
3155        assert_eq!(recovered, expected);
3156    }
3157
3158    #[test]
3159    fn owned_view_decode_invalid_data_returns_error() {
3160        // Truncated varint
3161        let bad = Bytes::from_static(&[0x08, 0x80]);
3162        let result = OwnedView::<SimpleMessageView<'static>>::decode(bad);
3163        assert!(result.is_err());
3164    }
3165
3166    #[test]
3167    fn owned_view_empty_message() {
3168        let bytes = Bytes::from_static(&[]);
3169        let view = OwnedView::<SimpleMessageView<'static>>::decode(bytes).unwrap();
3170        assert_eq!(view.reborrow().id, 0);
3171        assert_eq!(view.reborrow().name, "");
3172    }
3173
3174    #[test]
3175    fn owned_view_is_send_and_sync() {
3176        fn assert_send_sync<T: Send + Sync>() {}
3177        assert_send_sync::<OwnedView<SimpleMessageView<'static>>>();
3178    }
3179
3180    #[test]
3181    fn owned_view_from_owned_roundtrips() {
3182        let msg = SimpleMessage {
3183            id: 99,
3184            name: "roundtrip".into(),
3185        };
3186        let view = OwnedView::<SimpleMessageView<'static>>::from_owned(&msg).expect("from_owned");
3187        assert_eq!(view.reborrow().id, 99);
3188        assert_eq!(view.reborrow().name, "roundtrip");
3189
3190        let back = view.to_owned_message().unwrap();
3191        assert_eq!(back, msg);
3192    }
3193
3194    #[test]
3195    fn owned_view_decode_with_options() {
3196        let bytes = encode_simple(42, "opts");
3197        let opts = crate::DecodeOptions::new().with_max_message_size(1024);
3198        let view =
3199            OwnedView::<SimpleMessageView<'static>>::decode_with_options(bytes, &opts).unwrap();
3200        assert_eq!(view.reborrow().id, 42);
3201        assert_eq!(view.reborrow().name, "opts");
3202    }
3203
3204    #[test]
3205    fn owned_view_decode_with_options_rejects_oversized() {
3206        let bytes = encode_simple(42, "too large");
3207        let opts = crate::DecodeOptions::new().with_max_message_size(2);
3208        let result = OwnedView::<SimpleMessageView<'static>>::decode_with_options(bytes, &opts);
3209        assert!(result.is_err());
3210    }
3211
3212    #[test]
3213    fn owned_view_clone_survives_original_drop() {
3214        let bytes = encode_simple(42, "cloned");
3215        let view = OwnedView::<SimpleMessageView<'static>>::decode(bytes).unwrap();
3216        let cloned = view.clone();
3217        drop(view); // drop original — clone must still be valid
3218        assert_eq!(cloned.reborrow().id, 42);
3219        assert_eq!(cloned.reborrow().name, "cloned");
3220    }
3221
3222    #[test]
3223    fn owned_view_clone_equality() {
3224        let bytes = encode_simple(42, "eq");
3225        let view = OwnedView::<SimpleMessageView<'static>>::decode(bytes).unwrap();
3226        let cloned = view.clone();
3227        assert_eq!(view, cloned);
3228    }
3229
3230    #[test]
3231    fn owned_view_eq_same_data() {
3232        let a = OwnedView::<SimpleMessageView<'static>>::decode(encode_simple(1, "x")).unwrap();
3233        let b = OwnedView::<SimpleMessageView<'static>>::decode(encode_simple(1, "x")).unwrap();
3234        assert_eq!(a, b);
3235    }
3236
3237    #[test]
3238    fn owned_view_ne_different_data() {
3239        let a = OwnedView::<SimpleMessageView<'static>>::decode(encode_simple(1, "x")).unwrap();
3240        let b = OwnedView::<SimpleMessageView<'static>>::decode(encode_simple(2, "y")).unwrap();
3241        assert_ne!(a, b);
3242    }
3243
3244    #[test]
3245    fn owned_view_into_bytes_after_clone() {
3246        let bytes = encode_simple(42, "test");
3247        let expected = bytes.clone();
3248        let view = OwnedView::<SimpleMessageView<'static>>::decode(bytes).unwrap();
3249        let cloned = view.clone();
3250        drop(view); // drop original first
3251        let recovered = cloned.into_bytes();
3252        assert_eq!(recovered, expected);
3253    }
3254
3255    #[test]
3256    fn owned_view_drop_count() {
3257        use core::sync::atomic::{AtomicUsize, Ordering};
3258
3259        static DROP_COUNT: AtomicUsize = AtomicUsize::new(0);
3260
3261        /// A wrapper view that counts drops.
3262        struct DropCountingView<'a> {
3263            inner: SimpleMessageView<'a>,
3264        }
3265
3266        impl Drop for DropCountingView<'_> {
3267            fn drop(&mut self) {
3268                DROP_COUNT.fetch_add(1, Ordering::SeqCst);
3269            }
3270        }
3271
3272        impl<'a> MessageView<'a> for DropCountingView<'a> {
3273            type Owned = SimpleMessage;
3274            fn merge_view_field(
3275                &mut self,
3276                _tag: crate::encoding::Tag,
3277                cur: &'a [u8],
3278                _before_tag: &'a [u8],
3279                _ctx: crate::DecodeContext<'_>,
3280            ) -> Result<&'a [u8], DecodeError> {
3281                Ok(cur)
3282            }
3283
3284            fn decode_view(buf: &'a [u8]) -> Result<Self, DecodeError> {
3285                Ok(DropCountingView {
3286                    inner: SimpleMessageView::decode_view(buf)?,
3287                })
3288            }
3289
3290            fn to_owned_message(&self) -> Result<SimpleMessage, DecodeError> {
3291                self.inner.to_owned_message()
3292            }
3293        }
3294
3295        // Test normal drop: view drops exactly once.
3296        DROP_COUNT.store(0, Ordering::SeqCst);
3297        {
3298            let bytes = encode_simple(1, "drop");
3299            let _view = OwnedView::<DropCountingView<'static>>::decode(bytes).unwrap();
3300        }
3301        assert_eq!(DROP_COUNT.load(Ordering::SeqCst), 1, "normal drop");
3302
3303        // Test into_bytes: view drops exactly once.
3304        DROP_COUNT.store(0, Ordering::SeqCst);
3305        {
3306            let bytes = encode_simple(2, "into");
3307            let view = OwnedView::<DropCountingView<'static>>::decode(bytes).unwrap();
3308            let _bytes = view.into_bytes();
3309        }
3310        assert_eq!(DROP_COUNT.load(Ordering::SeqCst), 1, "into_bytes drop");
3311    }
3312
3313    #[test]
3314    fn owned_view_name_borrows_from_bytes_buffer() {
3315        let bytes = encode_simple(42, "borrowed");
3316        let view = OwnedView::<SimpleMessageView<'static>>::decode(bytes).unwrap();
3317        let buf = view.bytes();
3318        let buf_start = buf.as_ptr() as usize;
3319        let buf_end = buf_start + buf.len();
3320        let name_ptr = view.reborrow().name.as_ptr() as usize;
3321        assert!(
3322            (buf_start..buf_end).contains(&name_ptr),
3323            "view name should point into the Bytes buffer"
3324        );
3325    }
3326
3327    #[test]
3328    fn owned_view_concurrent_read() {
3329        use alloc::sync::Arc;
3330
3331        let bytes = encode_simple(42, "concurrent");
3332        let view = Arc::new(OwnedView::<SimpleMessageView<'static>>::decode(bytes).unwrap());
3333        let handles: alloc::vec::Vec<_> = (0..4)
3334            .map(|_| {
3335                let v = Arc::clone(&view);
3336                std::thread::spawn(move || {
3337                    assert_eq!(v.reborrow().id, 42);
3338                    assert_eq!(v.reborrow().name, "concurrent");
3339                })
3340            })
3341            .collect();
3342        for h in handles {
3343            h.join().unwrap();
3344        }
3345    }
3346
3347    #[test]
3348    fn owned_view_from_parts_roundtrip() {
3349        let bytes = encode_simple(42, "parts");
3350        // Decode a view from the bytes, then wrap via from_parts.
3351        // SAFETY: `view` was decoded from `bytes`.
3352        let view = unsafe {
3353            let slice: &'static [u8] = core::mem::transmute::<&[u8], &'static [u8]>(&bytes);
3354            let decoded = SimpleMessageView::decode_view(slice).unwrap();
3355            OwnedView::<SimpleMessageView<'static>>::from_parts(bytes, decoded)
3356        };
3357        assert_eq!(view.reborrow().id, 42);
3358        assert_eq!(view.reborrow().name, "parts");
3359    }
3360
3361    // ── ViewReborrow / OwnedView::reborrow ───────────────────────────────
3362
3363    #[test]
3364    fn reborrow_fields_match_original() {
3365        let bytes = encode_simple(7, "hello");
3366        let owned = OwnedView::<SimpleMessageView<'static>>::decode(bytes).unwrap();
3367        let reborrowed: &SimpleMessageView<'_> = owned.reborrow();
3368        assert_eq!(reborrowed.id, 7);
3369        assert_eq!(reborrowed.name, "hello");
3370        // The reborrowed &str must point into the Bytes buffer, not a copy.
3371        let buf_start = owned.bytes().as_ptr() as usize;
3372        let buf_end = buf_start + owned.bytes().len();
3373        assert!((buf_start..buf_end).contains(&(reborrowed.name.as_ptr() as usize)));
3374    }
3375
3376    #[test]
3377    fn reborrow_does_not_consume_owned_view() {
3378        let bytes = encode_simple(1, "world");
3379        let owned = OwnedView::<SimpleMessageView<'static>>::decode(bytes).unwrap();
3380        let r1: &SimpleMessageView<'_> = owned.reborrow();
3381        let r2: &SimpleMessageView<'_> = owned.reborrow();
3382        assert_eq!(r1.name, r2.name);
3383        // `owned` still usable here
3384        assert_eq!(owned.reborrow().name, "world");
3385    }
3386    // ── Lazy views ───────────────────────────────────────────────────────
3387
3388    /// Hand-written lazy view of `SimpleMessage`, shaped like generated
3389    /// `FooLazyView` code: scalars borrowed, one flat scan, fragment merge.
3390    #[derive(Clone, Debug, Default, PartialEq)]
3391    struct SimpleLazyView<'a> {
3392        pub id: i32,
3393        pub name: &'a str,
3394    }
3395
3396    impl<'a> LazyMessageView<'a> for SimpleLazyView<'a> {
3397        type Owned = SimpleMessage;
3398
3399        fn decode_lazy(buf: &'a [u8]) -> Result<Self, DecodeError> {
3400            let limit = core::cell::Cell::new(crate::DEFAULT_UNKNOWN_FIELD_LIMIT);
3401            Self::decode_lazy_with_ctx(
3402                buf,
3403                crate::DecodeContext::new(crate::RECURSION_LIMIT, &limit),
3404            )
3405        }
3406
3407        fn decode_lazy_with_ctx(
3408            buf: &'a [u8],
3409            ctx: crate::DecodeContext<'_>,
3410        ) -> Result<Self, DecodeError> {
3411            let mut view = SimpleLazyView::default();
3412            view.merge_lazy(buf, ctx)?;
3413            Ok(view)
3414        }
3415
3416        fn merge_lazy(
3417            &mut self,
3418            buf: &'a [u8],
3419            ctx: crate::DecodeContext<'_>,
3420        ) -> Result<(), DecodeError> {
3421            let mut cursor: &'a [u8] = buf;
3422            while !cursor.is_empty() {
3423                let tag = crate::encoding::Tag::decode(&mut cursor)?;
3424                match tag.field_number() {
3425                    1 => self.id = crate::types::decode_int32(&mut cursor)?,
3426                    2 => self.name = crate::types::borrow_str(&mut cursor)?,
3427                    _ => crate::encoding::skip_field_depth(tag, &mut cursor, ctx.depth())?,
3428                }
3429            }
3430            Ok(())
3431        }
3432
3433        fn to_owned_message(&self) -> Result<SimpleMessage, DecodeError> {
3434            Ok(SimpleMessage {
3435                id: self.id,
3436                name: self.name.into(),
3437            })
3438        }
3439    }
3440
3441    fn full_budget_ctx(cell: &core::cell::Cell<usize>) -> crate::DecodeContext<'_> {
3442        crate::DecodeContext::new(crate::RECURSION_LIMIT, cell)
3443    }
3444
3445    #[test]
3446    fn lazy_message_field_view_decodes_on_access() {
3447        let bytes = encode_simple(42, "lazy");
3448        let unset = LazyMessageFieldView::<SimpleLazyView<'_>>::unset();
3449        assert!(unset.is_unset());
3450        assert!(unset.fragments().is_empty());
3451        assert!(unset.get().unwrap().is_none());
3452        assert_eq!(unset.get_or_default().unwrap(), SimpleLazyView::default());
3453
3454        let lazy = LazyMessageFieldView::<SimpleLazyView<'_>>::from_bytes(&bytes);
3455        assert!(lazy.is_set());
3456        assert_eq!(lazy.fragments(), &[&bytes[..]]);
3457        let v = lazy.get().unwrap().expect("set");
3458        assert_eq!((v.id, v.name), (42, "lazy"));
3459        // Re-decodes each call (no cache).
3460        assert_eq!(lazy.get().unwrap().unwrap().id, 42);
3461        assert_eq!(v.to_owned_message().unwrap().name, "lazy");
3462    }
3463
3464    #[test]
3465    fn lazy_message_field_view_merges_fragments() {
3466        // A singular message field split across wire occurrences must merge:
3467        // fragment 1 sets `name`, fragment 2 sets `id`; the merged view has
3468        // both, matching the eager/owned decoders.
3469        let frag1 = encode_simple(0, "from-frag-1");
3470        let frag2 = encode_simple(7, "");
3471        let cell = core::cell::Cell::new(crate::DEFAULT_UNKNOWN_FIELD_LIMIT);
3472
3473        let mut lazy = LazyMessageFieldView::<SimpleLazyView<'_>>::unset();
3474        lazy.push_fragment(&frag1, full_budget_ctx(&cell));
3475        assert_eq!(lazy.fragments().len(), 1);
3476        lazy.push_fragment(&frag2, full_budget_ctx(&cell));
3477        assert_eq!(lazy.fragments(), &[&frag1[..], &frag2[..]]);
3478
3479        let v = lazy.get().unwrap().expect("set");
3480        assert_eq!((v.id, v.name), (7, "from-frag-1"));
3481
3482        // Later fragments overwrite singular scalars (last-wins).
3483        let frag3 = encode_simple(9, "final");
3484        lazy.push_fragment(&frag3, full_budget_ctx(&cell));
3485        assert_eq!(lazy.fragments().len(), 3);
3486        let v = lazy.get().unwrap().expect("set");
3487        assert_eq!((v.id, v.name), (9, "final"));
3488    }
3489
3490    #[test]
3491    fn lazy_message_field_view_records_smallest_budgets() {
3492        // Budgets recorded across pushes are min-combined, and the recorded
3493        // allowance replays per access (capture-then-replay).
3494        let bytes = encode_simple(1, "x");
3495        let cell_big = core::cell::Cell::new(500);
3496        let cell_small = core::cell::Cell::new(3);
3497
3498        let mut lazy = LazyMessageFieldView::<SimpleLazyView<'_>>::unset();
3499        lazy.push_fragment(&bytes, crate::DecodeContext::new(80, &cell_big));
3500        lazy.push_fragment(&bytes, crate::DecodeContext::new(50, &cell_small));
3501        // Decoding succeeds — SimpleLazyView has no unknowns or nesting here;
3502        // the recorded budgets only bound what access may consume.
3503        assert!(lazy.get().unwrap().is_some());
3504    }
3505
3506    #[test]
3507    fn lazy_message_field_view_clone_default_debug() {
3508        let bytes = encode_simple(1, "x");
3509        let cell = core::cell::Cell::new(crate::DEFAULT_UNKNOWN_FIELD_LIMIT);
3510        let mut lazy = LazyMessageFieldView::<SimpleLazyView<'_>>::default();
3511        assert!(lazy.is_unset());
3512        lazy.push_fragment(&bytes, full_budget_ctx(&cell));
3513        lazy.push_fragment(&bytes, full_budget_ctx(&cell));
3514        let cloned = lazy.clone();
3515        assert_eq!(cloned.fragments(), lazy.fragments());
3516        let dbg = alloc::format!("{lazy:?}");
3517        assert!(dbg.contains("is_set: true"), "{dbg}");
3518        assert!(dbg.contains("fragments: 2"), "{dbg}");
3519    }
3520
3521    #[test]
3522    fn lazy_message_field_view_malformed_errors_on_access() {
3523        // 0xFF starts a tag whose varint never terminates — invalid.
3524        let malformed = [0xFFu8; 3];
3525        let lazy = LazyMessageFieldView::<SimpleLazyView<'_>>::from_bytes(&malformed);
3526        // Deferred validation: construction succeeds, access fails.
3527        assert!(lazy.is_set());
3528        assert!(lazy.get().is_err());
3529    }
3530
3531    #[test]
3532    fn lazy_repeated_view_decodes_per_element() {
3533        let b0 = encode_simple(1, "a");
3534        let b1 = encode_simple(2, "b");
3535        let cell = core::cell::Cell::new(crate::DEFAULT_UNKNOWN_FIELD_LIMIT);
3536        let mut rep = LazyRepeatedView::<SimpleLazyView<'_>>::new();
3537        assert!(rep.is_empty());
3538        rep.push_bytes(&b0, full_budget_ctx(&cell));
3539        rep.push_bytes(&b1, full_budget_ctx(&cell));
3540        assert_eq!(rep.len(), 2);
3541        assert_eq!(rep.raw_elements(), &[&b0[..], &b1[..]]);
3542        assert_eq!(rep.get(0).unwrap().unwrap().name, "a");
3543        assert_eq!(rep.get(1).unwrap().unwrap().id, 2);
3544        assert!(rep.get(2).is_none());
3545    }
3546
3547    #[test]
3548    fn lazy_repeated_view_iter() {
3549        let bufs: alloc::vec::Vec<Bytes> = (1..=3)
3550            .map(|i| encode_simple(i, core::str::from_utf8(&[b'a' + i as u8]).unwrap()))
3551            .collect();
3552        let cell = core::cell::Cell::new(crate::DEFAULT_UNKNOWN_FIELD_LIMIT);
3553        let mut rep = LazyRepeatedView::<SimpleLazyView<'_>>::new();
3554        for b in &bufs {
3555            rep.push_bytes(b, full_budget_ctx(&cell));
3556        }
3557
3558        let iter = rep.iter();
3559        assert_eq!(iter.len(), 3);
3560        let ids: alloc::vec::Vec<i32> = iter.map(|r| r.unwrap().id).collect();
3561        assert_eq!(ids, [1, 2, 3]);
3562
3563        // IntoIterator for &LazyRepeatedView.
3564        let names: alloc::vec::Vec<&str> = (&rep).into_iter().map(|r| r.unwrap().name).collect();
3565        assert_eq!(names, ["b", "c", "d"]);
3566
3567        // DoubleEndedIterator.
3568        let rev_ids: alloc::vec::Vec<i32> = rep.iter().rev().map(|r| r.unwrap().id).collect();
3569        assert_eq!(rev_ids, [3, 2, 1]);
3570    }
3571
3572    #[test]
3573    fn lazy_repeated_view_iter_surfaces_element_errors() {
3574        let good = encode_simple(1, "ok");
3575        let malformed = [0xFFu8; 3];
3576        let cell = core::cell::Cell::new(crate::DEFAULT_UNKNOWN_FIELD_LIMIT);
3577        let mut rep = LazyRepeatedView::<SimpleLazyView<'_>>::new();
3578        rep.push_bytes(&good, full_budget_ctx(&cell));
3579        rep.push_bytes(&malformed, full_budget_ctx(&cell));
3580        let results: alloc::vec::Vec<_> = rep.iter().collect();
3581        assert!(results[0].is_ok());
3582        assert!(results[1].is_err());
3583        let cloned = rep.clone();
3584        assert_eq!(cloned.len(), 2);
3585    }
3586}