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::encode_sink::EncodeSink;
103use crate::error::DecodeError;
104use crate::message::Message as _;
105use bytes::Bytes;
106
107/// Trait for zero-copy borrowed message views.
108///
109/// View types borrow from the input buffer and provide read-only access
110/// to message fields without allocation. Each generated `MyMessageView<'a>`
111/// implements this trait.
112///
113/// The lifetime `'a` ties the view to the input buffer — the view cannot
114/// outlive the buffer it was decoded from.
115///
116/// Generated view structs may gain fields across releases; see the
117/// [struct evolution policy on `Message`](crate::Message#struct-evolution-policy).
118pub trait MessageView<'a>: Sized {
119    /// The corresponding owned message type.
120    type Owned: crate::Message;
121
122    /// Decode a view from a buffer, borrowing string/bytes fields directly.
123    ///
124    /// The returned view borrows from `buf`'s underlying bytes. The caller
125    /// must ensure the buffer is contiguous (e.g., `&[u8]` or `bytes::Bytes`).
126    ///
127    /// Decoding validates the whole message tree eagerly. For
128    /// decode-on-access of large sub-message trees, see the opt-in
129    /// [`LazyMessageView`] family (`lazy_views` codegen option).
130    ///
131    /// Generated impls construct a default [`DecodeContext`](crate::DecodeContext)
132    /// and delegate to [`decode_view_ctx`](Self::decode_view_ctx). (Kept
133    /// required, without a `Self: Default` bound, so generic callers stay
134    /// bound-free.)
135    ///
136    /// The default context carries the same three budgets
137    /// [`Message::decode`](crate::Message::decode) applies:
138    /// [`RECURSION_LIMIT`](crate::RECURSION_LIMIT),
139    /// [`DEFAULT_UNKNOWN_FIELD_LIMIT`](crate::DEFAULT_UNKNOWN_FIELD_LIMIT), and
140    /// [`DEFAULT_ELEMENT_MEMORY_LIMIT`](crate::DEFAULT_ELEMENT_MEMORY_LIMIT).
141    /// A view of a repeated field costs element memory just as the owned decode
142    /// does — each element occupies a `size_of::<FooView>()` slot in a `Vec`
143    /// even though its string and bytes contents stay borrowed.
144    fn decode_view(buf: &'a [u8]) -> Result<Self, DecodeError>;
145
146    /// Decode a view under custom decode limits.
147    ///
148    /// Used by [`DecodeOptions::decode_view`](crate::DecodeOptions::decode_view)
149    /// to pass a non-default recursion depth, unknown-field allowance, and
150    /// element-memory budget.
151    /// The default implementation delegates to
152    /// [`decode_view`](Self::decode_view) and **ignores the context** —
153    /// a hand-written `MessageView` that recurses or preserves unknown
154    /// fields must override this method to honor the limits configured on
155    /// `DecodeOptions`. Implementing
156    /// [`merge_view_field`](Self::merge_view_field) is **not sufficient**:
157    /// without this override, `DecodeOptions` limits never reach your
158    /// field arms. The one-line override is
159    /// `Self::decode_view_ctx(buf, ctx)` (when `Self: Default`). Generated
160    /// code always overrides it that way.
161    ///
162    /// Not to be confused with [`decode_view_ctx`](Self::decode_view_ctx),
163    /// which is the provided decoder that *honors* the context; this method
164    /// is the override point `DecodeOptions` calls.
165    fn decode_view_with_ctx(
166        buf: &'a [u8],
167        _ctx: crate::DecodeContext<'_>,
168    ) -> Result<Self, DecodeError> {
169        Self::decode_view(buf)
170    }
171
172    /// Decode a view under an explicit [`DecodeContext`](crate::DecodeContext)
173    /// (remaining recursion depth, unknown-field allowance, and element-memory
174    /// budget), driving the provided tag loop over
175    /// [`merge_view_field`](Self::merge_view_field).
176    ///
177    /// This is the bridge a hand-written impl uses to wire its required
178    /// `decode_view` to its required `merge_view_field`:
179    ///
180    /// ```rust,ignore
181    /// fn decode_view(buf: &'a [u8]) -> Result<Self, buffa::DecodeError> {
182    ///     let limit = core::cell::Cell::new(buffa::DEFAULT_UNKNOWN_FIELD_LIMIT);
183    ///     let elem = core::cell::Cell::new(buffa::DEFAULT_ELEMENT_MEMORY_LIMIT);
184    ///     Self::decode_view_ctx(
185    ///         buf,
186    ///         buffa::DecodeContext::new(buffa::RECURSION_LIMIT, &limit)
187    ///             .with_element_memory(&elem),
188    ///     )
189    /// }
190    /// ```
191    ///
192    /// Attaching the element-memory budget is load-bearing, not decoration.
193    /// [`register_element_memory`](crate::DecodeContext::register_element_memory)
194    /// returns `Ok(())` when no budget is attached, so a context built without
195    /// [`with_element_memory`](crate::DecodeContext::with_element_memory)
196    /// turns every repeated-element charge in every field arm into a no-op.
197    ///
198    /// Also called by generated sub-message decode arms with a descended
199    /// context. Not to be confused with
200    /// [`decode_view_with_ctx`](Self::decode_view_with_ctx), the
201    /// `DecodeOptions` override point whose *default* ignores the context.
202    ///
203    /// # Errors
204    ///
205    /// Returns a [`DecodeError`] on malformed input, a wire-type mismatch, or
206    /// when a configured decode limit (recursion depth, unknown-field
207    /// allowance) is exceeded.
208    fn decode_view_ctx(buf: &'a [u8], ctx: crate::DecodeContext<'_>) -> Result<Self, DecodeError>
209    where
210        Self: Default,
211    {
212        let mut view = Self::default();
213        view.merge_into_view(buf, ctx)?;
214        Ok(view)
215    }
216
217    /// Merge fields from `buf` into this view (proto merge semantics):
218    /// repeated fields append, singular fields last-wins, singular message
219    /// fields merge recursively.
220    ///
221    /// The per-message work is the field `match` in
222    /// [`merge_view_field`](Self::merge_view_field); this provided method
223    /// owns the tag loop that every generated view previously restated.
224    /// Each iteration consumes the field's tag itself, so the loop makes
225    /// progress even if an arm consumes no payload bytes.
226    ///
227    /// # Errors
228    ///
229    /// Returns a [`DecodeError`] on malformed input, a wire-type mismatch, or
230    /// when a configured decode limit (recursion depth, unknown-field
231    /// allowance) is exceeded.
232    fn merge_into_view(
233        &mut self,
234        buf: &'a [u8],
235        ctx: crate::DecodeContext<'_>,
236    ) -> Result<(), DecodeError> {
237        let mut cur: &'a [u8] = buf;
238        while !cur.is_empty() {
239            // Captured so unknown fields can preserve their raw byte span
240            // (`before_tag.len() - cur.len()` after the payload is consumed).
241            let before_tag = cur;
242            let tag = crate::encoding::Tag::decode(&mut cur)?;
243            cur = self.merge_view_field(tag, cur, before_tag, ctx)?;
244        }
245        Ok(())
246    }
247
248    /// Decode one field's payload into this view (generated per message).
249    ///
250    /// `cur` is the input positioned just past `tag`; the implementation
251    /// returns the remaining input after the field's payload. The
252    /// pass-by-value/return shape (rather than `&mut &'a [u8]`) keeps each
253    /// arm's `&mut` borrow of the slice local to that arm — sub-message
254    /// arms can hand `cur` slices to recursive decode calls without
255    /// fighting a long-lived outer `&mut` reborrow. `before_tag` is the
256    /// input including the tag bytes, for raw-span unknown-field capture.
257    ///
258    /// Hand-written views must supply this (it is the one method the
259    /// provided decode loop requires). A view that instead overrides both
260    /// [`decode_view`](Self::decode_view) and
261    /// [`decode_view_with_ctx`](Self::decode_view_with_ctx) to decode by hand
262    /// never reaches the provided loop, so it can satisfy the trait with a
263    /// one-line `Ok(cur)` stub. The canonical shape is a match on
264    /// `tag.field_number()`. Mark the method `#[inline]`: the provided loop
265    /// calls it once per field across the crate boundary, so the hint lets the
266    /// optimizer fold the match into that loop.
267    ///
268    /// ```rust,ignore
269    /// #[inline]
270    /// fn merge_view_field(
271    ///     &mut self,
272    ///     tag: buffa::encoding::Tag,
273    ///     cur: &'a [u8],
274    ///     _before_tag: &'a [u8],
275    ///     ctx: buffa::DecodeContext<'_>,
276    /// ) -> Result<&'a [u8], buffa::DecodeError> {
277    ///     let mut cur = cur;
278    ///     match tag.field_number() {
279    ///         1 => self.id = buffa::types::decode_int32(&mut cur)?,
280    ///         2 => self.name = buffa::types::borrow_str(&mut cur)?,
281    ///         _ => buffa::encoding::skip_field_depth(tag, &mut cur, ctx.depth())?,
282    ///     }
283    ///     Ok(cur)
284    /// }
285    /// ```
286    ///
287    /// Views that preserve unknown fields capture the raw span — tag
288    /// included — via `before_tag` (the span length is measured *after* the
289    /// payload is consumed) and store it with
290    /// [`UnknownFieldsView::push_record`], which charges the context's
291    /// unknown-field allowance per field (including fields nested in
292    /// unknown groups) so that [`to_owned_message`](Self::to_owned_message)
293    /// cannot exhaust it later; the provided loop stays message-agnostic:
294    ///
295    /// ```rust,ignore
296    /// _ => {
297    ///     buffa::encoding::skip_field_depth(tag, &mut cur, ctx.depth())?;
298    ///     let span_len = before_tag.len() - cur.len();
299    ///     self.unknown_fields.push_record(before_tag, span_len, ctx)?;
300    /// }
301    /// ```
302    ///
303    /// The returned slice must be a suffix of `cur` (and hence of
304    /// `before_tag`): the provided loop continues from it, and the
305    /// unknown-field span is measured as `before_tag.len() - cur.len()`, which
306    /// underflows and panics if the returned slice is longer than the input.
307    ///
308    /// # Errors
309    ///
310    /// Returns a [`DecodeError`] on malformed payloads or wire-type
311    /// mismatches.
312    fn merge_view_field(
313        &mut self,
314        tag: crate::encoding::Tag,
315        cur: &'a [u8],
316        before_tag: &'a [u8],
317        ctx: crate::DecodeContext<'_>,
318    ) -> Result<&'a [u8], DecodeError>;
319
320    /// Convert this view to the owned message type.
321    ///
322    /// This allocates and copies all borrowed fields. Equivalent to
323    /// [`to_owned_from_source(None)`](Self::to_owned_from_source).
324    ///
325    /// For views produced by [`decode_view`](Self::decode_view) (or the
326    /// other wire-decoding entry points), this cannot fail: decoding
327    /// charged the unknown-field allowance with exactly the slots that
328    /// re-materializing preserved unknown fields consumes, every span was
329    /// parsed off the wire, and re-materialization replays under the field
330    /// budget and group-nesting depth recorded at decode time. The `Result`
331    /// remains for hand-written view impls and for views holding manually
332    /// pushed ([`UnknownFieldsView::push_raw`]) unknown-field spans.
333    /// [`OwnedView`], which always holds a wire-decoded view, exposes this
334    /// conversion infallibly — see
335    /// [`OwnedView::to_owned_message`](OwnedView::to_owned_message) (and the
336    /// generated `FooOwnedView` wrappers likewise).
337    ///
338    /// # Errors
339    ///
340    /// Returns an error if re-materializing preserved unknown fields fails —
341    /// possible only for views not produced by wire decoding, as described
342    /// above.
343    fn to_owned_message(&self) -> Result<Self::Owned, DecodeError>;
344
345    /// Convert this view to the owned message type, optionally slicing
346    /// `bytes::Bytes`-typed fields from `source` instead of copying.
347    ///
348    /// When `source` is the [`Bytes`] buffer this view was decoded from,
349    /// owned fields configured for `bytes::Bytes` (via the `bytes_fields`
350    /// codegen option) are produced via [`Bytes::slice_ref`] — a refcount
351    /// bump, no allocation or copy. Borrowed fields that fall outside
352    /// `source` (e.g. on a manually-constructed view) and the `None` case
353    /// fall back to [`Bytes::copy_from_slice`].
354    ///
355    /// Generated view types override this; the default delegates to
356    /// [`to_owned_message`](Self::to_owned_message) so hand-written impls
357    /// need only provide that method.
358    ///
359    /// # Errors
360    ///
361    /// Same contract as [`to_owned_message`](Self::to_owned_message).
362    fn to_owned_from_source(&self, source: Option<&Bytes>) -> Result<Self::Owned, DecodeError> {
363        let _ = source;
364        self.to_owned_message()
365    }
366}
367
368/// Exposes the real lifetime of an [`OwnedView`]'s borrows.
369///
370/// `OwnedView<V>` stores `V` with a `'static` lifetime — the actual borrows
371/// point into its internal [`Bytes`] buffer. `ViewReborrow` lets
372/// [`OwnedView::reborrow`] return a reference typed as `&'b V::Reborrowed<'b>`,
373/// tying the borrow to `&'b self` so the compiler can reason about it correctly.
374///
375/// Codegen emits `impl ViewReborrow` automatically for every generated view
376/// type. Hand-written view types must provide it manually if
377/// [`OwnedView::reborrow`] is needed.
378///
379/// # Soundness
380///
381/// `ViewReborrow` is a **safe** trait. Soundness is established mechanically
382/// by the compiler at each impl site: the [`reborrow`](Self::reborrow) method
383/// body coerces a `&'b Self` (where `Self = FooView<'static>`) to
384/// `&'b Self::Reborrowed<'b>` (= `&'b FooView<'b>`). Rust accepts this only
385/// when `FooView` is **covariant** in its lifetime parameter — a covariant
386/// `FooView<'static>` is a subtype of `FooView<'b>` and the coercion is a
387/// standard subtyping move. Invariant fields (`Cell<&'a T>`, `&'a mut T`,
388/// `fn(&'a T)`) make the type invariant in `'a`; the trait body then fails
389/// to compile and the impl is rejected — which is exactly what should
390/// happen, because narrowing the lifetime of an invariant view *would* be
391/// unsound.
392///
393/// Hand-written impls cannot accidentally introduce undefined behaviour
394/// without writing `unsafe` themselves: the canonical body is just `this`,
395/// which the type checker accepts iff the variance permits the coercion.
396#[rustversion::attr(
397    since(1.78),
398    diagnostic::on_unimplemented(
399        message = "`{Self}` does not implement `ViewReborrow` — required by `OwnedView::reborrow`",
400        note = "for a generated view type, this impl is emitted automatically by codegen",
401        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    }}",
402        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",
403        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"
404    )
405)]
406pub trait ViewReborrow: MessageView<'static> {
407    /// The same view type with its lifetime shortened to `'b`.
408    type Reborrowed<'b>: MessageView<'b, Owned = <Self as MessageView<'static>>::Owned>
409    where
410        Self: 'b;
411
412    /// Coerce `&'b Self` (= `&'b FooView<'static>`) to
413    /// `&'b Self::Reborrowed<'b>` (= `&'b FooView<'b>`). The canonical body
414    /// is just `this`; the compiler accepts it via standard lifetime
415    /// variance for covariant view types.
416    ///
417    /// Called by [`OwnedView::reborrow`]; users shouldn't need to call this
418    /// method directly.
419    fn reborrow<'b>(this: &'b Self) -> &'b Self::Reborrowed<'b>;
420}
421
422/// Implement [`ViewReborrow`] for a generated view type.
423///
424/// Emitted by generated code (one invocation per view struct); the trait's
425/// `on_unimplemented` note shows the equivalent expansion for hand-written
426/// views.
427///
428/// ```rust,ignore
429/// buffa::impl_view_reborrow!(MyMessageView);
430/// ```
431#[macro_export]
432macro_rules! impl_view_reborrow {
433    ($ty:ident) => {
434        impl $crate::ViewReborrow for $ty<'static> {
435            type Reborrowed<'b> = $ty<'b>;
436            fn reborrow<'b>(this: &'b Self) -> &'b Self::Reborrowed<'b> {
437                this
438            }
439        }
440    };
441}
442
443/// Links an owned message type to its generated zero-copy view types.
444///
445/// For a message `Foo`, generated code implements this trait as
446/// `View<'a> = FooView<'a>` (the borrowed view) and
447/// `ViewHandle = FooOwnedView` (the self-contained `'static` handle). The
448/// trait lets code that is generic over an owned message name those types —
449/// for example an RPC framework that decodes `M::View<'_>` from a request
450/// body it owns, or holds `M::ViewHandle` items in a stream — without
451/// per-message glue on the consumer's side.
452///
453/// The associated types intentionally carry only structural bounds:
454///
455/// - [`View<'a>`](Self::View) is the message's view, with
456///   [`Owned`](MessageView::Owned)` = Self`.
457/// - [`ViewHandle`](Self::ViewHandle) is convertible from, and exposes via
458///   [`AsRef`], the corresponding `OwnedView<Self::View<'static>>`, so
459///   generic code can reach [`reborrow`](OwnedView::reborrow),
460///   [`bytes`](OwnedView::bytes), and
461///   [`to_owned_message`](OwnedView::to_owned_message) without naming the
462///   concrete wrapper. The wrapper's per-field accessor methods remain
463///   inherent on the concrete type.
464///
465/// Generic code that wants to reborrow through the handle
466/// (`handle.as_ref().reborrow()`) adds `M::View<'static>: ViewReborrow` as a
467/// bound at the use site; every generated view satisfies it. (The bound
468/// cannot live on the trait itself: a `where Self::View<'static>:
469/// ViewReborrow` clause currently trips a GAT normalization error, E0308
470/// "expected `MessageView<'a>`, found `MessageView<'static>`".)
471///
472/// # Implementing
473///
474/// Implementations are generated alongside the view and owned-view wrapper
475/// (and are therefore gated with them). Hand-written implementations are only
476/// needed for hand-written view types and must follow the same shape.
477#[rustversion::attr(
478    since(1.78),
479    diagnostic::on_unimplemented(
480        message = "`{Self}` does not implement `HasMessageView` — its message-view family was not generated or is not enabled",
481        note = "the `HasMessageView` impl is emitted next to each message's view types: \
482                regenerate the crate that defines `{Self}` with buffa 0.7.0 or newer and \
483                views enabled — `generate_views(true)` (on by default) in a buffa-build / \
484                buffa-codegen config, or `views=true` for protoc-gen-buffa",
485        note = "if the defining crate feature-gates its generated impls, enabling its views \
486                feature is enough — no regeneration needed"
487    )
488)]
489pub trait HasMessageView: crate::Message + Sized {
490    /// The zero-copy view of `Self`, borrowing from a buffer with lifetime
491    /// `'a`.
492    type View<'a>: MessageView<'a, Owned = Self> + Send + Sync;
493
494    /// The generated `'static` owned-view handle for `Self`
495    /// (`FooOwnedView`).
496    type ViewHandle: From<OwnedView<Self::View<'static>>>
497        + AsRef<OwnedView<Self::View<'static>>>
498        + Send
499        + Sync
500        + 'static;
501
502    /// Decode a borrowed [`View`](Self::View) from a byte slice.
503    ///
504    /// Convenience for generic code: lets a caller bounded only on
505    /// `M: HasMessageView` write `M::decode_view(buf)` instead of the
506    /// associated-type path
507    /// `<M as HasMessageView>::View::decode_view(buf)`. The returned view
508    /// borrows from `buf`. Reading the returned view (e.g.
509    /// [`to_owned_message`](MessageView::to_owned_message)) requires
510    /// [`MessageView`] in scope.
511    ///
512    /// Like the underlying [`MessageView::decode_view`], this does not
513    /// enforce `max_message_size`; use
514    /// [`decode_view_with_options`](Self::decode_view_with_options) for that.
515    ///
516    /// # Errors
517    ///
518    /// Returns [`DecodeError`] if the buffer contains invalid protobuf data.
519    #[inline]
520    fn decode_view(buf: &[u8]) -> Result<Self::View<'_>, DecodeError> {
521        <Self::View<'_> as MessageView<'_>>::decode_view(buf)
522    }
523
524    /// Decode a borrowed [`View`](Self::View) under custom
525    /// [`DecodeOptions`](crate::DecodeOptions) (recursion limit, max message
526    /// size, unknown-field limit).
527    ///
528    /// Convenience for generic code; equivalent to
529    /// [`DecodeOptions::decode_view::<M::View<'_>>`](crate::DecodeOptions::decode_view).
530    ///
531    /// # Errors
532    ///
533    /// Returns [`DecodeError`] if the buffer is invalid or exceeds the
534    /// configured limits.
535    #[inline]
536    fn decode_view_with_options<'a>(
537        buf: &'a [u8],
538        opts: &crate::DecodeOptions,
539    ) -> Result<Self::View<'a>, DecodeError> {
540        opts.decode_view(buf)
541    }
542
543    /// Decode a [`ViewHandle`](Self::ViewHandle) from a [`Bytes`] buffer.
544    ///
545    /// Convenience for generic code; equivalent to decoding an
546    /// [`OwnedView<Self::View<'static>>`](OwnedView) and converting it with
547    /// `From`.
548    ///
549    /// # Errors
550    ///
551    /// Returns [`DecodeError`] if the buffer contains invalid protobuf data.
552    fn decode_view_handle(bytes: Bytes) -> Result<Self::ViewHandle, DecodeError> {
553        Ok(Self::ViewHandle::from(
554            OwnedView::<Self::View<'static>>::decode(bytes)?,
555        ))
556    }
557
558    /// Decode a [`ViewHandle`](Self::ViewHandle) with custom
559    /// [`DecodeOptions`](crate::DecodeOptions) (recursion limit, max message
560    /// size).
561    ///
562    /// # Errors
563    ///
564    /// Returns [`DecodeError`] if the buffer is invalid or exceeds the
565    /// configured limits.
566    fn decode_view_handle_with_options(
567        bytes: Bytes,
568        opts: &crate::DecodeOptions,
569    ) -> Result<Self::ViewHandle, DecodeError> {
570        Ok(Self::ViewHandle::from(
571            OwnedView::<Self::View<'static>>::decode_with_options(bytes, opts)?,
572        ))
573    }
574}
575
576/// Produce a [`Bytes`] for a borrowed slice, preferring a zero-copy
577/// [`Bytes::slice_ref`] into `source` when the slice lies within it.
578///
579/// Used by generated [`MessageView::to_owned_from_source`] for
580/// `bytes_fields`. Empty slices return [`Bytes::new`]; slices outside
581/// `source` (or `source = None`) fall back to [`Bytes::copy_from_slice`].
582#[doc(hidden)]
583#[inline]
584pub fn bytes_from_source(source: Option<&Bytes>, slice: &[u8]) -> Bytes {
585    if slice.is_empty() {
586        return Bytes::new();
587    }
588    if let Some(b) = source {
589        if let Some(shared) = try_slice_ref(b, slice) {
590            return shared;
591        }
592    }
593    Bytes::copy_from_slice(slice)
594}
595
596/// Zero-copy [`Bytes::slice_ref`] guarded by `slice_ref`'s own containment
597/// precondition: returns `Some` only when `slice` lies entirely within
598/// `backing`, so callers fall back to a copy rather than panic for slices
599/// from elsewhere. Shared by [`bytes_from_source`] and the
600/// [`Rope`](crate::Rope) backing-buffer capture.
601///
602/// The caller is responsible for excluding empty slices when an empty
603/// result is not wanted (an empty slice's dangling pointer can spuriously
604/// fall inside any range).
605#[inline]
606pub(crate) fn try_slice_ref(backing: &Bytes, slice: &[u8]) -> Option<Bytes> {
607    let b_start = backing.as_ptr() as usize;
608    let s_start = slice.as_ptr() as usize;
609    let b_end = b_start.checked_add(backing.len())?;
610    let s_end = s_start.checked_add(slice.len())?;
611    (s_start >= b_start && s_end <= b_end).then(|| backing.slice_ref(slice))
612}
613
614/// Serialize a [`MessageView`] directly from its borrowed fields.
615///
616/// Symmetric with [`Message`](crate::Message)'s two-pass
617/// `compute_size` / `write_to` model, but the `&'a str` / `&'a [u8]` /
618/// [`MapView`] / [`RepeatedView`] fields are written by borrow — no
619/// owned-struct intermediary, no per-field `String`/`Vec<u8>` allocations.
620///
621/// Generated `*View<'a>` types implement this trait whenever views are
622/// generated (`generate_views(true)`, the default). Serialization state
623/// lives in the external [`SizeCache`](crate::SizeCache), not the view —
624/// view structs hold no interior mutability and remain `Send + Sync`.
625///
626/// ## When to use
627///
628/// Reach for `ViewEncode` when the source data is already in memory and
629/// you would otherwise allocate an owned message just to encode-then-drop
630/// it — e.g. an RPC handler serializing from app state. If you already
631/// hold the owned message, use [`Message::encode`](crate::Message::encode)
632/// instead; the wire output is identical.
633///
634/// ```rust,ignore
635/// let view = PersonView {
636///     name: "borrowed",
637///     tags: ["a", "b"].iter().copied().collect(),
638///     ..Default::default()
639/// };
640/// let bytes = view.encode_to_vec();
641/// ```
642#[rustversion::attr(
643    since(1.78),
644    diagnostic::on_unimplemented(
645        message = "`{Self}` does not implement `ViewEncode` — view types were not generated for this message",
646        note = "ViewEncode is implemented on every generated `*View<'a>` type; enable `generate_views(true)` (on by default) in your buffa-build / buffa-codegen config"
647    )
648)]
649pub trait ViewEncode<'a>: MessageView<'a> {
650    /// Compute the encoded byte size of this view, recording nested
651    /// sub-message sizes in `cache` for [`write_to`](Self::write_to)
652    /// to consume.
653    ///
654    /// Most callers should use [`encode`](Self::encode) instead, which runs
655    /// both passes with a fresh cache.
656    fn compute_size(&self, cache: &mut crate::SizeCache) -> u32;
657
658    /// Write this view's encoded bytes to a buffer, consuming
659    /// nested-message sizes from `cache` (populated by a prior
660    /// [`compute_size`](Self::compute_size) call on the same cache).
661    ///
662    /// Most callers should use [`encode`](Self::encode) instead. This is a
663    /// low-level primitive: the 2 GiB size check
664    /// ([`MAX_MESSAGE_BYTES`](crate::MAX_MESSAGE_BYTES)) lives in the
665    /// provided encode entry points, so callers driving `compute_size` /
666    /// `write_to` directly must validate the size themselves (via
667    /// [`checked_encode_size`](crate::checked_encode_size)).
668    fn write_to(&self, cache: &mut crate::SizeCache, buf: &mut impl EncodeSink);
669
670    /// Compute size, then write. Primary view-encode entry point.
671    ///
672    /// The sink can be any [`BufMut`](bytes::BufMut) (contiguous output) or
673    /// a [`Rope`](crate::Rope); a rope constructed with
674    /// [`with_backing`](crate::Rope::with_backing) on the view's source
675    /// buffer re-encodes large borrowed fields zero-copy.
676    ///
677    /// # Panics
678    ///
679    /// Panics if the encoded size exceeds the 2 GiB protobuf limit
680    /// ([`MAX_MESSAGE_BYTES`](crate::MAX_MESSAGE_BYTES)) — see
681    /// [`try_encode`](Self::try_encode) for the error-returning variant.
682    #[inline]
683    fn encode(&self, buf: &mut impl EncodeSink) {
684        self.try_encode(buf)
685            .unwrap_or_else(|_| crate::message::encode_size_overflow())
686    }
687
688    /// Encode, returning an error instead of panicking if the encoded size
689    /// exceeds the 2 GiB protobuf limit
690    /// ([`MAX_MESSAGE_BYTES`](crate::MAX_MESSAGE_BYTES)).
691    ///
692    /// On `Err`, nothing is written to `buf`.
693    ///
694    /// # Errors
695    ///
696    /// Returns [`EncodeError::MessageTooLarge`](crate::EncodeError::MessageTooLarge)
697    /// if the encoded size exceeds the limit.
698    fn try_encode(&self, buf: &mut impl EncodeSink) -> Result<(), crate::EncodeError> {
699        let mut cache = crate::SizeCache::new();
700        crate::message::checked_encode_size(self.compute_size(&mut cache))?;
701        self.write_to(&mut cache, buf);
702        Ok(())
703    }
704
705    /// Encode using a caller-supplied [`SizeCache`](crate::SizeCache), for
706    /// reuse across many encodes in a hot loop. Clears the cache first.
707    ///
708    /// # Panics
709    ///
710    /// Panics if the encoded size exceeds the 2 GiB protobuf limit
711    /// ([`MAX_MESSAGE_BYTES`](crate::MAX_MESSAGE_BYTES)) — see
712    /// [`try_encode_with_cache`](Self::try_encode_with_cache) for the
713    /// error-returning variant.
714    #[inline]
715    fn encode_with_cache(&self, cache: &mut crate::SizeCache, buf: &mut impl EncodeSink) {
716        self.try_encode_with_cache(cache, buf)
717            .unwrap_or_else(|_| crate::message::encode_size_overflow())
718    }
719
720    /// Encode with a caller-supplied [`SizeCache`](crate::SizeCache),
721    /// returning an error instead of panicking if the encoded size exceeds
722    /// the 2 GiB protobuf limit ([`MAX_MESSAGE_BYTES`](crate::MAX_MESSAGE_BYTES)).
723    /// Clears the cache first.
724    ///
725    /// On `Err`, nothing is written to `buf`.
726    ///
727    /// # Errors
728    ///
729    /// Returns [`EncodeError::MessageTooLarge`](crate::EncodeError::MessageTooLarge)
730    /// if the encoded size exceeds the limit.
731    fn try_encode_with_cache(
732        &self,
733        cache: &mut crate::SizeCache,
734        buf: &mut impl EncodeSink,
735    ) -> Result<(), crate::EncodeError> {
736        cache.clear();
737        crate::message::checked_encode_size(self.compute_size(cache))?;
738        self.write_to(cache, buf);
739        Ok(())
740    }
741
742    /// Encode this view into `buf` only if its encoded size fits within
743    /// `max_bytes`, using a single size pass that is then reused for the write.
744    ///
745    /// This avoids the double tree-walk that `try_encoded_len` + `encode`
746    /// would require: one `compute_size` pass populates the
747    /// [`SizeCache`](crate::SizeCache); the budget check happens before
748    /// `write_to` runs, so on `Err` nothing is written to `buf`.
749    ///
750    /// Returns the encoded body length on success (excludes any length prefix
751    /// you add for framing) — useful for metrics or frame sizing. Note that
752    /// this return type is `u32`, unlike `try_encode`'s `()`. `max_bytes` is
753    /// also `u32`; callers with a `usize` budget can cast with
754    /// `u32::try_from(budget).unwrap_or(u32::MAX)`.
755    ///
756    /// # Errors
757    ///
758    /// - [`EncodeError::MessageTooLarge`](crate::EncodeError::MessageTooLarge)
759    ///   if the encoded size exceeds the 2 GiB protobuf limit
760    ///   ([`MAX_MESSAGE_BYTES`](crate::MAX_MESSAGE_BYTES)).
761    ///   `MessageTooLarge` takes precedence if both limits are exceeded.
762    /// - [`EncodeError::ExceedsBudget`](crate::EncodeError::ExceedsBudget)
763    ///   if the encoded size is within the protobuf limit but exceeds
764    ///   `max_bytes`.
765    fn try_encode_bounded(
766        &self,
767        max_bytes: u32,
768        buf: &mut impl EncodeSink,
769    ) -> Result<u32, crate::EncodeError> {
770        let mut cache = crate::SizeCache::new();
771        self.try_encode_bounded_with_cache(max_bytes, &mut cache, buf)
772    }
773
774    /// Like [`try_encode_bounded`](Self::try_encode_bounded) but reuses an
775    /// existing [`SizeCache`](crate::SizeCache), clearing it first.
776    ///
777    /// Prefer
778    /// [`SizeCachePool::try_encode_view_bounded`](crate::SizeCachePool::try_encode_view_bounded)
779    /// for hot-loop use — the pool amortizes the cache's spill allocation.
780    ///
781    /// # Errors
782    ///
783    /// Same as [`try_encode_bounded`](Self::try_encode_bounded).
784    fn try_encode_bounded_with_cache(
785        &self,
786        max_bytes: u32,
787        cache: &mut crate::SizeCache,
788        buf: &mut impl EncodeSink,
789    ) -> Result<u32, crate::EncodeError> {
790        cache.clear();
791        let len = crate::message::checked_encode_size(self.compute_size(cache))?;
792        if len > max_bytes {
793            return Err(crate::EncodeError::ExceedsBudget { len, max_bytes });
794        }
795        self.write_to(cache, buf);
796        Ok(len)
797    }
798
799    /// Compute the encoded byte size of this view.
800    ///
801    /// Walks the view tree, discarding the intermediate
802    /// [`SizeCache`](crate::SizeCache). If you also intend to encode,
803    /// prefer [`encode`](Self::encode) or [`encode_to_vec`](Self::encode_to_vec)
804    /// — they do a single size pass and reuse the cache for the write.
805    ///
806    /// # Panics
807    ///
808    /// Panics if the encoded size exceeds the 2 GiB protobuf limit
809    /// ([`MAX_MESSAGE_BYTES`](crate::MAX_MESSAGE_BYTES)) — see
810    /// [`try_encoded_len`](Self::try_encoded_len) for the error-returning
811    /// variant.
812    #[inline]
813    #[must_use]
814    fn encoded_len(&self) -> u32 {
815        self.try_encoded_len()
816            .unwrap_or_else(|_| crate::message::encode_size_overflow())
817    }
818
819    /// Compute the encoded byte size, returning an error instead of
820    /// panicking if it exceeds the 2 GiB protobuf limit
821    /// ([`MAX_MESSAGE_BYTES`](crate::MAX_MESSAGE_BYTES)).
822    ///
823    /// # Errors
824    ///
825    /// Returns [`EncodeError::MessageTooLarge`](crate::EncodeError::MessageTooLarge)
826    /// if the encoded size exceeds the limit.
827    fn try_encoded_len(&self) -> Result<u32, crate::EncodeError> {
828        crate::message::checked_encode_size(self.compute_size(&mut crate::SizeCache::new()))
829    }
830
831    /// Encode this view as a length-delimited byte sequence.
832    ///
833    /// # Panics
834    ///
835    /// Panics if the encoded size exceeds the 2 GiB protobuf limit
836    /// ([`MAX_MESSAGE_BYTES`](crate::MAX_MESSAGE_BYTES)); the check runs
837    /// before the length prefix is written, so nothing reaches `buf` on
838    /// failure. See
839    /// [`try_encode_length_delimited`](Self::try_encode_length_delimited)
840    /// for the error-returning variant.
841    #[inline]
842    fn encode_length_delimited(&self, buf: &mut impl EncodeSink) {
843        self.try_encode_length_delimited(buf)
844            .unwrap_or_else(|_| crate::message::encode_size_overflow())
845    }
846
847    /// Encode as a length-delimited byte sequence, returning an error
848    /// instead of panicking if the encoded size exceeds the 2 GiB protobuf
849    /// limit ([`MAX_MESSAGE_BYTES`](crate::MAX_MESSAGE_BYTES)).
850    ///
851    /// On `Err`, nothing is written to `buf`.
852    ///
853    /// # Errors
854    ///
855    /// Returns [`EncodeError::MessageTooLarge`](crate::EncodeError::MessageTooLarge)
856    /// if the encoded size exceeds the limit.
857    fn try_encode_length_delimited(
858        &self,
859        buf: &mut impl EncodeSink,
860    ) -> Result<(), crate::EncodeError> {
861        let mut cache = crate::SizeCache::new();
862        let len = crate::message::checked_encode_size(self.compute_size(&mut cache))?;
863        crate::encoding::encode_varint(len as u64, buf);
864        self.write_to(&mut cache, buf);
865        Ok(())
866    }
867
868    /// Encode this view to a new `Vec<u8>`.
869    ///
870    /// # Panics
871    ///
872    /// Panics if the encoded size exceeds the 2 GiB protobuf limit
873    /// ([`MAX_MESSAGE_BYTES`](crate::MAX_MESSAGE_BYTES)) — see
874    /// [`try_encode_to_vec`](Self::try_encode_to_vec) for the
875    /// error-returning variant. In debug builds, also panics if a manual
876    /// implementation's `write_to` produces a different byte count than
877    /// its `compute_size` declared.
878    // Direct body rather than delegating to try_encode_to_vec — the
879    // Result<Vec<u8>> niche survives inlining and costs measurably in
880    // callers; see Message::encode_to_vec for the measurement.
881    #[inline]
882    #[must_use]
883    fn encode_to_vec(&self) -> alloc::vec::Vec<u8> {
884        let mut cache = crate::SizeCache::new();
885        let size = match crate::message::checked_encode_size(self.compute_size(&mut cache)) {
886            Ok(size) => size as usize,
887            Err(_) => crate::message::encode_size_overflow(),
888        };
889        let mut buf = alloc::vec::Vec::with_capacity(size);
890        self.write_to(&mut cache, &mut buf);
891        crate::message::debug_assert_two_pass(buf.len(), size);
892        buf
893    }
894
895    /// Encode to a new `Vec<u8>`, returning an error instead of panicking
896    /// if the encoded size exceeds the 2 GiB protobuf limit
897    /// ([`MAX_MESSAGE_BYTES`](crate::MAX_MESSAGE_BYTES)).
898    ///
899    /// # Errors
900    ///
901    /// Returns [`EncodeError::MessageTooLarge`](crate::EncodeError::MessageTooLarge)
902    /// if the encoded size exceeds the limit.
903    ///
904    /// # Panics
905    ///
906    /// In debug builds, panics if a manual implementation's `write_to`
907    /// produces a different byte count than its `compute_size` declared.
908    fn try_encode_to_vec(&self) -> Result<alloc::vec::Vec<u8>, crate::EncodeError> {
909        let mut cache = crate::SizeCache::new();
910        let size = crate::message::checked_encode_size(self.compute_size(&mut cache))? as usize;
911        let mut buf = alloc::vec::Vec::with_capacity(size);
912        self.write_to(&mut cache, &mut buf);
913        crate::message::debug_assert_two_pass(buf.len(), size);
914        Ok(buf)
915    }
916
917    /// Encode this view to a new [`bytes::Bytes`].
918    ///
919    /// # Panics
920    ///
921    /// Panics if the encoded size exceeds the 2 GiB protobuf limit
922    /// ([`MAX_MESSAGE_BYTES`](crate::MAX_MESSAGE_BYTES)) — see
923    /// [`try_encode_to_bytes`](Self::try_encode_to_bytes) for the
924    /// error-returning variant. In debug builds, also panics if a manual
925    /// implementation's `write_to` produces a different byte count than
926    /// its `compute_size` declared.
927    // Direct body — see Message::encode_to_vec for why the fat-payload
928    // entry points do not delegate to their try_ twins.
929    #[inline]
930    #[must_use]
931    fn encode_to_bytes(&self) -> Bytes {
932        let mut cache = crate::SizeCache::new();
933        let size = match crate::message::checked_encode_size(self.compute_size(&mut cache)) {
934            Ok(size) => size as usize,
935            Err(_) => crate::message::encode_size_overflow(),
936        };
937        let mut buf = bytes::BytesMut::with_capacity(size);
938        self.write_to(&mut cache, &mut buf);
939        crate::message::debug_assert_two_pass(buf.len(), size);
940        buf.freeze()
941    }
942
943    /// Encode to a new [`bytes::Bytes`], returning an error instead of
944    /// panicking if the encoded size exceeds the 2 GiB protobuf limit
945    /// ([`MAX_MESSAGE_BYTES`](crate::MAX_MESSAGE_BYTES)).
946    ///
947    /// # Errors
948    ///
949    /// Returns [`EncodeError::MessageTooLarge`](crate::EncodeError::MessageTooLarge)
950    /// if the encoded size exceeds the limit.
951    ///
952    /// # Panics
953    ///
954    /// In debug builds, panics if a manual implementation's `write_to`
955    /// produces a different byte count than its `compute_size` declared.
956    fn try_encode_to_bytes(&self) -> Result<Bytes, crate::EncodeError> {
957        let mut cache = crate::SizeCache::new();
958        let size = crate::message::checked_encode_size(self.compute_size(&mut cache))? as usize;
959        let mut buf = bytes::BytesMut::with_capacity(size);
960        self.write_to(&mut cache, &mut buf);
961        crate::message::debug_assert_two_pass(buf.len(), size);
962        Ok(buf.freeze())
963    }
964}
965
966/// Provides access to a lazily-initialized default view instance.
967///
968/// View types implement this trait so that [`MessageFieldView`] can
969/// dereference to a default when unset, just as [`MessageField`](crate::MessageField)
970/// does for owned types via [`DefaultInstance`](crate::DefaultInstance).
971///
972/// Generated view types like `FooView<'a>` contain only covariant borrows
973/// (`&'a str`, `&'a [u8]`, etc.). A default view holds only `'static` data
974/// (`""`, `&[]`, `0`), so an implementation stores a single
975/// `&'static FooView<'static>` and returns it at the caller's lifetime via
976/// ordinary covariant subtyping — the compiler verifies covariance at the
977/// `impl` site, so no `unsafe` is required.
978///
979/// # Recommended implementation
980///
981/// The pattern codegen uses (and the recommended pattern for hand-written
982/// view types) stores the instance in a static
983/// [`once_cell::race::OnceBox`] (re-exported as
984/// `::buffa::__private::OnceBox`):
985///
986/// ```rust,ignore
987/// impl<'v> DefaultViewInstance for MyView<'v> {
988///     fn default_view_instance<'a>() -> &'a Self
989///     where
990///         Self: 'a,
991///     {
992///         static VALUE: ::buffa::__private::OnceBox<MyView<'static>>
993///             = ::buffa::__private::OnceBox::new();
994///         VALUE.get_or_init(|| Box::new(<MyView<'static>>::default()))
995///     }
996/// }
997/// ```
998///
999/// The return expression has type `&'static MyView<'static>`; the compiler
1000/// coerces it to `&'a MyView<'v>` iff `MyView` is covariant in `'v` —
1001/// non-covariant view types fail to compile here rather than risk an
1002/// unsound cast.
1003///
1004/// # Non-covariant types are rejected
1005///
1006/// A type that is invariant in its lifetime parameter cannot satisfy the
1007/// recommended pattern, because the `&'static T<'static> → &'a T<'v>`
1008/// coercion is refused:
1009///
1010/// ```compile_fail
1011/// # use core::marker::PhantomData;
1012/// // `fn(&'v ()) -> &'v ()` is invariant in 'v, making `Invariant<'v>` invariant.
1013/// struct Invariant<'v>(PhantomData<fn(&'v ()) -> &'v ()>);
1014/// static INST: Invariant<'static> = Invariant(PhantomData);
1015///
1016/// impl<'v> buffa::view::DefaultViewInstance for Invariant<'v> {
1017///     fn default_view_instance<'a>() -> &'a Self where Self: 'a {
1018///         // error: lifetime may not live long enough
1019///         //   note: requirement occurs because of the type `Invariant<'_>`,
1020///         //         which makes the generic argument `'_` invariant
1021///         &INST
1022///     }
1023/// }
1024/// ```
1025pub trait DefaultViewInstance {
1026    /// Return a reference to the single default view instance.
1027    ///
1028    /// The lifetime `'a` is caller-chosen up to `Self: 'a`, so a
1029    /// `FooView<'v>` can serve its `'static` default at any `'a ≤ 'v`.
1030    fn default_view_instance<'a>() -> &'a Self
1031    where
1032        Self: 'a;
1033}
1034
1035/// Implement [`DefaultViewInstance`] for a generated view type via a
1036/// lazily-initialized `OnceBox<FooView<'static>>` singleton.
1037///
1038/// Emitted by generated code (one invocation per view struct). The static
1039/// holds the `'static` instantiation; returning it at any shorter `'a` is
1040/// sound because view lifetimes are covariant.
1041///
1042/// ```rust,ignore
1043/// buffa::impl_default_view_instance!(MyMessageView);
1044/// ```
1045#[macro_export]
1046macro_rules! impl_default_view_instance {
1047    ($ty:ident) => {
1048        impl<'v> $crate::DefaultViewInstance for $ty<'v> {
1049            fn default_view_instance<'a>() -> &'a Self
1050            where
1051                Self: 'a,
1052            {
1053                static VALUE: $crate::__private::OnceBox<$ty<'static>> =
1054                    $crate::__private::OnceBox::new();
1055                VALUE.get_or_init(|| {
1056                    $crate::alloc::boxed::Box::new(
1057                        <$ty<'static> as ::core::default::Default>::default(),
1058                    )
1059                })
1060            }
1061        }
1062    };
1063}
1064
1065/// A borrowed view of an optional message field.
1066///
1067/// Analogous to [`MessageField<T>`](crate::MessageField) but for the view
1068/// layer. Like `MessageField`, the inner view is **boxed** — recursive
1069/// message types (`Foo { NestedMessage { corecursive: Foo } }`) would
1070/// otherwise have infinite size. The box is API-transparent: `Deref`
1071/// returns `&V`, and `set()` takes `V` by value.
1072///
1073/// When `V` implements [`DefaultViewInstance`], this type implements
1074/// [`Deref<Target = V>`](core::ops::Deref), returning a reference to a
1075/// static default instance when the field is unset — making view code
1076/// identical to owned code for field access:
1077///
1078/// ```rust,ignore
1079/// // Both work the same, regardless of whether `address` is set:
1080/// let city = owned_msg.address.city;    // MessageField<Address>
1081/// let city = view_msg.address.city;     // MessageFieldView<AddressView>
1082/// ```
1083///
1084/// The lifetime of the contained view type `V` (e.g. `AddressView<'a>`)
1085/// ties this to the input buffer — no separate lifetime parameter is
1086/// needed here.
1087#[derive(Clone, Debug)]
1088pub struct MessageFieldView<V> {
1089    inner: Option<alloc::boxed::Box<V>>,
1090}
1091
1092impl<V> MessageFieldView<V> {
1093    /// An unset field (the default).
1094    #[inline]
1095    pub const fn unset() -> Self {
1096        Self { inner: None }
1097    }
1098
1099    /// A set field with the given view value.
1100    #[inline]
1101    pub fn set(v: V) -> Self {
1102        Self {
1103            inner: Some(alloc::boxed::Box::new(v)),
1104        }
1105    }
1106
1107    /// Alias for [`set`](Self::set), mirroring owned
1108    /// [`MessageField::some`](crate::MessageField::some).
1109    #[inline]
1110    pub fn some(v: V) -> Self {
1111        Self::set(v)
1112    }
1113
1114    /// Returns `true` if the field has a value.
1115    #[inline]
1116    pub const fn is_set(&self) -> bool {
1117        self.inner.is_some()
1118    }
1119
1120    /// Returns `true` if the field has no value.
1121    #[inline]
1122    pub const fn is_unset(&self) -> bool {
1123        self.inner.is_none()
1124    }
1125
1126    /// Get a reference to the inner view, or `None` if unset.
1127    #[inline]
1128    pub fn as_option(&self) -> Option<&V> {
1129        self.inner.as_deref()
1130    }
1131
1132    /// Get a mutable reference to the inner view, or `None` if unset.
1133    ///
1134    /// Used by generated decode code to merge a second occurrence of a
1135    /// message field into an existing value (proto merge semantics).
1136    #[inline]
1137    pub fn as_mut(&mut self) -> Option<&mut V> {
1138        self.inner.as_deref_mut()
1139    }
1140}
1141
1142impl<'a, V: ViewEncode<'a>> MessageFieldView<V> {
1143    /// Forward to the inner view's [`compute_size`](ViewEncode::compute_size),
1144    /// or `0` if unset. Generated `compute_size` calls this for nested-message
1145    /// fields, mirroring [`MessageField`](crate::MessageField) on the owned side.
1146    #[inline]
1147    pub fn compute_size(&self, cache: &mut crate::SizeCache) -> u32 {
1148        self.inner.as_deref().map_or(0, |v| v.compute_size(cache))
1149    }
1150
1151    /// Forward to the inner view's [`write_to`](ViewEncode::write_to);
1152    /// no-op if unset.
1153    #[inline]
1154    pub fn write_to(&self, cache: &mut crate::SizeCache, buf: &mut impl EncodeSink) {
1155        if let Some(v) = self.inner.as_deref() {
1156            v.write_to(cache, buf);
1157        }
1158    }
1159}
1160
1161impl<V> Default for MessageFieldView<V> {
1162    #[inline]
1163    fn default() -> Self {
1164        Self::unset()
1165    }
1166}
1167
1168impl<V> From<V> for MessageFieldView<V> {
1169    #[inline]
1170    fn from(v: V) -> Self {
1171        Self::set(v)
1172    }
1173}
1174
1175impl<V: DefaultViewInstance> core::ops::Deref for MessageFieldView<V> {
1176    type Target = V;
1177
1178    #[inline]
1179    fn deref(&self) -> &V {
1180        self.inner
1181            .as_deref()
1182            .unwrap_or_else(V::default_view_instance)
1183    }
1184}
1185
1186/// Wire-equivalent equality: `Unset` equals `Set(v)` when `v` equals the
1187/// default instance.
1188///
1189/// This matches [`MessageField::eq`](crate::MessageField) on the owned side,
1190/// so `view_a == view_b` agrees with
1191/// `view_a.to_owned_message() == view_b.to_owned_message()`.
1192///
1193/// The comparison against the default routes through the
1194/// [`Deref`](core::ops::Deref) impl.
1195impl<V: PartialEq + DefaultViewInstance> PartialEq for MessageFieldView<V> {
1196    fn eq(&self, other: &Self) -> bool {
1197        match (&self.inner, &other.inner) {
1198            // Short-circuit: two unset fields are equal regardless of whether
1199            // V::PartialEq is reflexive (e.g. a view containing an f64 NaN).
1200            (None, None) => true,
1201            // At least one side is set. Deref handles None → default.
1202            _ => {
1203                <Self as core::ops::Deref>::deref(self) == <Self as core::ops::Deref>::deref(other)
1204            }
1205        }
1206    }
1207}
1208
1209impl<V: Eq + DefaultViewInstance> Eq for MessageFieldView<V> {}
1210
1211// ---------------------------------------------------------------------------
1212// Lazy views (generated under the `lazy_views` codegen option)
1213// ---------------------------------------------------------------------------
1214
1215/// The trait implemented by generated lazy view types (`FooLazyView<'a>`).
1216///
1217/// Lazy views are a separate, additive type family generated alongside the
1218/// eager `FooView` family under the `lazy_views` codegen option. Where
1219/// [`MessageView`]'s contract is "decode succeeded ⇒ the whole tree was
1220/// validated", a lazy view's [`decode_lazy`](Self::decode_lazy) performs a
1221/// single non-recursive scan over the message's own fields: scalar, string,
1222/// and bytes fields are borrowed exactly as in the eager view, while nested
1223/// and repeated message fields are *recorded* as undecoded byte ranges (see
1224/// [`LazyMessageFieldView`] / [`LazyRepeatedView`]) and decoded only on
1225/// access. Deferred validation is therefore visible in the type and trait
1226/// bound — generic code over `MessageView` never silently inherits it.
1227///
1228/// Generated lazy-view structs may gain fields across releases; see the
1229/// [struct evolution policy on `Message`](crate::Message#struct-evolution-policy).
1230pub trait LazyMessageView<'a>: Sized {
1231    /// The corresponding owned message type.
1232    type Owned: crate::Message;
1233
1234    /// Decode a lazy view from `buf`: one scan over the message's own
1235    /// fields, deferring nested message fields.
1236    ///
1237    /// # Errors
1238    ///
1239    /// Returns [`DecodeError`] if the message's *own* fields are malformed,
1240    /// or [`DecodeError::ElementMemoryLimitExceeded`] if recording its
1241    /// repeated elements exceeds the default element-memory budget — the
1242    /// `Vec` of deferred byte ranges is real memory even though the elements
1243    /// themselves are not decoded yet. Deferred sub-message bytes are
1244    /// **not** validated here; they surface errors on access.
1245    fn decode_lazy(buf: &'a [u8]) -> Result<Self, DecodeError>;
1246
1247    /// Decode a lazy view under custom decode limits.
1248    ///
1249    /// Used by [`DecodeOptions::decode_lazy_view`](crate::DecodeOptions::decode_lazy_view).
1250    /// The budgets remaining at each deferred field's position are recorded
1251    /// and charged when that field is accessed, so custom limits flow through
1252    /// deferred decoding. The default implementation delegates to
1253    /// [`decode_lazy`](Self::decode_lazy) and **ignores the context**;
1254    /// generated code always overrides it.
1255    ///
1256    /// # Errors
1257    ///
1258    /// Same contract as [`decode_lazy`](Self::decode_lazy), plus
1259    /// [`DecodeError::RecursionLimitExceeded`],
1260    /// [`DecodeError::UnknownFieldLimitExceeded`], or
1261    /// [`DecodeError::ElementMemoryLimitExceeded`] when `ctx`'s budgets are
1262    /// exhausted by the message's own fields.
1263    fn decode_lazy_with_ctx(
1264        buf: &'a [u8],
1265        ctx: crate::DecodeContext<'_>,
1266    ) -> Result<Self, DecodeError> {
1267        let _ = ctx;
1268        Self::decode_lazy(buf)
1269    }
1270
1271    /// Merge fields decoded from `buf` into this view (proto merge
1272    /// semantics: singular scalars last-wins, repeated append, deferred
1273    /// message fragments accumulate).
1274    ///
1275    /// Used by [`LazyMessageFieldView::get`] to reassemble a field whose
1276    /// value was split across multiple wire occurrences — application code
1277    /// rarely calls this directly.
1278    ///
1279    /// # Errors
1280    ///
1281    /// Same contract as [`decode_lazy_with_ctx`](Self::decode_lazy_with_ctx).
1282    fn merge_lazy(
1283        &mut self,
1284        buf: &'a [u8],
1285        ctx: crate::DecodeContext<'_>,
1286    ) -> Result<(), DecodeError>;
1287
1288    /// Convert this view to the owned message type.
1289    ///
1290    /// This decodes every deferred sub-message, so it is where deferred
1291    /// validation errors surface. Each deferred subtree decodes under its
1292    /// own replayed unknown-field allowance (see
1293    /// [`LazyMessageFieldView::get`]), so the conversion's total
1294    /// unknown-field records are bounded per subtree, not globally as in an
1295    /// eager decode.
1296    ///
1297    /// # Errors
1298    ///
1299    /// Returns the [`DecodeError`] that accessing a malformed or
1300    /// over-budget deferred field would have reported. Unlike
1301    /// [`MessageView::to_owned_message`], this conversion can genuinely
1302    /// fail for a wire-decoded lazy view: deferred subtrees were never
1303    /// validated (or charged against the unknown-field allowance) at
1304    /// decode time, so their errors surface here.
1305    fn to_owned_message(&self) -> Result<Self::Owned, DecodeError>;
1306}
1307
1308/// Fragments of one singular message field. `Many` only arises when an
1309/// encoder split the field across occurrences, keeping the common
1310/// single-occurrence path allocation-free.
1311#[derive(Clone)]
1312enum LazyFragments<'a> {
1313    None,
1314    One(&'a [u8]),
1315    Many(alloc::vec::Vec<&'a [u8]>),
1316}
1317
1318/// A deferred view of a singular message field on a lazy view.
1319///
1320/// Unlike [`MessageFieldView`] — which eagerly decodes (and boxes) the
1321/// sub-message during decode — this stores only the field's undecoded wire
1322/// bytes and decodes a fresh `V` on each [`get`](Self::get), so decoding the
1323/// enclosing message does not allocate or recurse into sub-messages the
1324/// caller never reads.
1325///
1326/// `get` returns a freshly-decoded view each call (views are thin borrows,
1327/// so this is cheap) and does not cache — bind the result when reading
1328/// several fields.
1329///
1330/// # Merge semantics
1331///
1332/// A singular message field may legally appear more than once on the wire;
1333/// decoders must merge the occurrences. This type stores each occurrence's
1334/// bytes as a separate fragment and [`get`](Self::get) replays them in order
1335/// (decode the first, [`LazyMessageView::merge_lazy`] the rest), so the
1336/// result matches the eager and owned decoders.
1337///
1338/// # Deferred validation and budgets
1339///
1340/// The fragment bytes are *not* validated when the enclosing view is
1341/// decoded; a malformed sub-message surfaces as a [`DecodeError`] from
1342/// [`get`](Self::get). The recursion budget, unknown-field allowance, and
1343/// element-memory budget remaining when the field was recorded are stored
1344/// alongside the fragments,
1345/// and each access replays them as a fresh per-subtree budget (see
1346/// [`get`](Self::get) for the approximation this implies). Deep lazy chains
1347/// fail with [`DecodeError::RecursionLimitExceeded`] at the same boundary as
1348/// the eager decoder, and custom limits passed to the enclosing
1349/// [`decode_lazy_with_ctx`](LazyMessageView::decode_lazy_with_ctx) flow
1350/// through.
1351///
1352/// # Re-encoding
1353///
1354/// `ViewEncode` on the enclosing lazy view replays the recorded fragments
1355/// byte-for-byte **without validating them** — re-encoding a never-accessed
1356/// malformed field round-trips its bytes silently.
1357pub struct LazyMessageFieldView<'a, V> {
1358    raw: LazyFragments<'a>,
1359    depth: u32,
1360    allowance: usize,
1361    elem_allowance: usize,
1362    _marker: core::marker::PhantomData<fn() -> V>,
1363}
1364
1365impl<'a, V> LazyMessageFieldView<'a, V> {
1366    /// An unset field (the default).
1367    #[inline]
1368    pub const fn unset() -> Self {
1369        Self {
1370            raw: LazyFragments::None,
1371            // Sentinels: the first `push_fragment` lowers these to its
1372            // recorded budgets, so custom limits above the defaults aren't
1373            // clamped.
1374            depth: u32::MAX,
1375            allowance: usize::MAX,
1376            elem_allowance: usize::MAX,
1377            _marker: core::marker::PhantomData,
1378        }
1379    }
1380
1381    /// A set field carrying the sub-message's undecoded wire bytes, with the
1382    /// default recursion, unknown-field, and element-memory budgets for
1383    /// access.
1384    #[inline]
1385    pub const fn from_bytes(raw: &'a [u8]) -> Self {
1386        Self {
1387            raw: LazyFragments::One(raw),
1388            depth: crate::RECURSION_LIMIT,
1389            allowance: crate::DEFAULT_UNKNOWN_FIELD_LIMIT,
1390            elem_allowance: crate::DEFAULT_ELEMENT_MEMORY_LIMIT,
1391            _marker: core::marker::PhantomData,
1392        }
1393    }
1394
1395    /// Append one wire occurrence of the field (used by generated
1396    /// `decode_lazy`). Fragments accumulate in wire order; [`get`](Self::get)
1397    /// merges them. `ctx` carries the recursion budget and unknown-field
1398    /// allowance remaining at the record site; the smallest pushed budgets
1399    /// are charged on access.
1400    #[doc(hidden)]
1401    #[inline]
1402    pub fn push_fragment(&mut self, raw: &'a [u8], ctx: crate::DecodeContext<'_>) {
1403        self.depth = self.depth.min(ctx.depth());
1404        self.allowance = self.allowance.min(ctx.remaining_unknown_fields());
1405        if let Some(remaining) = ctx.remaining_element_memory() {
1406            self.elem_allowance = self.elem_allowance.min(remaining);
1407        }
1408        self.raw = match core::mem::replace(&mut self.raw, LazyFragments::None) {
1409            LazyFragments::None => LazyFragments::One(raw),
1410            LazyFragments::One(first) => LazyFragments::Many(alloc::vec![first, raw]),
1411            LazyFragments::Many(mut frags) => {
1412                frags.push(raw);
1413                LazyFragments::Many(frags)
1414            }
1415        };
1416    }
1417
1418    /// Whether the field is present.
1419    #[inline]
1420    pub const fn is_set(&self) -> bool {
1421        !matches!(self.raw, LazyFragments::None)
1422    }
1423
1424    /// Whether the field has no value.
1425    #[inline]
1426    pub const fn is_unset(&self) -> bool {
1427        matches!(self.raw, LazyFragments::None)
1428    }
1429
1430    /// The undecoded wire fragments, in wire order (empty if unset).
1431    ///
1432    /// A singular message field that appeared exactly once on the wire — the
1433    /// common case — yields one fragment. Encoders that split the field
1434    /// across multiple occurrences yield one fragment per occurrence;
1435    /// [`get`](Self::get) merges them per proto semantics.
1436    #[inline]
1437    pub fn fragments(&self) -> &[&'a [u8]] {
1438        match &self.raw {
1439            LazyFragments::None => &[],
1440            LazyFragments::One(raw) => core::slice::from_ref(raw),
1441            LazyFragments::Many(frags) => frags,
1442        }
1443    }
1444}
1445
1446impl<'a, V: LazyMessageView<'a>> LazyMessageFieldView<'a, V> {
1447    /// Decode and return the sub-message view, or `None` if unset.
1448    ///
1449    /// Multiple wire fragments are merged per proto semantics (see the type
1450    /// docs). The view is re-decoded on every call; there is no cache — bind
1451    /// the result when reading several fields. Note the shape difference
1452    /// from [`LazyRepeatedView::get`], which returns `Option<Result<V, _>>`.
1453    ///
1454    /// Each access rebuilds a fresh decode context from the budgets recorded
1455    /// at decode time, so every deferred subtree independently gets the full
1456    /// recorded unknown-field allowance and element-memory budget rather than
1457    /// sharing one pool with its siblings (the original decode call's shared
1458    /// budgets are gone by access time). Both are therefore *per-subtree*
1459    /// bounds on the lazy path, not the global decode-time caps the eager
1460    /// decoder enforces: a full traversal can materialize records
1461    /// proportional to input size, where eager
1462    /// [`decode_view`](crate::DecodeOptions::decode_view) rejects such input
1463    /// up front. Prefer the eager path for untrusted input if that global
1464    /// bound matters.
1465    ///
1466    /// # Errors
1467    ///
1468    /// Returns [`DecodeError`] if the deferred bytes are not a valid
1469    /// encoding of `V` — validation happens here, not when the enclosing
1470    /// view was decoded — [`DecodeError::RecursionLimitExceeded`] when the
1471    /// recursion budget recorded at decode time is exhausted,
1472    /// [`DecodeError::UnknownFieldLimitExceeded`] when the unknown-field
1473    /// allowance is, or [`DecodeError::ElementMemoryLimitExceeded`] when the
1474    /// element-memory budget is.
1475    #[inline]
1476    pub fn get(&self) -> Result<Option<V>, DecodeError> {
1477        let allowance = core::cell::Cell::new(self.allowance);
1478        let elem = core::cell::Cell::new(self.elem_allowance);
1479        let ctx = crate::DecodeContext::new(self.depth, &allowance).with_element_memory(&elem);
1480        match &self.raw {
1481            LazyFragments::None => Ok(None),
1482            LazyFragments::One(raw) => V::decode_lazy_with_ctx(raw, ctx).map(Some),
1483            LazyFragments::Many(frags) => {
1484                // `Many` always holds ≥ 2 fragments (see `push_fragment`);
1485                // the guard is belt-and-suspenders.
1486                let mut iter = frags.iter();
1487                let Some(first) = iter.next() else {
1488                    return Ok(None);
1489                };
1490                let mut view = V::decode_lazy_with_ctx(first, ctx)?;
1491                for frag in iter {
1492                    view.merge_lazy(frag, ctx)?;
1493                }
1494                Ok(Some(view))
1495            }
1496        }
1497    }
1498
1499    /// Like [`get`](Self::get), but an unset field decodes to the default
1500    /// view — the lazy analogue of [`MessageFieldView`]'s deref-to-default,
1501    /// for the common read path:
1502    ///
1503    /// ```rust,ignore
1504    /// let city = view.address.get_or_default()?.city;
1505    /// ```
1506    ///
1507    /// # Errors
1508    ///
1509    /// Same as [`get`](Self::get).
1510    #[inline]
1511    pub fn get_or_default(&self) -> Result<V, DecodeError>
1512    where
1513        V: Default,
1514    {
1515        Ok(self.get()?.unwrap_or_default())
1516    }
1517}
1518
1519impl<V> Clone for LazyMessageFieldView<'_, V> {
1520    #[inline]
1521    fn clone(&self) -> Self {
1522        Self {
1523            raw: self.raw.clone(),
1524            depth: self.depth,
1525            allowance: self.allowance,
1526            elem_allowance: self.elem_allowance,
1527            _marker: core::marker::PhantomData,
1528        }
1529    }
1530}
1531impl<V> Default for LazyMessageFieldView<'_, V> {
1532    #[inline]
1533    fn default() -> Self {
1534        Self::unset()
1535    }
1536}
1537impl<V> core::fmt::Debug for LazyMessageFieldView<'_, V> {
1538    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1539        f.debug_struct("LazyMessageFieldView")
1540            .field("is_set", &self.is_set())
1541            .field("fragments", &self.fragments().len())
1542            .finish()
1543    }
1544}
1545
1546/// A deferred view of a repeated message field on a lazy view.
1547///
1548/// Holds the wire byte-slice of each element (cheap pointers) and decodes a
1549/// fresh element view on access ([`get`](Self::get)) or iteration
1550/// ([`iter`](Self::iter)), instead of eagerly decoding every element into a
1551/// `Vec` like [`RepeatedView`].
1552///
1553/// Element bytes are *not* validated when the enclosing view is decoded; a
1554/// malformed element surfaces as a [`DecodeError`] from `get`/`iter`. Unlike
1555/// [`RepeatedView`], this type is not slice-backed: there is no `Deref` or
1556/// indexing, use `get`/`iter`/`len`. Budgets and re-encoding behave as on
1557/// [`LazyMessageFieldView`].
1558pub struct LazyRepeatedView<'a, V> {
1559    elements: alloc::vec::Vec<&'a [u8]>,
1560    depth: u32,
1561    allowance: usize,
1562    elem_allowance: usize,
1563    _marker: core::marker::PhantomData<fn() -> V>,
1564}
1565
1566impl<'a, V> LazyRepeatedView<'a, V> {
1567    /// An empty repeated field.
1568    #[inline]
1569    pub fn new() -> Self {
1570        Self {
1571            elements: alloc::vec::Vec::new(),
1572            // Sentinels — see `LazyMessageFieldView::unset`.
1573            depth: u32::MAX,
1574            allowance: usize::MAX,
1575            elem_allowance: usize::MAX,
1576            _marker: core::marker::PhantomData,
1577        }
1578    }
1579
1580    /// Number of elements.
1581    #[inline]
1582    pub fn len(&self) -> usize {
1583        self.elements.len()
1584    }
1585
1586    /// Whether the field has no elements.
1587    #[inline]
1588    pub fn is_empty(&self) -> bool {
1589        self.elements.is_empty()
1590    }
1591
1592    /// The undecoded wire bytes of each element, in wire order.
1593    #[inline]
1594    pub fn raw_elements(&self) -> &[&'a [u8]] {
1595        &self.elements
1596    }
1597
1598    /// Append an element's undecoded bytes (used by generated `decode_lazy`).
1599    /// `ctx` carries the recursion budget, unknown-field allowance, and
1600    /// element-memory budget remaining at the record site; the smallest
1601    /// pushed budgets are charged on access.
1602    #[doc(hidden)]
1603    #[inline]
1604    pub fn push_bytes(&mut self, raw: &'a [u8], ctx: crate::DecodeContext<'_>) {
1605        self.depth = self.depth.min(ctx.depth());
1606        self.allowance = self.allowance.min(ctx.remaining_unknown_fields());
1607        if let Some(remaining) = ctx.remaining_element_memory() {
1608            self.elem_allowance = self.elem_allowance.min(remaining);
1609        }
1610        self.elements.push(raw);
1611    }
1612}
1613
1614/// Decode one deferred element under a fresh context carrying the budgets
1615/// recorded at decode time. Each access decodes independently, so each gets
1616/// the full recorded allowance — a per-subtree bound, not the eager
1617/// decoder's shared global pool (see [`LazyMessageFieldView::get`]).
1618#[inline]
1619fn decode_deferred<'a, V: LazyMessageView<'a>>(
1620    raw: &'a [u8],
1621    depth: u32,
1622    allowance: usize,
1623    elem_allowance: usize,
1624) -> Result<V, DecodeError> {
1625    let cell = core::cell::Cell::new(allowance);
1626    let elem = core::cell::Cell::new(elem_allowance);
1627    V::decode_lazy_with_ctx(
1628        raw,
1629        crate::DecodeContext::new(depth, &cell).with_element_memory(&elem),
1630    )
1631}
1632
1633impl<'a, V: LazyMessageView<'a>> LazyRepeatedView<'a, V> {
1634    /// Decode the element at `index`, or `None` if out of range.
1635    ///
1636    /// Re-decodes on every call (no cache) — bind the result when reading
1637    /// multiple fields, and avoid calling it inside a tight loop over the
1638    /// same index. Note the shape difference from
1639    /// [`LazyMessageFieldView::get`], which returns `Result<Option<V>, _>`.
1640    #[inline]
1641    pub fn get(&self, index: usize) -> Option<Result<V, DecodeError>> {
1642        self.elements
1643            .get(index)
1644            .map(|b| decode_deferred(b, self.depth, self.allowance, self.elem_allowance))
1645    }
1646
1647    /// Like [`get`](Self::get) with the layers flipped to match
1648    /// [`LazyMessageFieldView::get`]'s `Result<Option<_>, _>` shape:
1649    /// out-of-range yields `Ok(None)`.
1650    ///
1651    /// # Errors
1652    ///
1653    /// Same as [`get`](Self::get).
1654    #[inline]
1655    pub fn try_get(&self, index: usize) -> Result<Option<V>, DecodeError> {
1656        self.get(index).transpose()
1657    }
1658
1659    /// Iterate the elements, decoding each on the fly.
1660    ///
1661    /// Yields `Result<V, DecodeError>` — element bytes are validated here,
1662    /// not when the enclosing view was decoded. Each pass over the iterator
1663    /// re-decodes the elements (no cache).
1664    #[inline]
1665    pub fn iter(&self) -> LazyRepeatedIter<'_, 'a, V> {
1666        LazyRepeatedIter {
1667            inner: self.elements.iter(),
1668            depth: self.depth,
1669            allowance: self.allowance,
1670            elem_allowance: self.elem_allowance,
1671            _marker: core::marker::PhantomData,
1672        }
1673    }
1674}
1675
1676impl<'s, 'a, V: LazyMessageView<'a>> IntoIterator for &'s LazyRepeatedView<'a, V> {
1677    type Item = Result<V, DecodeError>;
1678    type IntoIter = LazyRepeatedIter<'s, 'a, V>;
1679
1680    #[inline]
1681    fn into_iter(self) -> Self::IntoIter {
1682        self.iter()
1683    }
1684}
1685
1686/// Iterator over a [`LazyRepeatedView`], decoding each element on `next`.
1687#[derive(Clone, Debug)]
1688pub struct LazyRepeatedIter<'s, 'a, V> {
1689    inner: core::slice::Iter<'s, &'a [u8]>,
1690    depth: u32,
1691    allowance: usize,
1692    elem_allowance: usize,
1693    _marker: core::marker::PhantomData<fn() -> V>,
1694}
1695
1696impl<'a, V: LazyMessageView<'a>> Iterator for LazyRepeatedIter<'_, 'a, V> {
1697    type Item = Result<V, DecodeError>;
1698
1699    #[inline]
1700    fn next(&mut self) -> Option<Self::Item> {
1701        self.inner
1702            .next()
1703            .map(|b| decode_deferred(b, self.depth, self.allowance, self.elem_allowance))
1704    }
1705
1706    #[inline]
1707    fn size_hint(&self) -> (usize, Option<usize>) {
1708        self.inner.size_hint()
1709    }
1710}
1711
1712impl<'a, V: LazyMessageView<'a>> DoubleEndedIterator for LazyRepeatedIter<'_, 'a, V> {
1713    #[inline]
1714    fn next_back(&mut self) -> Option<Self::Item> {
1715        self.inner
1716            .next_back()
1717            .map(|b| decode_deferred(b, self.depth, self.allowance, self.elem_allowance))
1718    }
1719}
1720
1721impl<'a, V: LazyMessageView<'a>> ExactSizeIterator for LazyRepeatedIter<'_, 'a, V> {}
1722
1723impl<V> Clone for LazyRepeatedView<'_, V> {
1724    #[inline]
1725    fn clone(&self) -> Self {
1726        Self {
1727            elements: self.elements.clone(),
1728            depth: self.depth,
1729            allowance: self.allowance,
1730            elem_allowance: self.elem_allowance,
1731            _marker: core::marker::PhantomData,
1732        }
1733    }
1734}
1735impl<V> Default for LazyRepeatedView<'_, V> {
1736    #[inline]
1737    fn default() -> Self {
1738        Self::new()
1739    }
1740}
1741impl<V> core::fmt::Debug for LazyRepeatedView<'_, V> {
1742    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1743        f.debug_struct("LazyRepeatedView")
1744            .field("len", &self.len())
1745            .finish()
1746    }
1747}
1748
1749/// A borrowed view of a repeated field.
1750///
1751/// For scalar repeated fields, this is backed by a decoded `Vec` (scalars
1752/// can't be zero-copy because they require varint decoding). For string and
1753/// bytes repeated fields, elements borrow from the input buffer.
1754#[derive(Clone, Debug, PartialEq, Eq)]
1755pub struct RepeatedView<'a, T> {
1756    elements: alloc::vec::Vec<T>,
1757    _marker: core::marker::PhantomData<&'a ()>,
1758}
1759
1760impl<'a, T> RepeatedView<'a, T> {
1761    /// Create from a vec of decoded elements.
1762    pub fn new(elements: alloc::vec::Vec<T>) -> Self {
1763        Self {
1764            elements,
1765            _marker: core::marker::PhantomData,
1766        }
1767    }
1768
1769    /// Returns the number of elements.
1770    pub fn len(&self) -> usize {
1771        self.elements.len()
1772    }
1773
1774    /// Returns `true` if the repeated field contains no elements.
1775    pub fn is_empty(&self) -> bool {
1776        self.elements.is_empty()
1777    }
1778
1779    /// Append an element (used by generated `decode_view` code).
1780    #[doc(hidden)]
1781    pub fn push(&mut self, elem: T) {
1782        self.elements.push(elem);
1783    }
1784
1785    /// Reserve capacity for at least `additional` more elements (used by
1786    /// generated `decode_view` code as a pre-allocation hint for packed
1787    /// repeated scalars). For varint elements the hint is an upper bound
1788    /// (every element occupies at least one byte on the wire); for fixed-
1789    /// size elements it is the exact remaining element count.
1790    #[doc(hidden)]
1791    pub fn reserve(&mut self, additional: usize) {
1792        self.elements.reserve(additional);
1793    }
1794
1795    /// Mutable access to the backing vec (used by generated `decode_view`
1796    /// code to decode packed fixed-width payloads in one bulk call).
1797    #[doc(hidden)]
1798    pub fn as_mut_vec(&mut self) -> &mut alloc::vec::Vec<T> {
1799        &mut self.elements
1800    }
1801
1802    /// Returns an iterator over the elements.
1803    pub fn iter(&self) -> core::slice::Iter<'_, T> {
1804        self.elements.iter()
1805    }
1806}
1807
1808impl<'a, T> Default for RepeatedView<'a, T> {
1809    fn default() -> Self {
1810        Self {
1811            elements: alloc::vec::Vec::new(),
1812            _marker: core::marker::PhantomData,
1813        }
1814    }
1815}
1816
1817impl<'a, T> core::ops::Deref for RepeatedView<'a, T> {
1818    type Target = [T];
1819
1820    fn deref(&self) -> &[T] {
1821        &self.elements
1822    }
1823}
1824
1825impl<'a, T> IntoIterator for RepeatedView<'a, T> {
1826    type Item = T;
1827    type IntoIter = alloc::vec::IntoIter<T>;
1828
1829    fn into_iter(self) -> Self::IntoIter {
1830        self.elements.into_iter()
1831    }
1832}
1833
1834impl<'b, 'a, T> IntoIterator for &'b RepeatedView<'a, T> {
1835    type Item = &'b T;
1836    type IntoIter = core::slice::Iter<'b, T>;
1837
1838    fn into_iter(self) -> Self::IntoIter {
1839        self.elements.iter()
1840    }
1841}
1842
1843impl<'a, T> From<alloc::vec::Vec<T>> for RepeatedView<'a, T> {
1844    fn from(elements: alloc::vec::Vec<T>) -> Self {
1845        Self::new(elements)
1846    }
1847}
1848
1849impl<'a, T> FromIterator<T> for RepeatedView<'a, T> {
1850    fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
1851        Self::new(iter.into_iter().collect())
1852    }
1853}
1854
1855/// A borrowed view of a map field.
1856///
1857/// Protobuf `map<K, V>` fields are encoded as repeated sub-messages, each
1858/// containing a key (field 1) and value (field 2). This type stores the
1859/// decoded entries in a `Vec<(K, V)>`, borrowing string and bytes keys/values
1860/// directly from the input buffer.
1861///
1862/// Lookup is O(n) linear scan, which is appropriate for the typically small
1863/// maps found in protobuf messages (metadata labels, headers, etc.).
1864/// If duplicate keys appear on the wire, [`get`](MapView::get) returns the
1865/// last occurrence (last-write-wins, per the protobuf spec). That rule is
1866/// about whole entries; *within* one entry, a repeated scalar key or value
1867/// also last-wins, while a repeated message value merges — the same as the
1868/// owned decoder.
1869///
1870/// For larger maps where O(1) lookup matters, collect into a `HashMap`:
1871///
1872/// ```ignore
1873/// use std::collections::HashMap;
1874/// let index: HashMap<&str, &str> = view.labels.into_iter().collect();
1875/// ```
1876///
1877/// Duplicate keys resolve last-write-wins in the collected map (matching
1878/// proto map semantics), since `HashMap::from_iter` keeps the last value.
1879///
1880/// # Allocation
1881///
1882/// Like [`RepeatedView`], the `Vec` backing store requires allocation.
1883/// The individual keys and values borrow from the input buffer where possible
1884/// (string keys as `&'a str`, bytes values as `&'a [u8]`).
1885#[derive(Clone, Debug, PartialEq, Eq)]
1886pub struct MapView<'a, K, V> {
1887    entries: alloc::vec::Vec<(K, V)>,
1888    _marker: core::marker::PhantomData<&'a ()>,
1889}
1890
1891impl<'a, K, V> MapView<'a, K, V> {
1892    /// Construct from a `Vec` of entries, for [`ViewEncode`] use.
1893    ///
1894    /// Duplicate keys are kept and all encoded — valid protobuf wire data
1895    /// (decoders apply last-write-wins). Mirrors [`RepeatedView::new`].
1896    pub fn new(entries: alloc::vec::Vec<(K, V)>) -> Self {
1897        Self {
1898            entries,
1899            _marker: core::marker::PhantomData,
1900        }
1901    }
1902
1903    /// Returns the number of entries (including duplicates).
1904    pub fn len(&self) -> usize {
1905        self.entries.len()
1906    }
1907
1908    /// Returns `true` if there are no entries.
1909    pub fn is_empty(&self) -> bool {
1910        self.entries.is_empty()
1911    }
1912
1913    /// Append a key-value pair (used by generated `decode_view` code).
1914    #[doc(hidden)]
1915    pub fn push(&mut self, key: K, value: V) {
1916        self.entries.push((key, value));
1917    }
1918
1919    /// Iterate over all entries in wire order.
1920    ///
1921    /// If duplicate keys exist, all occurrences are yielded.
1922    pub fn iter(&self) -> core::slice::Iter<'_, (K, V)> {
1923        self.entries.iter()
1924    }
1925
1926    /// Iterate over all keys in wire order.
1927    pub fn keys(&self) -> impl Iterator<Item = &K> {
1928        self.entries.iter().map(|(k, _)| k)
1929    }
1930
1931    /// Iterate over all values in wire order.
1932    pub fn values(&self) -> impl Iterator<Item = &V> {
1933        self.entries.iter().map(|(_, v)| v)
1934    }
1935
1936    /// Look up a value by key, returning the last occurrence (last-write-wins).
1937    ///
1938    /// Accepts any type that `K` can borrow as, so `map.get("key")` works
1939    /// when `K` is `&str`. O(n) scan.
1940    pub fn get<Q>(&self, key: &Q) -> Option<&V>
1941    where
1942        K: core::borrow::Borrow<Q>,
1943        Q: PartialEq + ?Sized,
1944    {
1945        self.entries
1946            .iter()
1947            .rev()
1948            .find(|(k, _)| k.borrow() == key)
1949            .map(|(_, v)| v)
1950    }
1951
1952    /// Returns `true` if an entry with the given key exists.
1953    pub fn contains_key<Q>(&self, key: &Q) -> bool
1954    where
1955        K: core::borrow::Borrow<Q>,
1956        Q: PartialEq + ?Sized,
1957    {
1958        self.entries.iter().any(|(k, _)| k.borrow() == key)
1959    }
1960
1961    /// Iterate over key-value pairs with duplicate keys removed.
1962    ///
1963    /// Each distinct key is yielded **exactly once, at the position of its
1964    /// last wire occurrence, carrying that occurrence's value** — i.e.
1965    /// last-write-wins, mirroring the merge semantics that an owned
1966    /// `HashMap` decode applies. Callers that need first-occurrence position
1967    /// should use [`iter`](Self::iter) and filter themselves.
1968    ///
1969    /// Used by the generated view `Serialize` impl: a JSON object cannot
1970    /// hold duplicate keys, but `MapView` preserves all wire entries
1971    /// (including malformed duplicates), so the JSON encode path must
1972    /// deduplicate. The implementation is allocation-free and O(n²) — for
1973    /// each entry, scan the remaining entries for a later occurrence of the
1974    /// same key. Duplicate map keys are invalid per the protobuf encoding
1975    /// spec and only arise in adversarial or conformance-test wire data, so
1976    /// `n` is effectively always small.
1977    pub fn iter_unique(&self) -> impl Iterator<Item = &(K, V)>
1978    where
1979        K: PartialEq,
1980    {
1981        let entries = &self.entries;
1982        entries.iter().enumerate().filter_map(move |(i, entry)| {
1983            if entries[i + 1..]
1984                .iter()
1985                .any(|(later_k, _)| *later_k == entry.0)
1986            {
1987                None
1988            } else {
1989                Some(entry)
1990            }
1991        })
1992    }
1993
1994    /// Count of distinct keys (`iter_unique().count()`).
1995    pub fn len_unique(&self) -> usize
1996    where
1997        K: PartialEq,
1998    {
1999        self.iter_unique().count()
2000    }
2001}
2002
2003impl<'a, K, V> From<alloc::vec::Vec<(K, V)>> for MapView<'a, K, V> {
2004    fn from(entries: alloc::vec::Vec<(K, V)>) -> Self {
2005        Self::new(entries)
2006    }
2007}
2008
2009/// Duplicate keys are kept and all encoded; see [`MapView::new`].
2010impl<'a, K, V> FromIterator<(K, V)> for MapView<'a, K, V> {
2011    fn from_iter<I: IntoIterator<Item = (K, V)>>(iter: I) -> Self {
2012        Self::new(iter.into_iter().collect())
2013    }
2014}
2015
2016impl<'a, K, V> Default for MapView<'a, K, V> {
2017    fn default() -> Self {
2018        Self {
2019            entries: alloc::vec::Vec::new(),
2020            _marker: core::marker::PhantomData,
2021        }
2022    }
2023}
2024
2025impl<'b, 'a, K, V> IntoIterator for &'b MapView<'a, K, V> {
2026    type Item = &'b (K, V);
2027    type IntoIter = core::slice::Iter<'b, (K, V)>;
2028
2029    fn into_iter(self) -> Self::IntoIter {
2030        self.entries.iter()
2031    }
2032}
2033
2034impl<'a, K, V> IntoIterator for MapView<'a, K, V> {
2035    type Item = (K, V);
2036    type IntoIter = alloc::vec::IntoIter<(K, V)>;
2037
2038    fn into_iter(self) -> Self::IntoIter {
2039        self.entries.into_iter()
2040    }
2041}
2042
2043/// One unknown-field wire record: either a span borrowed from the input
2044/// buffer, or synthetic bytes for a value with no borrowable source span.
2045#[derive(Clone, Debug)]
2046enum UnknownFieldsViewRecord<'a> {
2047    Borrowed(&'a [u8]),
2048    Owned(alloc::vec::Vec<u8>),
2049}
2050
2051impl UnknownFieldsViewRecord<'_> {
2052    fn as_slice(&self) -> &[u8] {
2053        match self {
2054            Self::Borrowed(span) => span,
2055            Self::Owned(bytes) => bytes,
2056        }
2057    }
2058}
2059
2060/// A borrowed view of unknown fields.
2061///
2062/// Stores unknown fields as wire records rather than decoded values, enabling
2063/// zero-copy round-tripping for borrowable input spans. Borrowed spans may
2064/// hold **one or more consecutive** complete `(tag, value)` records: adjacent
2065/// unknown fields are coalesced into a single span, so a long run of unknown
2066/// fields costs one `Vec` slot rather than one per field. Synthetic records
2067/// cover cases where the view decoder must preserve a value that has no
2068/// borrowable source span.
2069/// Coalescing bounds the view's memory only — the decode-time
2070/// unknown-field allowance is still charged per field (see
2071/// [`push_record`](Self::push_record)).
2072#[derive(Clone, Default)]
2073pub struct UnknownFieldsView<'a> {
2074    // Boxed, so this type is one pointer wide and holds no inline heap owner.
2075    // Every generated view embeds one by value; with the records inline, the
2076    // view becomes an owning aggregate that the compiler moves with
2077    // out-of-line `memcpy` calls instead of inline vector stores, which costs
2078    // view-decode throughput on message-dense shapes even when no unknown
2079    // field is ever pushed. The allocation happens on the first push.
2080    state: Option<alloc::boxed::Box<UnknownFieldsState<'a>>>,
2081}
2082
2083/// The records and replay accounting, allocated once a view turns out to
2084/// carry an unknown field.
2085#[derive(Clone, Default)]
2086struct UnknownFieldsState<'a> {
2087    /// Unknown wire records in decode order. Borrowed records may each hold
2088    /// one or more complete `(tag, value)` records; owned records are
2089    /// synthetic wire bytes for values that have no borrowable source span.
2090    records: alloc::vec::Vec<UnknownFieldsViewRecord<'a>>,
2091    /// The input-buffer tail starting at the first byte of the last span,
2092    /// kept so [`push_record`](Self::push_record) can extend that span over
2093    /// an adjacent record by re-slicing `last_tail` — never by widening the
2094    /// narrowed span reference, which would be provenance-unsound.
2095    last_tail: Option<&'a [u8]>,
2096    /// Total slots charged against the decode-time unknown-field allowance
2097    /// across every [`push_record`](Self::push_record) — exactly the number
2098    /// of `UnknownField`s [`to_owned`](Self::to_owned) re-materializes, so
2099    /// replay runs under precisely this budget and cannot exhaust it.
2100    to_owned_budget: usize,
2101    /// Deepest group nesting across all pushed records — the recursion
2102    /// depth [`to_owned`](Self::to_owned)'s replay needs, regardless of the
2103    /// (possibly larger) recursion limit the view was decoded under.
2104    to_owned_depth: u32,
2105    /// Set by [`push_raw`](Self::push_raw): the view holds spans that were
2106    /// never charged at decode time, so [`to_owned`](Self::to_owned) grants
2107    /// the default limits on top of the tracked budget and can fail.
2108    manual_spans: bool,
2109}
2110
2111// Manual impl: `last_tail` is an internal coalescing cursor that extends to
2112// the end of the input buffer — deriving Debug would dump the remaining
2113// message bytes on every `{:?}` print.
2114impl core::fmt::Debug for UnknownFieldsView<'_> {
2115    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
2116        f.debug_struct("UnknownFieldsView")
2117            .field("records", &self.records_slice())
2118            .finish_non_exhaustive()
2119    }
2120}
2121
2122impl<'a> UnknownFieldsView<'a> {
2123    /// The state, created on first use.
2124    ///
2125    /// The `Some` test inlines and only the allocation is out of line, so a
2126    /// run of unknown records pays the branch once per record rather than a
2127    /// call: every push after the first finds the state already there.
2128    #[inline]
2129    fn state_mut(&mut self) -> &mut UnknownFieldsState<'a> {
2130        self.state.get_or_insert_with(Self::alloc_state)
2131    }
2132
2133    /// Out of line: this runs once, when a message turns out to carry an
2134    /// unknown field at all.
2135    #[cold]
2136    fn alloc_state() -> alloc::boxed::Box<UnknownFieldsState<'a>> {
2137        alloc::boxed::Box::default()
2138    }
2139
2140    /// The records, or an empty slice when nothing was ever pushed.
2141    #[inline]
2142    fn records_slice(&self) -> &[UnknownFieldsViewRecord<'a>] {
2143        self.state.as_ref().map_or(&[], |st| st.records.as_slice())
2144    }
2145
2146    /// Creates an empty view.
2147    pub fn new() -> Self {
2148        Self::default()
2149    }
2150
2151    #[doc(hidden)]
2152    pub fn push_raw(&mut self, span: &'a [u8]) {
2153        let st = self.state_mut();
2154        st.records.push(UnknownFieldsViewRecord::Borrowed(span));
2155        // A manually pushed span has no known position in the input buffer,
2156        // so coalescing must not extend it — and it was never charged
2157        // against a decode allowance, so to_owned falls back to the default
2158        // limits for it.
2159        st.last_tail = None;
2160        st.manual_spans = true;
2161    }
2162
2163    /// Record one unknown wire record of `span_len` bytes starting at the
2164    /// head of `tail`, where `tail` extends from the record's first byte to
2165    /// the end of the input buffer.
2166    ///
2167    /// Every record charges `ctx`'s unknown-field allowance with exactly the
2168    /// slots [`to_owned`](Self::to_owned) will re-materialize it into — one
2169    /// for the record's field plus, for group records, one per nested field.
2170    /// The charge total (and the deepest group nesting) is accumulated on
2171    /// the view as the conversion replay budget, so a view that decoded
2172    /// successfully always converts.
2173    ///
2174    /// If the record starts exactly where the previous one ended, the
2175    /// previous span is extended in place instead of pushing a new one —
2176    /// coalescing saves memory (no allocation, no `Vec` slot), not
2177    /// allowance.
2178    ///
2179    /// Marked `#[cold]`: every caller is an exceptional-value route — the
2180    /// unrecognized-field arm of a generated view merge, and the arms that
2181    /// preserve an unrecognized value of a closed enum (singular and map
2182    /// entry). None runs when the payload matches the schema, so the loop
2183    /// that inlines around them is laid out as though they never do.
2184    /// Decoding from a newer producer does take these routes, once per field
2185    /// it added, and pays for that choice.
2186    ///
2187    /// # Errors
2188    ///
2189    /// Returns [`DecodeError::UnknownFieldLimitExceeded`] when the allowance
2190    /// is exhausted, or [`DecodeError::UnexpectedEof`] if `span_len` exceeds
2191    /// `tail`.
2192    #[doc(hidden)]
2193    #[cold]
2194    pub fn push_record(
2195        &mut self,
2196        tail: &'a [u8],
2197        span_len: usize,
2198        ctx: crate::DecodeContext<'_>,
2199    ) -> Result<(), crate::DecodeError> {
2200        if span_len > tail.len() {
2201            return Err(crate::DecodeError::UnexpectedEof);
2202        }
2203        let charge = crate::encoding::register_unknown_record(&tail[..span_len], ctx)?;
2204        let st = self.state_mut();
2205        st.to_owned_budget = st.to_owned_budget.saturating_add(charge.fields);
2206        st.to_owned_depth = st.to_owned_depth.max(charge.depth);
2207        if let (Some(UnknownFieldsViewRecord::Borrowed(last)), Some(prev_tail)) =
2208            (st.records.last_mut(), st.last_tail)
2209        {
2210            let prev_len = last.len();
2211            // Contiguous if the new record begins exactly one past the end
2212            // of the previous span. Both checks are plain pointer/length
2213            // comparisons; the extension below re-slices `prev_tail`, whose
2214            // provenance covers the combined range.
2215            if prev_tail.len() >= prev_len + span_len
2216                && core::ptr::eq(prev_tail[prev_len..].as_ptr(), tail.as_ptr())
2217            {
2218                *last = &prev_tail[..prev_len + span_len];
2219                return Ok(());
2220            }
2221        }
2222        st.records
2223            .push(UnknownFieldsViewRecord::Borrowed(&tail[..span_len]));
2224        st.last_tail = Some(tail);
2225        Ok(())
2226    }
2227
2228    /// Preserve one unrecognized value of a closed enum as synthetic varint
2229    /// wire bytes.
2230    ///
2231    /// Marked `#[cold]`: the sole caller is the per-element route for a closed
2232    /// enum whose wire value names no variant — reached from a *recognized*
2233    /// field, including inside a packed element loop, so it can run more than
2234    /// once per message against a newer producer's data. It builds a `Vec` per
2235    /// value regardless, which dwarfs what the size-optimized body this
2236    /// attribute asks for costs.
2237    #[doc(hidden)]
2238    #[cold]
2239    pub fn push_varint(
2240        &mut self,
2241        field_number: u32,
2242        value: u64,
2243        ctx: crate::DecodeContext<'_>,
2244    ) -> Result<(), crate::DecodeError> {
2245        use crate::encoding::{encode_varint, Tag, WireType};
2246
2247        ctx.register_unknown_field()?;
2248        let st = self.state_mut();
2249        st.to_owned_budget = st.to_owned_budget.saturating_add(1);
2250
2251        let mut bytes = alloc::vec::Vec::new();
2252        Tag::new(field_number, WireType::Varint).encode(&mut bytes);
2253        encode_varint(value, &mut bytes);
2254        st.records.push(UnknownFieldsViewRecord::Owned(bytes));
2255        // Synthetic bytes have no position in the input buffer, so a later
2256        // borrowed record must start a fresh span.
2257        st.last_tail = None;
2258        Ok(())
2259    }
2260
2261    /// Returns `true` if no unknown fields were recorded.
2262    pub fn is_empty(&self) -> bool {
2263        self.records_slice().is_empty()
2264    }
2265
2266    /// Total byte length of all unknown field data.
2267    pub fn encoded_len(&self) -> usize {
2268        self.records_slice()
2269            .iter()
2270            .map(|record| record.as_slice().len())
2271            .sum()
2272    }
2273
2274    /// Write all unknown-field bytes in decode order. Each record holds one
2275    /// or more complete `(tag, value)` records, so concatenating them
2276    /// produces a valid encoding.
2277    pub fn write_to(&self, buf: &mut impl EncodeSink) {
2278        for record in self.records_slice() {
2279            buf.put_slice(record.as_slice());
2280        }
2281    }
2282
2283    /// Convert to an owned [`UnknownFields`](crate::UnknownFields) by parsing all stored wire records.
2284    ///
2285    /// Each record holds one or more consecutive (tag + value) records as
2286    /// they should be re-emitted. Parsing uses
2287    /// [`crate::encoding::decode_unknown_field`] under exactly the budget
2288    /// [`push_record`](Self::push_record) and [`push_varint`](Self::push_varint)
2289    /// charged at decode time — the same field count and group-nesting depth —
2290    /// so replay cannot exhaust either. Views holding manually pushed spans
2291    /// (via [`push_raw`](Self::push_raw)) additionally get
2292    /// [`DEFAULT_UNKNOWN_FIELD_LIMIT`](crate::DEFAULT_UNKNOWN_FIELD_LIMIT)
2293    /// slots and the full [`RECURSION_LIMIT`](crate::RECURSION_LIMIT), since
2294    /// those spans were never charged.
2295    /// A coalesced borrowed span re-materializes one owned `UnknownField` per
2296    /// wire record, so this conversion is where a long run of unknown fields
2297    /// actually allocates.
2298    ///
2299    /// # Errors
2300    ///
2301    /// Returns `Err` if a stored record is malformed or exceeds the replay
2302    /// budget. Neither can occur when the view was produced by wire decoding
2303    /// — every borrowed record was parsed off the wire, and the budget equals
2304    /// what decoding charged — so any such view converts successfully. Only
2305    /// views holding [`push_raw`](Self::push_raw) spans can fail here.
2306    pub fn to_owned(&self) -> Result<crate::UnknownFields, crate::DecodeError> {
2307        use crate::encoding::{decode_unknown_field, Tag};
2308
2309        let Some(state) = self.state.as_deref() else {
2310            return Ok(crate::UnknownFields::new());
2311        };
2312        let (budget, depth) = if state.manual_spans {
2313            (
2314                state
2315                    .to_owned_budget
2316                    .saturating_add(crate::DEFAULT_UNKNOWN_FIELD_LIMIT),
2317                state.to_owned_depth.max(crate::RECURSION_LIMIT),
2318            )
2319        } else {
2320            (state.to_owned_budget, state.to_owned_depth)
2321        };
2322        let limit = core::cell::Cell::new(budget);
2323        let ctx = crate::DecodeContext::new(depth, &limit);
2324        let mut out = crate::UnknownFields::new();
2325        for record in &state.records {
2326            let mut cur = record.as_slice();
2327            while !cur.is_empty() {
2328                let tag = Tag::decode(&mut cur)?;
2329                let field = decode_unknown_field(tag, &mut cur, ctx)?;
2330                out.push(field);
2331            }
2332        }
2333        Ok(out)
2334    }
2335}
2336
2337/// An owned, `'static` container for a decoded message view.
2338///
2339/// `OwnedView` holds a [`Bytes`] buffer alongside the decoded view, ensuring
2340/// the view's borrows remain valid for the container's lifetime. The inner
2341/// view is reached through [`reborrow()`](OwnedView::reborrow), which returns
2342/// it with a lifetime tied to `&self`.
2343///
2344/// This type is `Send + Sync + 'static`, making it suitable for use across
2345/// async boundaries, in tower services, and anywhere a `'static` bound is
2346/// required.
2347///
2348/// # When to use
2349///
2350/// Use `OwnedView` when you need a zero-copy view that outlives the scope
2351/// where the buffer was received — for example, in an RPC handler where the
2352/// framework requires `'static` types:
2353///
2354/// ```rust,ignore
2355/// use buffa::view::OwnedView;
2356/// use bytes::Bytes;
2357///
2358/// let bytes: Bytes = receive_request_body().await;
2359/// let view = OwnedView::<PersonView>::decode(bytes)?;
2360///
2361/// // Field access through reborrow — the borrow is tied to `view`.
2362/// let person = view.reborrow();
2363/// println!("name: {}", person.name);
2364/// println!("id: {}", person.id);
2365///
2366/// // Convert to owned if you need to store or mutate — infallible, since
2367/// // an OwnedView always holds a wire-decoded view.
2368/// let owned: Person = view.to_owned_message();
2369/// ```
2370///
2371/// Generated code additionally provides a per-message `FooOwnedView` wrapper
2372/// around `OwnedView<FooView<'static>>` with per-field accessor methods
2373/// (`owned.name()`, `owned.id()`, …), so most handler code never touches
2374/// `OwnedView` or `reborrow` directly.
2375///
2376/// For scoped access where the buffer's lifetime is known, use
2377/// [`MessageView::decode_view`] directly — it has zero overhead beyond the
2378/// decode itself.
2379///
2380/// # Why field access goes through `reborrow`
2381///
2382/// `OwnedView` stores `V = FooView<'static>`: the view's borrows really point
2383/// into `self`'s [`Bytes`] buffer, and the `'static` is a synthetic lifetime
2384/// established by the constructor. Exposing `&V` directly (for example via a
2385/// `Deref` impl) would let borrowed fields *appear* `'static` to the
2386/// compiler and escape the `OwnedView`'s scope, dangling once it drops.
2387/// [`reborrow()`](OwnedView::reborrow) narrows the synthetic `'static` down
2388/// to the `OwnedView`'s real lifetime, so the borrow checker enforces the
2389/// actual validity of every field borrow:
2390///
2391/// ```no_run
2392/// # use buffa::view::OwnedView;
2393/// # use buffa::__doctest_fixtures::PersonView;
2394/// // Inline reads: reborrow once, then use plain field access.
2395/// fn log(owned: &OwnedView<PersonView<'static>>) {
2396///     let person = owned.reborrow();
2397///     println!("{}", person.name);
2398/// }
2399///
2400/// // Returning a borrowed field: the result is tied to the OwnedView.
2401/// fn name<'a>(owned: &'a OwnedView<PersonView<'static>>) -> &'a str {
2402///     owned.reborrow().name  // &'a str tied to the OwnedView's lifetime
2403/// }
2404/// ```
2405///
2406/// View fields are not reachable directly on the handle — this fails to
2407/// compile rather than handing out a `'static` borrow into the buffer:
2408///
2409/// ```compile_fail,E0609
2410/// # use buffa::view::OwnedView;
2411/// # use buffa::__doctest_fixtures::PersonView;
2412/// fn field(owned: &OwnedView<PersonView<'static>>) -> &'static str {
2413///     owned.name // error[E0609]: no field `name` on type `&OwnedView<...>`
2414/// }
2415/// ```
2416///
2417/// # Safety
2418///
2419/// Internally, `OwnedView` extends the view's lifetime to `'static` via
2420/// `transmute` in its constructors. This is sound because:
2421///
2422/// 1. [`Bytes`] is reference-counted — its heap data pointer is stable across
2423///    moves. The view's borrows always point into valid memory.
2424/// 2. [`Bytes`] is immutable — the underlying data cannot be modified while
2425///    borrowed.
2426/// 3. The view is declared before the buffer, and the compiler's drop glue
2427///    drops fields in declaration order, so the view is always gone before
2428///    the buffer it borrows from is released — on a normal drop and during
2429///    an unwind; [`into_bytes`](OwnedView::into_bytes) drops it explicitly
2430///    before handing the buffer back.
2431/// 4. The view is stored in a private `MaybeDangling` wrapper (an in-tree
2432///    stand-in for RFC 3336), which tells the aliasing model that its forged
2433///    `'static` borrows carry no validity guarantees of their own while an
2434///    `OwnedView` is moved around by value.
2435///
2436/// [`reborrow`](OwnedView::reborrow) is a plain Rust subtype coercion (no
2437/// `unsafe`, no pointer cast): the [`ViewReborrow`] trait method coerces
2438/// `&'b FooView<'static>` into `&'b FooView<'b>` via standard lifetime
2439/// variance for covariant view types. See [`ViewReborrow`]'s docs for the
2440/// soundness argument.
2441pub struct OwnedView<V> {
2442    // INVARIANT: `view` borrows from `bytes`. FIELD ORDER IS LOAD-BEARING:
2443    // drop glue runs in declaration order, so `view` must stay declared
2444    // before `bytes` for the view to be dropped while its buffer is still
2445    // alive. There is deliberately no `Drop` impl on `OwnedView` — with one,
2446    // `into_bytes` could not move `bytes` out, and a panic in `V::drop`
2447    // could unwind into it and drop the view a second time (#377).
2448    //
2449    // CONSTRUCTORS: any constructor added here MUST ensure the view's
2450    // borrows point into `self.bytes` (not into caller-owned memory).
2451    // The auto-`Send`/`Sync` derivation is only sound under that invariant
2452    // — there is no longer a `V: 'static` bound on `Send` to act as a
2453    // second gate. See the comment block above `send_sync_assertions` below.
2454    view: MaybeDangling<V>,
2455    bytes: Bytes,
2456}
2457
2458/// An in-tree stand-in for the `MaybeDangling<T>` proposed in [RFC 3336],
2459/// modelled on `yoke`'s `KindaSortaDangling` (minus the `into_inner` and
2460/// `DerefMut` this crate has no caller for).
2461///
2462/// The view inside an [`OwnedView`] carries `&'static` borrows that really
2463/// point into the sibling `Bytes` buffer. Storing it behind a
2464/// [`MaybeUninit`](core::mem::MaybeUninit) tells the aliasing model that the
2465/// value has no memory-dependent validity properties (`dereferenceable`,
2466/// `noalias`) of its own. Without the wrapper, Miri's field retagging puts a
2467/// protector on each forged `&'static` whenever an `OwnedView` is passed by
2468/// value, and freeing the buffer inside that call — a plain `drop(owned)` in
2469/// the callee, or the unwind path of [`OwnedView::into_bytes`] — is reported
2470/// as undefined behaviour. [icu4x #3696] is the `yoke` test case for exactly
2471/// this.
2472///
2473/// Once RFC 3336 lands this can become the standard library type.
2474///
2475/// [RFC 3336]: https://github.com/rust-lang/rfcs/pull/3336
2476/// [icu4x #3696]: https://github.com/unicode-org/icu4x/issues/3696
2477#[repr(transparent)]
2478struct MaybeDangling<T> {
2479    /// INVARIANT: always holds an initialized `T`. Its drop glue runs from
2480    /// [`Drop::drop`] below rather than from `MaybeUninit` (which has none),
2481    /// so nothing may treat `inner` as initialized after that point — and
2482    /// nothing does, because the only code that runs afterwards is the
2483    /// empty drop glue of `MaybeUninit`.
2484    inner: core::mem::MaybeUninit<T>,
2485}
2486
2487impl<T> MaybeDangling<T> {
2488    #[inline]
2489    const fn new(value: T) -> Self {
2490        Self {
2491            inner: core::mem::MaybeUninit::new(value),
2492        }
2493    }
2494}
2495
2496impl<T> core::ops::Deref for MaybeDangling<T> {
2497    type Target = T;
2498    #[inline]
2499    fn deref(&self) -> &T {
2500        // SAFETY: `inner` is initialized (the type invariant); `deref` is
2501        // never reachable once `Drop::drop` has run.
2502        unsafe { self.inner.assume_init_ref() }
2503    }
2504}
2505
2506impl<T> Drop for MaybeDangling<T> {
2507    #[inline]
2508    fn drop(&mut self) {
2509        // SAFETY: `inner` is initialized (the type invariant) and is dropped
2510        // exactly once here — `MaybeUninit` has no drop glue, so nothing runs
2511        // it again afterwards. `drop_in_place` rather than
2512        // `assume_init_read` so the `T` is never moved into an unwrapped
2513        // local, which would reassert the validity properties this wrapper
2514        // exists to suppress.
2515        unsafe { self.inner.as_mut_ptr().drop_in_place() }
2516    }
2517}
2518
2519/// Panic path for [`OwnedView::to_owned_message`], hoisted out of the
2520/// generic method so the format machinery is emitted once rather than per
2521/// monomorphization — the branch is unreachable for generated view types.
2522#[cold]
2523#[inline(never)]
2524fn convert_contract_violated(e: DecodeError) -> ! {
2525    panic!(
2526        "OwnedView conversion failed ({e:?}): the wrapped MessageView \
2527         impl violates the wire-decode => convert contract"
2528    )
2529}
2530
2531impl<V> OwnedView<V>
2532where
2533    V: MessageView<'static>,
2534{
2535    /// Decode a view from a [`Bytes`] buffer.
2536    ///
2537    /// The view borrows directly from the buffer's data. Because [`Bytes`] is
2538    /// reference-counted and its data pointer is stable across moves, the
2539    /// view's borrows remain valid for the lifetime of this `OwnedView`.
2540    ///
2541    /// # Errors
2542    ///
2543    /// Returns [`DecodeError`] if the buffer contains invalid protobuf data.
2544    pub fn decode(bytes: Bytes) -> Result<Self, DecodeError> {
2545        // SAFETY: `Bytes` is StableDeref — its heap data never moves or is
2546        // freed while we hold the `Bytes` value. We hold it in `self.bytes`,
2547        // and declaration-order drop glue (`OwnedView` has no `Drop` impl)
2548        // guarantees `view` drops first.
2549        let view = unsafe {
2550            let slice: &'static [u8] = core::mem::transmute::<&[u8], &'static [u8]>(&bytes);
2551            V::decode_view(slice)?
2552        };
2553        Ok(Self {
2554            view: MaybeDangling::new(view),
2555            bytes,
2556        })
2557    }
2558
2559    /// Decode a view with custom [`DecodeOptions`](crate::DecodeOptions)
2560    /// (recursion limit, max message size).
2561    ///
2562    /// # Errors
2563    ///
2564    /// Returns [`DecodeError`] if the buffer is invalid or exceeds the
2565    /// configured limits.
2566    pub fn decode_with_options(
2567        bytes: Bytes,
2568        opts: &crate::DecodeOptions,
2569    ) -> Result<Self, DecodeError> {
2570        // SAFETY: Same invariants as `decode` — see above.
2571        let view = unsafe {
2572            let slice: &'static [u8] = core::mem::transmute::<&[u8], &'static [u8]>(&bytes);
2573            opts.decode_view::<V>(slice)?
2574        };
2575        Ok(Self {
2576            view: MaybeDangling::new(view),
2577            bytes,
2578        })
2579    }
2580
2581    /// Create an `OwnedView` from an owned message by encoding then decoding.
2582    ///
2583    /// This performs a full **encode → decode** round-trip: the message is
2584    /// serialized to protobuf bytes, then a zero-copy view is decoded from
2585    /// those bytes. This is useful when the original wire bytes are not
2586    /// available (e.g., after JSON deserialization or programmatic construction),
2587    /// but note the cost: one allocation + O(n) encode + O(n) decode.
2588    ///
2589    /// For the common case where you already have wire bytes, prefer
2590    /// [`decode`](Self::decode) instead.
2591    ///
2592    /// # Errors
2593    ///
2594    /// Returns [`DecodeError::MessageTooLarge`] if the message's encoded
2595    /// size exceeds the 2 GiB protobuf limit
2596    /// ([`MAX_MESSAGE_BYTES`](crate::MAX_MESSAGE_BYTES)), or another
2597    /// [`DecodeError`] if the re-encoded bytes are somehow invalid (should
2598    /// not happen for well-formed messages).
2599    pub fn from_owned(msg: &V::Owned) -> Result<Self, DecodeError> {
2600        let bytes = Bytes::from(
2601            msg.try_encode_to_vec()
2602                .map_err(|_| DecodeError::MessageTooLarge)?,
2603        );
2604        Self::decode(bytes)
2605    }
2606
2607    /// Convert the view to the corresponding owned message type.
2608    ///
2609    /// `bytes::Bytes`-typed fields are produced via [`Bytes::slice_ref`]
2610    /// into the retained buffer (zero-copy); other borrowed fields are
2611    /// allocated and copied.
2612    ///
2613    /// Infallible: every `OwnedView` constructor wire-decodes its view
2614    /// ([`decode`](Self::decode), [`decode_with_options`](Self::decode_with_options),
2615    /// [`from_owned`](Self::from_owned)) or requires wire-decode provenance
2616    /// as part of its safety contract ([`from_parts`](Self::from_parts)),
2617    /// and a view produced by wire decoding always converts (see
2618    /// [`MessageView::to_owned_message`]).
2619    ///
2620    /// # Panics
2621    ///
2622    /// Panics if `V`'s [`MessageView`] implementation violates the
2623    /// wire-decode ⇒ convert contract. Generated view types cannot trigger
2624    /// this; only a buggy hand-written impl (or a
2625    /// [`from_parts`](Self::from_parts) view that breaches its safety
2626    /// contract) can.
2627    #[must_use]
2628    pub fn to_owned_message(&self) -> V::Owned {
2629        self.view
2630            .to_owned_from_source(Some(&self.bytes))
2631            .unwrap_or_else(|e| convert_contract_violated(e))
2632    }
2633
2634    /// Get a reference to the underlying bytes buffer.
2635    pub fn bytes(&self) -> &Bytes {
2636        &self.bytes
2637    }
2638
2639    /// Create an `OwnedView` from a buffer and a pre-decoded view.
2640    ///
2641    /// This avoids re-decoding when you already hold a decoded view and want
2642    /// to wrap it for `'static` use.
2643    ///
2644    /// # Safety
2645    ///
2646    /// The caller must ensure that `view` was produced by **wire-decoding**
2647    /// `bytes` (or a sub-slice that `bytes` fully contains) — e.g. via
2648    /// [`MessageView::decode_view`]. This guarantees both that all borrows
2649    /// in `view` point into the data region of `bytes` (violating that
2650    /// causes undefined behavior — dangling references) and that
2651    /// [`to_owned_message`](Self::to_owned_message)'s infallible-conversion
2652    /// contract holds (a manually assembled view merely borrowing from
2653    /// `bytes` satisfies the borrow requirement but can make conversion
2654    /// panic).
2655    pub unsafe fn from_parts(bytes: Bytes, view: V) -> Self {
2656        Self {
2657            view: MaybeDangling::new(view),
2658            bytes,
2659        }
2660    }
2661
2662    /// Consume the `OwnedView`, returning the underlying [`Bytes`] buffer.
2663    ///
2664    /// The view is dropped before the buffer is returned.
2665    ///
2666    /// # Panics
2667    ///
2668    /// Propagates a panic from `V`'s destructor; the buffer is then released
2669    /// by the unwind instead of being returned.
2670    pub fn into_bytes(self) -> Bytes {
2671        // Destructuring is only legal because `OwnedView` has no `Drop` impl
2672        // of its own. Moving the `Bytes` handle out first is fine: the heap
2673        // data the view borrows stays put (`Bytes` is `StableDeref`), and
2674        // the local keeps it alive. Dropping the view explicitly before
2675        // `bytes` moves into the return slot keeps the buffer a plain local
2676        // while `V::drop` runs: if that panics, the unwind frees `bytes` (a
2677        // value already in the return slot would be leaked instead), and
2678        // `view` has been moved into `drop`, so nothing can drop it twice.
2679        let Self { view, bytes } = self;
2680        drop(view);
2681        bytes
2682    }
2683
2684    /// Reborrow the view with a lifetime tied to `&'b self`.
2685    ///
2686    /// `OwnedView<V>` stores `V` with a `'static` lifetime — the actual borrows
2687    /// point into `self`'s internal [`Bytes`] buffer and are only valid while
2688    /// `self` is alive. `reborrow` makes that real lifetime visible to the borrow
2689    /// checker: the returned `&'b V::Reborrowed<'b>` cannot outlive `&'b self`.
2690    ///
2691    /// # Example
2692    ///
2693    /// ```no_run
2694    /// # use buffa::view::OwnedView;
2695    /// # use buffa::__doctest_fixtures::PersonView;
2696    /// fn handler<'a>(req: &'a OwnedView<PersonView<'static>>) -> &'a str {
2697    ///     // The explicit annotation is for emphasis; inference works without it.
2698    ///     // If you need to name the lifetime, store the reborrow in a `let` first.
2699    ///     let req_view: &PersonView<'a> = req.reborrow();
2700    ///     req_view.name  // zero-copy from the OwnedView's buffer
2701    /// }
2702    /// ```
2703    ///
2704    /// The returned reference is tied to `&'b self` — the borrow checker
2705    /// prevents the reborrowed view from outliving the `OwnedView`:
2706    ///
2707    /// ```compile_fail,E0597
2708    /// # use buffa::view::OwnedView;
2709    /// # use buffa::__doctest_fixtures::PersonView;
2710    /// let name: &str;
2711    /// {
2712    ///     // SAFETY: empty Bytes, no borrows — safe to construct directly.
2713    ///     let owned = unsafe {
2714    ///         OwnedView::<PersonView<'static>>::from_parts(
2715    ///             ::buffa::bytes::Bytes::new(),
2716    ///             PersonView::default(),
2717    ///         )
2718    ///     };
2719    ///     name = owned.reborrow().name; // error[E0597]: `owned` does not live long enough
2720    /// }
2721    /// println!("{name}"); // name is dangling — borrow checker rejects this
2722    /// ```
2723    ///
2724    /// # How it works
2725    ///
2726    /// The trait method [`ViewReborrow::reborrow`] is a plain Rust subtype
2727    /// coercion: `&'b V` (where `V = FooView<'static>`) flows into the
2728    /// return slot `&'b V::Reborrowed<'b>` (= `&'b FooView<'b>`). Variance
2729    /// makes this safe — covariant view types narrow `'static` down to
2730    /// `'b` automatically. No `unsafe`, no pointer cast, no layout
2731    /// assertions. `OwnedView`'s own invariant (every borrow in `view`
2732    /// points into `self.bytes`, established by `decode` or upheld by the
2733    /// `unsafe from_parts` caller) guarantees the pointed-to data lives
2734    /// at least as long as `'b`.
2735    #[must_use = "reborrow returns a tied-lifetime view; discarding it is a no-op"]
2736    pub fn reborrow<'b>(&'b self) -> &'b V::Reborrowed<'b>
2737    where
2738        V: ViewReborrow,
2739    {
2740        V::reborrow(&self.view)
2741    }
2742}
2743
2744// Deliberately NO `Deref<Target = V>` impl: `V` is `FooView<'static>`, so a
2745// `&V` return would expose the synthetic `'static` on every borrowed field
2746// and let it escape the OwnedView's scope (dangling once the buffer drops).
2747// All access goes through `reborrow()`, which ties the borrow to `&self`.
2748
2749impl<V> core::fmt::Debug for OwnedView<V>
2750where
2751    V: core::fmt::Debug,
2752{
2753    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
2754        (*self.view).fmt(f)
2755    }
2756}
2757
2758impl<V> Clone for OwnedView<V>
2759where
2760    V: Clone,
2761{
2762    fn clone(&self) -> Self {
2763        // SAFETY: `Bytes::clone()` is a refcount bump — both the original and
2764        // the clone share the same backing heap allocation. The cloned view's
2765        // `'static` references remain valid because they point into data that
2766        // is now kept alive by the cloned `Bytes` handle. This would be
2767        // unsound if `Bytes::clone()` performed a deep copy to a new address.
2768        Self {
2769            view: MaybeDangling::new((*self.view).clone()),
2770            bytes: self.bytes.clone(),
2771        }
2772    }
2773}
2774
2775impl<V> PartialEq for OwnedView<V>
2776where
2777    V: PartialEq,
2778{
2779    fn eq(&self, other: &Self) -> bool {
2780        *self.view == *other.view
2781    }
2782}
2783
2784impl<V> Eq for OwnedView<V> where V: Eq {}
2785
2786/// Serialize an `OwnedView<V>` by delegating to the inner view's `Serialize`
2787/// impl.
2788///
2789/// Equivalent to serializing `owned_view.reborrow()` directly, so
2790/// `serde_json::to_string(&owned_view)` works on the handle itself. When
2791/// `V` is a buffa-generated view with `generate_json` enabled, this produces
2792/// protobuf JSON; the impl itself just forwards to whatever `V::serialize`
2793/// does.
2794///
2795/// Only available when the `json` feature is enabled.
2796#[cfg(feature = "json")]
2797impl<V: ::serde::Serialize> ::serde::Serialize for OwnedView<V> {
2798    fn serialize<S: ::serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
2799        ::serde::Serialize::serialize(&*self.view, s)
2800    }
2801}
2802
2803// `OwnedView<V>` is auto-`Send`/`Sync` when `V` is — `MaybeDangling<V>` (a
2804// `MaybeUninit<V>`) and `Bytes` both forward auto-traits. No manual
2805// `unsafe impl` is needed, and adding one with a `V: 'static` bound is
2806// actively harmful: it is precisely what triggers E0477 when `async fn` is
2807// used in a trait impl against an RPITIT `+ Send` return type
2808// (rust-lang/rust#128095). The RPITIT desugaring introduces a fresh lifetime
2809// for the `'static` in `FooView<'static>`, and then cannot prove that fresh
2810// lifetime satisfies `'static` to discharge the manual impl's bound.
2811//
2812// The bound was defensive — intended to prevent `OwnedView<FooView<'short>>`
2813// from being `Send` when the view borrows from something outside `self.bytes`.
2814// But that type is already unconstructible: `::decode()` and
2815// `::decode_with_options()` are gated on `V: MessageView<'static>`, and the
2816// fields are private. The short-lifetime case the bound guards against cannot
2817// exist in safe code.
2818//
2819// Auto-trait soundness: `Bytes` is `Send + Sync`. The view's `&'static [u8]`
2820// borrows point into `Bytes`'s heap allocation, which is immutable,
2821// `StableDeref`, and moves with the struct. Sending the whole pair to another
2822// thread preserves the invariant. The `'static` in `V` being a lie is about
2823// *where* the reference points, not about thread safety.
2824#[cfg(test)]
2825mod send_sync_assertions {
2826    use super::*;
2827    fn assert_send<T: Send>() {}
2828    fn assert_sync<T: Sync>() {}
2829
2830    // Any `V: Send + Sync` suffices — generated `FooView<'static>` types are
2831    // auto-`Send + Sync` via their `&'static str` / `&'static [u8]` fields.
2832    #[allow(dead_code)]
2833    fn owned_view_is_send_sync<V: Send + Sync>() {
2834        assert_send::<OwnedView<V>>();
2835        assert_sync::<OwnedView<V>>();
2836    }
2837
2838    // `OwnedView<FooView<'static>>` must keep coercing to
2839    // `OwnedView<FooView<'a>>`: `MaybeUninit<V>` is covariant in `V` like the
2840    // `ManuallyDrop<V>` it replaced, but that is a derived property of the
2841    // union, not a documented guarantee, so pin it here.
2842    #[allow(dead_code)]
2843    fn owned_view_is_covariant<'a>(
2844        v: OwnedView<super::tests::TinyView<'static>>,
2845    ) -> OwnedView<super::tests::TinyView<'a>> {
2846        v
2847    }
2848
2849    // Concrete-type regression: `TinyView` is declared in the `tests` module
2850    // below and has the same shape as generated view types (one `&'a str`).
2851    #[allow(dead_code)]
2852    fn owned_tiny_view_is_send_sync() {
2853        assert_send::<OwnedView<super::tests::TinyView<'static>>>();
2854        assert_sync::<OwnedView<super::tests::TinyView<'static>>>();
2855    }
2856
2857    // `ViewReborrow::Reborrowed<'b>` must also be Send + Sync so that a
2858    // reborrowed view can be passed across threads (e.g. into a Tokio task).
2859    #[allow(dead_code)]
2860    fn reborrowed_view_is_send_sync<V>()
2861    where
2862        V: ViewReborrow + Send + Sync,
2863        for<'b> V::Reborrowed<'b>: Send + Sync,
2864    {
2865        assert_send::<OwnedView<V>>();
2866        assert_sync::<OwnedView<V>>();
2867    }
2868}
2869
2870#[cfg(test)]
2871mod tests {
2872    use super::*;
2873
2874    // ── MessageFieldView ─────────────────────────────────────────────────
2875
2876    #[test]
2877    fn message_field_view_default_is_unset() {
2878        let v: MessageFieldView<i32> = MessageFieldView::default();
2879        assert!(v.is_unset());
2880        assert!(!v.is_set());
2881        assert_eq!(v.as_option(), None);
2882    }
2883
2884    #[test]
2885    fn message_field_view_set_value() {
2886        let v = MessageFieldView::set(42);
2887        assert!(v.is_set());
2888        assert!(!v.is_unset());
2889        assert_eq!(v.as_option(), Some(&42));
2890    }
2891
2892    #[test]
2893    fn message_field_view_with_non_copy_type() {
2894        let v = MessageFieldView::set(alloc::string::String::from("hello"));
2895        assert!(v.is_set());
2896        assert_eq!(v.as_option().map(|s| s.as_str()), Some("hello"));
2897
2898        let unset: MessageFieldView<alloc::string::String> = MessageFieldView::unset();
2899        assert!(unset.is_unset());
2900        assert_eq!(unset.as_option(), None);
2901    }
2902
2903    // ── MessageFieldView Deref ─────────────────────────────────────────
2904
2905    /// A trivial view type for testing MessageFieldView Deref.
2906    #[derive(Clone, Debug, Default, PartialEq)]
2907    pub(super) struct TinyView<'a> {
2908        pub value: &'a str,
2909    }
2910
2911    // Via the exported macro, which doubles as its unit test (hygiene and
2912    // `$crate` path resolution).
2913    crate::impl_default_view_instance!(TinyView);
2914
2915    #[test]
2916    fn impl_default_view_instance_macro_returns_singleton() {
2917        let a: &TinyView<'_> = TinyView::default_view_instance();
2918        let b: &TinyView<'_> = TinyView::default_view_instance();
2919        assert!(core::ptr::eq(a, b), "singleton must be a single allocation");
2920        assert_eq!(a, &TinyView::default());
2921    }
2922
2923    #[test]
2924    fn message_field_view_deref_set() {
2925        let v = MessageFieldView::set(TinyView { value: "hello" });
2926        // Deref gives access to the inner view
2927        assert_eq!(v.value, "hello");
2928    }
2929
2930    #[test]
2931    fn message_field_view_deref_unset_returns_default() {
2932        let v: MessageFieldView<TinyView<'_>> = MessageFieldView::unset();
2933        // Deref transparently returns the default instance
2934        assert_eq!(v.value, "");
2935    }
2936
2937    #[test]
2938    fn message_field_view_deref_chained_access() {
2939        // Simulates accessing a nested field through an unset sub-message
2940        let v: MessageFieldView<TinyView<'_>> = MessageFieldView::unset();
2941        let len = v.value.len();
2942        assert_eq!(len, 0);
2943    }
2944
2945    // ── MessageFieldView PartialEq (wire-equivalent) ───────────────────
2946
2947    #[test]
2948    fn message_field_view_equality() {
2949        // None = Unset, Some(s) = Set(TinyView { value: s }).
2950        // TinyView::default() has value == "", so Some("") encodes Set(default).
2951        fn mk(c: Option<&str>) -> MessageFieldView<TinyView<'_>> {
2952            match c {
2953                None => MessageFieldView::unset(),
2954                Some(v) => MessageFieldView::set(TinyView { value: v }),
2955            }
2956        }
2957
2958        #[rustfmt::skip]
2959        let cases: &[(Option<&str>, Option<&str>, bool)] = &[
2960            // Wire-equivalent semantics: Unset == Set(default), matching
2961            // MessageField::PartialEq on the owned side.
2962            (None,      None,        true ),  // Unset == Unset
2963            (None,      Some(""),    true ),  // Unset == Set(default)
2964            (Some(""),  None,        true ),  // Set(default) == Unset (symmetric)
2965            (Some(""),  Some(""),    true ),  // Set(default) == Set(default)
2966            (None,      Some("x"),   false),  // Unset != Set(nondefault)
2967            (Some("x"), None,        false),  // Set(nondefault) != Unset (symmetric)
2968            (Some("x"), Some("x"),   true ),  // Set == Set (same)
2969            (Some("x"), Some("y"),   false),  // Set != Set (different)
2970        ];
2971
2972        for &(l, r, expect) in cases {
2973            assert_eq!(
2974                mk(l) == mk(r),
2975                expect,
2976                "({l:?} == {r:?}) should be {expect}"
2977            );
2978        }
2979    }
2980
2981    // ── RepeatedView ─────────────────────────────────────────────────────
2982
2983    #[test]
2984    fn repeated_view_new_and_accessors() {
2985        let rv = RepeatedView::new(alloc::vec![10, 20, 30]);
2986        assert_eq!(rv.len(), 3);
2987        assert!(!rv.is_empty());
2988        assert_eq!(&*rv, &[10, 20, 30]);
2989    }
2990
2991    #[test]
2992    fn repeated_view_default_is_empty() {
2993        let rv: RepeatedView<'_, u8> = RepeatedView::default();
2994        assert!(rv.is_empty());
2995        assert_eq!(rv.len(), 0);
2996    }
2997
2998    #[test]
2999    fn repeated_view_push_and_iter() {
3000        let mut rv = RepeatedView::<i32>::default();
3001        rv.push(1);
3002        rv.push(2);
3003        let collected: alloc::vec::Vec<_> = rv.iter().copied().collect();
3004        assert_eq!(collected, alloc::vec![1, 2]);
3005    }
3006
3007    // ── UnknownFieldsView::push_record (coalescing + limit) ────────────
3008
3009    /// A test context at full depth with `n` unknown-field slots, leaking
3010    /// the cell so the context can outlive this helper.
3011    fn record_ctx(n: usize) -> crate::DecodeContext<'static> {
3012        let limit = alloc::boxed::Box::leak(alloc::boxed::Box::new(core::cell::Cell::new(n)));
3013        crate::DecodeContext::new(crate::RECURSION_LIMIT, limit)
3014    }
3015
3016    #[test]
3017    fn push_record_coalesces_adjacent_records() {
3018        // Buffer holds three consecutive 2-byte records: they coalesce into
3019        // a single span, but each still consumes one allowance slot.
3020        let buf: &[u8] = &[0x08, 0x00, 0x08, 0x01, 0x08, 0x02];
3021        let ctx = record_ctx(3);
3022        let mut ufv = UnknownFieldsView::new();
3023        ufv.push_record(&buf[0..], 2, ctx).unwrap();
3024        ufv.push_record(&buf[2..], 2, ctx).unwrap();
3025        ufv.push_record(&buf[4..], 2, ctx).unwrap();
3026        assert_eq!(ufv.encoded_len(), 6);
3027        assert_eq!(ufv.records_slice().len(), 1, "coalesced into one span");
3028        let mut out = alloc::vec::Vec::new();
3029        ufv.write_to(&mut out);
3030        assert_eq!(out, buf);
3031        assert_eq!(ctx.remaining_unknown_fields(), 0, "one slot per record");
3032    }
3033
3034    #[test]
3035    fn push_record_non_adjacent_records_use_separate_slots() {
3036        let buf: &[u8] = &[0x08, 0x00, 0xFF, 0x08, 0x01];
3037        let ctx = record_ctx(2);
3038        let mut ufv = UnknownFieldsView::new();
3039        ufv.push_record(&buf[0..], 2, ctx).unwrap();
3040        // Skip buf[2] — the next record is not adjacent to the previous one.
3041        ufv.push_record(&buf[3..], 2, ctx).unwrap();
3042        assert_eq!(ufv.encoded_len(), 4);
3043        assert_eq!(ctx.remaining_unknown_fields(), 0, "two slots consumed");
3044    }
3045
3046    #[test]
3047    fn push_record_enforces_limit_per_record() {
3048        // Before the per-record accounting fix, a coalesced run consumed
3049        // one slot at decode and one slot per record at conversion, so an
3050        // over-limit contiguous run decoded as a view and then failed to
3051        // convert. Now it fails at push time.
3052        let buf: &[u8] = &[0x08, 0x00, 0x08, 0x01, 0x08, 0x02];
3053        let ctx = record_ctx(1);
3054        let mut ufv = UnknownFieldsView::new();
3055        ufv.push_record(&buf[0..], 2, ctx).unwrap();
3056        // Non-adjacent record (the one at buf[2..4] was skipped): new span.
3057        assert_eq!(
3058            ufv.push_record(&buf[4..], 2, ctx),
3059            Err(crate::DecodeError::UnknownFieldLimitExceeded)
3060        );
3061        // Coalescing saves a span slot, not allowance: at zero remaining
3062        // even an adjacent record is rejected, keeping the decode-time
3063        // count equal to the count to_owned re-materializes.
3064        assert_eq!(
3065            ufv.push_record(&buf[2..], 2, ctx),
3066            Err(crate::DecodeError::UnknownFieldLimitExceeded)
3067        );
3068    }
3069
3070    #[test]
3071    fn push_record_charges_group_records_per_nested_field() {
3072        // One group record (field 1) holding two nested varint fields:
3073        // to_owned materializes three UnknownFields (group + 2 nested), so
3074        // decode must charge three slots.
3075        let buf: &[u8] = &[0x0b, 0x08, 0x00, 0x08, 0x01, 0x0c];
3076        let ctx = record_ctx(2);
3077        let mut ufv = UnknownFieldsView::new();
3078        assert_eq!(
3079            ufv.push_record(buf, buf.len(), ctx),
3080            Err(crate::DecodeError::UnknownFieldLimitExceeded)
3081        );
3082
3083        let ctx = record_ctx(3);
3084        let mut ufv = UnknownFieldsView::new();
3085        ufv.push_record(buf, buf.len(), ctx).unwrap();
3086        assert_eq!(ctx.remaining_unknown_fields(), 0, "group + 2 nested");
3087        let owned = ufv.to_owned().expect("decode allowance covers replay");
3088        assert_eq!(owned.iter().count(), 1, "one top-level group field");
3089    }
3090
3091    #[test]
3092    fn push_record_charges_nested_groups_recursively() {
3093        // group 1 { varint; group 2 { varint } } — four materializable
3094        // fields, so four slots.
3095        let buf: &[u8] = &[0x0b, 0x08, 0x00, 0x13, 0x08, 0x01, 0x14, 0x0c];
3096        let ctx = record_ctx(3);
3097        let mut ufv = UnknownFieldsView::new();
3098        assert_eq!(
3099            ufv.push_record(buf, buf.len(), ctx),
3100            Err(crate::DecodeError::UnknownFieldLimitExceeded)
3101        );
3102
3103        let ctx = record_ctx(4);
3104        let mut ufv = UnknownFieldsView::new();
3105        ufv.push_record(buf, buf.len(), ctx).unwrap();
3106        assert_eq!(ctx.remaining_unknown_fields(), 0);
3107        ufv.to_owned().expect("decode allowance covers replay");
3108    }
3109
3110    #[test]
3111    fn push_raw_disables_coalescing_for_next_record() {
3112        let buf: &[u8] = &[0x08, 0x00, 0x08, 0x01];
3113        let ctx = record_ctx(2);
3114        let mut ufv = UnknownFieldsView::new();
3115        ufv.push_raw(&buf[0..2]);
3116        // Adjacent on the wire, but push_raw cleared the tail, so this must
3117        // open a fresh span (a manual span has no trusted buffer position).
3118        ufv.push_record(&buf[2..], 2, ctx).unwrap();
3119        assert_eq!(ctx.remaining_unknown_fields(), 1);
3120        assert_eq!(ufv.encoded_len(), 4);
3121    }
3122
3123    #[test]
3124    fn push_record_rejects_span_past_tail_end() {
3125        let buf: &[u8] = &[0x08, 0x00];
3126        let ctx = record_ctx(1);
3127        let mut ufv = UnknownFieldsView::new();
3128        assert_eq!(
3129            ufv.push_record(buf, 3, ctx),
3130            Err(crate::DecodeError::UnexpectedEof)
3131        );
3132    }
3133
3134    #[test]
3135    fn coalesced_span_to_owned_parses_every_record() {
3136        let buf: &[u8] = &[0x08, 0x00, 0x08, 0x01, 0x08, 0x02];
3137        let ctx = record_ctx(3);
3138        let mut ufv = UnknownFieldsView::new();
3139        for i in 0..3 {
3140            ufv.push_record(&buf[2 * i..], 2, ctx).unwrap();
3141        }
3142        let owned = ufv.to_owned().unwrap();
3143        assert_eq!(owned.iter().count(), 3, "all records parsed");
3144    }
3145
3146    #[test]
3147    fn decode_time_allowance_always_covers_to_owned() {
3148        // The invariant push_record's accounting exists for: any run that
3149        // decodes within the allowance converts within the captured
3150        // allowance. Here the record count exactly exhausts the limit and
3151        // the run coalesces into one span.
3152        let buf: &[u8] = &[0x08, 0x00, 0x08, 0x01, 0x08, 0x02];
3153        let ctx = record_ctx(3);
3154        let mut ufv = UnknownFieldsView::new();
3155        for i in 0..3 {
3156            ufv.push_record(&buf[2 * i..], 2, ctx).unwrap();
3157        }
3158        assert_eq!(ufv.records_slice().len(), 1, "coalesced into one span");
3159        assert_eq!(ctx.remaining_unknown_fields(), 0, "limit exactly used");
3160        let owned = ufv.to_owned().expect("decode succeeded, so convert must");
3161        assert_eq!(owned.iter().count(), 3);
3162    }
3163
3164    #[test]
3165    fn to_owned_of_manual_view_uses_default_allowance() {
3166        // push_raw spans are never charged at decode time; to_owned grants
3167        // the default limit for them.
3168        let mut ufv = UnknownFieldsView::new();
3169        ufv.push_raw(&[0x08, 0x00]);
3170        let owned = ufv.to_owned().unwrap();
3171        assert_eq!(owned.iter().count(), 1);
3172    }
3173
3174    #[test]
3175    fn to_owned_covers_records_pushed_under_different_contexts() {
3176        // The replay budget is the accumulated charge total, not a snapshot
3177        // of any single context's remaining allowance — so a view merged
3178        // across decode passes with unrelated contexts still converts.
3179        let buf: &[u8] = &[0x08, 0x00, 0x08, 0x01, 0x08, 0x02];
3180        let mut ufv = UnknownFieldsView::new();
3181        let tight = record_ctx(1);
3182        ufv.push_record(&buf[0..], 2, tight).unwrap();
3183        let fresh = record_ctx(2);
3184        ufv.push_record(&buf[2..], 2, fresh).unwrap();
3185        ufv.push_record(&buf[4..], 2, fresh).unwrap();
3186        let owned = ufv.to_owned().expect("every push succeeded");
3187        assert_eq!(owned.iter().count(), 3);
3188    }
3189
3190    #[test]
3191    fn to_owned_replays_deep_groups_decoded_under_raised_recursion_limit() {
3192        // Replay depth comes from the nesting tracked at decode time, not
3193        // the fixed RECURSION_LIMIT — a group nested deeper than the
3194        // default (decodable only under a raised recursion limit) must
3195        // still convert.
3196        let deep = crate::RECURSION_LIMIT as usize + 20;
3197        let mut buf = alloc::vec![0x0bu8; deep]; // StartGroup ×deep
3198        buf.resize(2 * deep, 0x0c); // EndGroup ×deep
3199        let ctx = record_ctx(deep);
3200        let mut ufv = UnknownFieldsView::new();
3201        ufv.push_record(&buf, buf.len(), ctx).unwrap();
3202        assert_eq!(ctx.remaining_unknown_fields(), 0, "one slot per group");
3203        ufv.to_owned().expect("decode succeeded, so convert must");
3204    }
3205
3206    #[test]
3207    fn to_owned_of_malformed_manual_span_fails() {
3208        // The replay error path stays live for manually built views: a
3209        // push_raw span that is not a complete record fails to parse.
3210        let mut ufv = UnknownFieldsView::new();
3211        ufv.push_raw(&[0xFF]);
3212        assert!(ufv.to_owned().is_err());
3213    }
3214
3215    #[test]
3216    fn to_owned_of_manual_flood_over_default_limit_fails() {
3217        // The replay limit stays live for manually built views: push_raw
3218        // spans get the default allowance, no more — the memory-
3219        // amplification bound survives even though wire-decoded views
3220        // cannot hit it (decode charges the allowance up front).
3221        let n = crate::DEFAULT_UNKNOWN_FIELD_LIMIT + 1;
3222        let mut buf = alloc::vec::Vec::with_capacity(2 * n);
3223        for _ in 0..n {
3224            buf.extend_from_slice(&[0x08, 0x00]);
3225        }
3226        let mut ufv = UnknownFieldsView::new();
3227        ufv.push_raw(&buf);
3228        assert_eq!(
3229            ufv.to_owned(),
3230            Err(crate::DecodeError::UnknownFieldLimitExceeded)
3231        );
3232    }
3233
3234    #[test]
3235    fn repeated_view_reserve_grows_capacity() {
3236        let mut rv = RepeatedView::<u32>::default();
3237        rv.reserve(64);
3238        assert!(rv.elements.capacity() >= 64);
3239        // Reserve must not produce visible elements.
3240        assert!(rv.is_empty());
3241        // reserve(0) is a no-op and must not panic.
3242        rv.reserve(0);
3243        // Reserve after pushes adds capacity above current len.
3244        rv.push(1);
3245        rv.push(2);
3246        rv.reserve(100);
3247        assert_eq!(rv.len(), 2);
3248        assert!(rv.elements.capacity() >= 102);
3249        // Subsequent reserve calls must not corrupt the existing elements.
3250        let collected: alloc::vec::Vec<_> = rv.iter().copied().collect();
3251        assert_eq!(collected, alloc::vec![1, 2]);
3252    }
3253
3254    #[test]
3255    fn repeated_view_with_borrowed_str() {
3256        let data = alloc::string::String::from("hello world");
3257        let parts: alloc::vec::Vec<&str> = data.split_whitespace().collect();
3258        let rv = RepeatedView::new(parts);
3259        assert_eq!(rv.len(), 2);
3260        assert_eq!(rv[0], "hello");
3261        assert_eq!(rv[1], "world");
3262    }
3263
3264    #[test]
3265    fn repeated_view_into_iter_by_ref() {
3266        let rv = RepeatedView::new(alloc::vec![1, 2, 3]);
3267        let sum: i32 = (&rv).into_iter().sum();
3268        assert_eq!(sum, 6);
3269        // `for x in &rv` syntax works:
3270        let mut count = 0;
3271        for _ in &rv {
3272            count += 1;
3273        }
3274        assert_eq!(count, 3);
3275    }
3276
3277    #[test]
3278    fn repeated_view_into_iter_by_value() {
3279        let rv = RepeatedView::new(alloc::vec![
3280            alloc::string::String::from("a"),
3281            alloc::string::String::from("b"),
3282        ]);
3283        let collected: alloc::vec::Vec<_> = rv.into_iter().collect();
3284        assert_eq!(collected, alloc::vec!["a".to_string(), "b".to_string()]);
3285    }
3286
3287    // ── MapView ──────────────────────────────────────────────────────────
3288
3289    #[test]
3290    fn map_view_get_with_borrow() {
3291        let mut mv = MapView::<&str, i32>::default();
3292        mv.push("apples", 3);
3293        mv.push("bananas", 5);
3294
3295        // Ergonomic: get("key") works via Borrow<str> on &str
3296        assert_eq!(mv.get("apples"), Some(&3));
3297        assert_eq!(mv.get("bananas"), Some(&5));
3298        assert_eq!(mv.get("oranges"), None);
3299
3300        // Old style still works
3301        assert_eq!(mv.get(&"apples"), Some(&3));
3302    }
3303
3304    #[test]
3305    fn map_view_contains_key_with_borrow() {
3306        let mut mv = MapView::<&str, i32>::default();
3307        mv.push("key", 1);
3308
3309        assert!(mv.contains_key("key"));
3310        assert!(!mv.contains_key("missing"));
3311    }
3312
3313    #[test]
3314    fn map_view_get_last_write_wins() {
3315        let mut mv = MapView::<&str, i32>::default();
3316        mv.push("x", 1);
3317        mv.push("x", 2);
3318        assert_eq!(mv.get("x"), Some(&2));
3319    }
3320
3321    #[test]
3322    fn map_view_iter_unique_dedups_last_write_wins() {
3323        let mut mv = MapView::<&str, i32>::default();
3324        mv.push("a", 1);
3325        mv.push("b", 2);
3326        mv.push("a", 3); // duplicate key — only this entry survives for "a"
3327        mv.push("c", 4);
3328        mv.push("b", 5); // duplicate key — only this entry survives for "b"
3329
3330        assert_eq!(mv.len(), 5, "iter() preserves all wire entries");
3331        assert_eq!(mv.len_unique(), 3, "len_unique() counts distinct keys");
3332
3333        let unique: alloc::vec::Vec<_> = mv.iter_unique().collect();
3334        assert_eq!(unique, [&("a", 3), &("c", 4), &("b", 5)]);
3335    }
3336
3337    #[test]
3338    fn map_view_iter_unique_all_duplicates() {
3339        let mut mv = MapView::<&str, i32>::default();
3340        mv.push("a", 1);
3341        mv.push("a", 2);
3342        mv.push("a", 3);
3343        assert_eq!(mv.len_unique(), 1);
3344        assert_eq!(
3345            mv.iter_unique().collect::<alloc::vec::Vec<_>>(),
3346            [&("a", 3)]
3347        );
3348    }
3349
3350    #[test]
3351    fn map_view_iter_unique_no_duplicates() {
3352        let mut mv = MapView::<i32, &str>::default();
3353        mv.push(1, "x");
3354        mv.push(2, "y");
3355        assert_eq!(mv.len_unique(), 2);
3356        assert_eq!(
3357            mv.iter_unique().collect::<alloc::vec::Vec<_>>(),
3358            [&(1, "x"), &(2, "y")]
3359        );
3360    }
3361
3362    #[test]
3363    fn map_view_iter_unique_empty() {
3364        let mv = MapView::<&str, i32>::default();
3365        assert_eq!(mv.len_unique(), 0);
3366        assert_eq!(mv.iter_unique().count(), 0);
3367    }
3368
3369    #[test]
3370    fn map_view_keys_and_values() {
3371        let mut mv = MapView::<&str, i32>::default();
3372        mv.push("a", 1);
3373        mv.push("b", 2);
3374        mv.push("c", 3);
3375
3376        let keys: alloc::vec::Vec<_> = mv.keys().copied().collect();
3377        assert_eq!(keys, alloc::vec!["a", "b", "c"]);
3378
3379        let values: alloc::vec::Vec<_> = mv.values().copied().collect();
3380        assert_eq!(values, alloc::vec![1, 2, 3]);
3381    }
3382
3383    #[test]
3384    fn map_view_keys_and_values_empty() {
3385        let mv = MapView::<&str, i32>::default();
3386        assert_eq!(mv.keys().count(), 0);
3387        assert_eq!(mv.values().count(), 0);
3388    }
3389
3390    #[test]
3391    fn map_view_into_iter_collect_to_hashmap() {
3392        let mut mv = MapView::<&str, i32>::default();
3393        mv.push("a", 1);
3394        mv.push("b", 2);
3395        mv.push("a", 3); // duplicate — last-write-wins on collect
3396        let m: crate::__private::HashMap<&str, i32> = mv.into_iter().collect();
3397        assert_eq!(m.len(), 2);
3398        assert_eq!(m.get("a"), Some(&3)); // last value kept
3399        assert_eq!(m.get("b"), Some(&2));
3400    }
3401
3402    // ── bytes_from_source ────────────────────────────────────────────────
3403
3404    #[test]
3405    fn bytes_from_source_none_copies() {
3406        let data: &[u8] = b"hello";
3407        let out = bytes_from_source(None, data);
3408        assert_eq!(&out[..], data);
3409        assert_ne!(out.as_ptr(), data.as_ptr()); // distinct allocation
3410    }
3411
3412    #[test]
3413    fn bytes_from_source_some_within_is_slice_ref() {
3414        let parent = Bytes::copy_from_slice(b"hello world");
3415        let slice = &parent[6..11];
3416        let out = bytes_from_source(Some(&parent), slice);
3417        assert_eq!(&out[..], b"world");
3418        // slice_ref shares the same backing storage — same pointer.
3419        assert_eq!(out.as_ptr(), slice.as_ptr());
3420    }
3421
3422    #[test]
3423    fn bytes_from_source_some_outside_falls_back_to_copy() {
3424        let parent = Bytes::copy_from_slice(b"hello");
3425        let outside: &[u8] = b"world"; // static, not in `parent`
3426        let out = bytes_from_source(Some(&parent), outside);
3427        assert_eq!(&out[..], b"world");
3428        assert_ne!(out.as_ptr(), outside.as_ptr());
3429    }
3430
3431    #[test]
3432    fn bytes_from_source_empty_returns_new() {
3433        let parent = Bytes::copy_from_slice(b"hello");
3434        assert!(bytes_from_source(Some(&parent), &[]).is_empty());
3435        assert!(bytes_from_source(None, &[]).is_empty());
3436    }
3437
3438    #[test]
3439    fn bytes_from_source_full_range() {
3440        let parent = Bytes::copy_from_slice(b"hello");
3441        let out = bytes_from_source(Some(&parent), &parent[..]);
3442        assert_eq!(out.as_ptr(), parent.as_ptr());
3443        assert_eq!(out.len(), parent.len());
3444    }
3445
3446    // ── UnknownFieldsView ────────────────────────────────────────────────
3447
3448    #[test]
3449    fn unknown_fields_view_new_is_empty() {
3450        let uf = UnknownFieldsView::new();
3451        assert!(uf.is_empty());
3452        assert_eq!(uf.encoded_len(), 0);
3453    }
3454
3455    #[test]
3456    fn unknown_fields_view_push_raw_and_encoded_len() {
3457        let mut uf = UnknownFieldsView::new();
3458        uf.push_raw(&[0x08, 0x01]); // field 1, varint 1
3459        uf.push_raw(&[0x10, 0x02]); // field 2, varint 2
3460        assert!(!uf.is_empty());
3461        assert_eq!(uf.encoded_len(), 4);
3462    }
3463
3464    #[test]
3465    fn unknown_fields_view_to_owned_single_field() {
3466        // Build a valid unknown field: tag for field 99, varint wire type,
3467        // value 42.  Tag = (99 << 3) | 0 = 792 = varint bytes [0x98, 0x06].
3468        let span: &[u8] = &[0x98, 0x06, 0x2A];
3469        let mut uf = UnknownFieldsView::new();
3470        uf.push_raw(span);
3471
3472        let owned = uf.to_owned().expect("valid wire data");
3473        assert_eq!(owned.len(), 1);
3474        let field = owned.iter().next().unwrap();
3475        assert_eq!(field.number, 99);
3476        assert_eq!(
3477            field.data,
3478            crate::unknown_fields::UnknownFieldData::Varint(42)
3479        );
3480    }
3481
3482    #[test]
3483    fn unknown_fields_view_to_owned_multiple_fields() {
3484        let mut uf = UnknownFieldsView::new();
3485        // Field 1, varint, value 7:  tag = (1<<3)|0 = 0x08, value = 0x07
3486        uf.push_raw(&[0x08, 0x07]);
3487        // Field 2, fixed32, value 0x01020304:
3488        //   tag = (2<<3)|5 = 0x15, then 4 LE bytes
3489        uf.push_raw(&[0x15, 0x04, 0x03, 0x02, 0x01]);
3490
3491        let owned = uf.to_owned().expect("valid wire data");
3492        assert_eq!(owned.len(), 2);
3493
3494        let mut it = owned.iter();
3495        let f1 = it.next().unwrap();
3496        assert_eq!(f1.number, 1);
3497        assert_eq!(f1.data, crate::unknown_fields::UnknownFieldData::Varint(7));
3498
3499        let f2 = it.next().unwrap();
3500        assert_eq!(f2.number, 2);
3501        assert_eq!(
3502            f2.data,
3503            crate::unknown_fields::UnknownFieldData::Fixed32(0x01020304)
3504        );
3505    }
3506
3507    #[test]
3508    fn unknown_fields_view_to_owned_malformed_returns_error() {
3509        // A truncated tag (high continuation bit, then EOF).
3510        let mut uf = UnknownFieldsView::new();
3511        uf.push_raw(&[0x80]);
3512        assert!(uf.to_owned().is_err());
3513    }
3514
3515    #[test]
3516    fn unknown_fields_view_to_owned_includes_synthetic_varint_records() {
3517        let ctx = record_ctx(1);
3518        let mut uf = UnknownFieldsView::new();
3519        uf.push_varint(3, 99, ctx).unwrap();
3520        assert_eq!(ctx.remaining_unknown_fields(), 0);
3521
3522        let owned = uf.to_owned().expect("owned unknown field");
3523        let fields: Vec<_> = owned.iter().collect();
3524        assert_eq!(fields.len(), 1);
3525        assert_eq!(fields[0].number, 3);
3526        assert!(matches!(
3527            fields[0].data,
3528            crate::UnknownFieldData::Varint(99)
3529        ));
3530    }
3531
3532    // ── OwnedView ──────────────────────────────────────────────────────
3533
3534    // Minimal types to test OwnedView without depending on generated code.
3535
3536    use crate::message::Message;
3537
3538    /// A trivial "message" for the owned side of the view contract.
3539    #[derive(Clone, Debug, Default, PartialEq)]
3540    struct SimpleMessage {
3541        pub id: i32,
3542        pub name: alloc::string::String,
3543    }
3544
3545    impl crate::DefaultInstance for SimpleMessage {
3546        fn default_instance() -> &'static Self {
3547            static INST: crate::__private::OnceBox<SimpleMessage> =
3548                crate::__private::OnceBox::new();
3549            INST.get_or_init(|| alloc::boxed::Box::new(SimpleMessage::default()))
3550        }
3551    }
3552
3553    impl crate::Message for SimpleMessage {
3554        fn compute_size(&self, _cache: &mut crate::SizeCache) -> u32 {
3555            let mut size = 0u32;
3556            if self.id != 0 {
3557                size += 1 + crate::types::int32_encoded_len(self.id) as u32;
3558            }
3559            if !self.name.is_empty() {
3560                size += 1 + crate::types::string_encoded_len(&self.name) as u32;
3561            }
3562            size
3563        }
3564
3565        fn write_to(&self, _cache: &mut crate::SizeCache, buf: &mut impl crate::EncodeSink) {
3566            if self.id != 0 {
3567                crate::encoding::Tag::new(1, crate::encoding::WireType::Varint).encode(buf);
3568                crate::types::encode_int32(self.id, buf);
3569            }
3570            if !self.name.is_empty() {
3571                crate::encoding::Tag::new(2, crate::encoding::WireType::LengthDelimited)
3572                    .encode(buf);
3573                crate::types::encode_string(&self.name, buf);
3574            }
3575        }
3576
3577        fn merge_field(
3578            &mut self,
3579            tag: crate::encoding::Tag,
3580            buf: &mut impl bytes::Buf,
3581            _ctx: crate::DecodeContext<'_>,
3582        ) -> Result<(), DecodeError> {
3583            match tag.field_number() {
3584                1 => self.id = crate::types::decode_int32(buf)?,
3585                2 => crate::types::merge_string(&mut self.name, buf)?,
3586                _ => crate::encoding::skip_field(tag, buf)?,
3587            }
3588            Ok(())
3589        }
3590
3591        fn clear(&mut self) {
3592            self.id = 0;
3593            self.name.clear();
3594        }
3595    }
3596
3597    /// A zero-copy view of `SimpleMessage`. Borrows `name` as `&str`.
3598    #[derive(Clone, Debug, Default, PartialEq)]
3599    struct SimpleMessageView<'a> {
3600        pub id: i32,
3601        pub name: &'a str,
3602    }
3603
3604    // Via the exported macro, which doubles as its unit test.
3605    crate::impl_view_reborrow!(SimpleMessageView);
3606
3607    impl<'a> MessageView<'a> for SimpleMessageView<'a> {
3608        type Owned = SimpleMessage;
3609        fn merge_view_field(
3610            &mut self,
3611            _tag: crate::encoding::Tag,
3612            cur: &'a [u8],
3613            _before_tag: &'a [u8],
3614            _ctx: crate::DecodeContext<'_>,
3615        ) -> Result<&'a [u8], DecodeError> {
3616            Ok(cur)
3617        }
3618
3619        fn decode_view(buf: &'a [u8]) -> Result<Self, DecodeError> {
3620            let mut view = SimpleMessageView::default();
3621            let mut cursor: &'a [u8] = buf;
3622            while !cursor.is_empty() {
3623                let tag = crate::encoding::Tag::decode(&mut cursor)?;
3624                match tag.field_number() {
3625                    1 => view.id = crate::types::decode_int32(&mut cursor)?,
3626                    2 => view.name = crate::types::borrow_str(&mut cursor)?,
3627                    _ => crate::encoding::skip_field(tag, &mut cursor)?,
3628                }
3629            }
3630            Ok(view)
3631        }
3632
3633        fn to_owned_message(&self) -> Result<SimpleMessage, DecodeError> {
3634            Ok(SimpleMessage {
3635                id: self.id,
3636                name: self.name.into(),
3637            })
3638        }
3639    }
3640
3641    impl<'a> ViewEncode<'a> for SimpleMessageView<'a> {
3642        fn compute_size(&self, _cache: &mut crate::SizeCache) -> u32 {
3643            let mut size = 0u32;
3644            if self.id != 0 {
3645                size += 1 + crate::types::int32_encoded_len(self.id) as u32;
3646            }
3647            if !self.name.is_empty() {
3648                size += 1 + crate::types::string_encoded_len(self.name) as u32;
3649            }
3650            size
3651        }
3652
3653        fn write_to(&self, _cache: &mut crate::SizeCache, buf: &mut impl crate::EncodeSink) {
3654            if self.id != 0 {
3655                crate::encoding::Tag::new(1, crate::encoding::WireType::Varint).encode(buf);
3656                crate::types::encode_int32(self.id, buf);
3657            }
3658            if !self.name.is_empty() {
3659                crate::encoding::Tag::new(2, crate::encoding::WireType::LengthDelimited)
3660                    .encode(buf);
3661                crate::types::encode_string(self.name, buf);
3662            }
3663        }
3664    }
3665
3666    /// Encode a SimpleMessage to Bytes for testing.
3667    fn encode_simple(id: i32, name: &str) -> Bytes {
3668        let msg = SimpleMessage {
3669            id,
3670            name: name.into(),
3671        };
3672        Bytes::from(msg.encode_to_vec())
3673    }
3674
3675    #[test]
3676    fn owned_view_decode_and_reborrow() {
3677        let bytes = encode_simple(42, "hello");
3678        let view = OwnedView::<SimpleMessageView<'static>>::decode(bytes).unwrap();
3679
3680        // Field access via reborrow — the borrow is tied to `view`.
3681        assert_eq!(view.reborrow().id, 42);
3682        assert_eq!(view.reborrow().name, "hello");
3683    }
3684
3685    #[test]
3686    fn owned_view_to_owned_message() {
3687        let bytes = encode_simple(7, "world");
3688        let view = OwnedView::<SimpleMessageView<'static>>::decode(bytes).unwrap();
3689        let owned = view.to_owned_message();
3690
3691        assert_eq!(owned.id, 7);
3692        assert_eq!(owned.name, "world");
3693    }
3694
3695    /// A view whose `to_owned_message` breaks the wire-decode ⇒ convert
3696    /// contract, standing in for a buggy hand-written impl.
3697    #[derive(Clone, Debug, Default, PartialEq)]
3698    struct ContractBreakingView<'a>(core::marker::PhantomData<&'a ()>);
3699
3700    crate::impl_view_reborrow!(ContractBreakingView);
3701
3702    impl<'a> MessageView<'a> for ContractBreakingView<'a> {
3703        type Owned = SimpleMessage;
3704        fn merge_view_field(
3705            &mut self,
3706            _tag: crate::encoding::Tag,
3707            cur: &'a [u8],
3708            _before_tag: &'a [u8],
3709            _ctx: crate::DecodeContext<'_>,
3710        ) -> Result<&'a [u8], DecodeError> {
3711            Ok(cur)
3712        }
3713        fn decode_view(_buf: &'a [u8]) -> Result<Self, DecodeError> {
3714            Ok(Self(core::marker::PhantomData))
3715        }
3716        fn to_owned_message(&self) -> Result<SimpleMessage, DecodeError> {
3717            Err(DecodeError::UnknownFieldLimitExceeded)
3718        }
3719    }
3720
3721    #[test]
3722    #[should_panic(expected = "wire-decode => convert contract")]
3723    fn owned_view_panics_when_impl_breaks_convert_contract() {
3724        // The infallible signature rests on the decode ⇒ convert invariant;
3725        // an impl that violates it must fail loudly, not silently.
3726        let view = OwnedView::<ContractBreakingView<'static>>::decode(Bytes::new()).unwrap();
3727        let _ = view.to_owned_message();
3728    }
3729
3730    #[test]
3731    fn owned_view_debug_delegates_to_view() {
3732        let bytes = encode_simple(1, "test");
3733        let view = OwnedView::<SimpleMessageView<'static>>::decode(bytes).unwrap();
3734        let debug = alloc::format!("{:?}", view);
3735        assert!(debug.contains("test"));
3736        assert!(debug.contains("1"));
3737    }
3738
3739    #[test]
3740    fn owned_view_bytes_accessor() {
3741        let bytes = encode_simple(5, "data");
3742        let original_len = bytes.len();
3743        let view = OwnedView::<SimpleMessageView<'static>>::decode(bytes).unwrap();
3744
3745        assert_eq!(view.bytes().len(), original_len);
3746    }
3747
3748    #[test]
3749    fn owned_view_into_bytes_recovers_buffer() {
3750        let bytes = encode_simple(99, "recover");
3751        let expected = bytes.clone();
3752        let view = OwnedView::<SimpleMessageView<'static>>::decode(bytes).unwrap();
3753        let recovered = view.into_bytes();
3754
3755        assert_eq!(recovered, expected);
3756    }
3757
3758    #[test]
3759    fn owned_view_decode_invalid_data_returns_error() {
3760        // Truncated varint
3761        let bad = Bytes::from_static(&[0x08, 0x80]);
3762        let result = OwnedView::<SimpleMessageView<'static>>::decode(bad);
3763        assert!(result.is_err());
3764    }
3765
3766    #[test]
3767    fn owned_view_empty_message() {
3768        let bytes = Bytes::from_static(&[]);
3769        let view = OwnedView::<SimpleMessageView<'static>>::decode(bytes).unwrap();
3770        assert_eq!(view.reborrow().id, 0);
3771        assert_eq!(view.reborrow().name, "");
3772    }
3773
3774    #[test]
3775    fn owned_view_is_send_and_sync() {
3776        fn assert_send_sync<T: Send + Sync>() {}
3777        assert_send_sync::<OwnedView<SimpleMessageView<'static>>>();
3778    }
3779
3780    #[test]
3781    fn owned_view_from_owned_roundtrips() {
3782        let msg = SimpleMessage {
3783            id: 99,
3784            name: "roundtrip".into(),
3785        };
3786        let view = OwnedView::<SimpleMessageView<'static>>::from_owned(&msg).expect("from_owned");
3787        assert_eq!(view.reborrow().id, 99);
3788        assert_eq!(view.reborrow().name, "roundtrip");
3789
3790        let back = view.to_owned_message();
3791        assert_eq!(back, msg);
3792    }
3793
3794    #[test]
3795    fn owned_view_decode_with_options() {
3796        let bytes = encode_simple(42, "opts");
3797        let opts = crate::DecodeOptions::new().with_max_message_size(1024);
3798        let view =
3799            OwnedView::<SimpleMessageView<'static>>::decode_with_options(bytes, &opts).unwrap();
3800        assert_eq!(view.reborrow().id, 42);
3801        assert_eq!(view.reborrow().name, "opts");
3802    }
3803
3804    #[test]
3805    fn owned_view_decode_with_options_rejects_oversized() {
3806        let bytes = encode_simple(42, "too large");
3807        let opts = crate::DecodeOptions::new().with_max_message_size(2);
3808        let result = OwnedView::<SimpleMessageView<'static>>::decode_with_options(bytes, &opts);
3809        assert!(result.is_err());
3810    }
3811
3812    #[test]
3813    fn owned_view_clone_survives_original_drop() {
3814        let bytes = encode_simple(42, "cloned");
3815        let view = OwnedView::<SimpleMessageView<'static>>::decode(bytes).unwrap();
3816        let cloned = view.clone();
3817        drop(view); // drop original — clone must still be valid
3818        assert_eq!(cloned.reborrow().id, 42);
3819        assert_eq!(cloned.reborrow().name, "cloned");
3820    }
3821
3822    #[test]
3823    fn owned_view_clone_equality() {
3824        let bytes = encode_simple(42, "eq");
3825        let view = OwnedView::<SimpleMessageView<'static>>::decode(bytes).unwrap();
3826        let cloned = view.clone();
3827        assert_eq!(view, cloned);
3828    }
3829
3830    #[test]
3831    fn owned_view_eq_same_data() {
3832        let a = OwnedView::<SimpleMessageView<'static>>::decode(encode_simple(1, "x")).unwrap();
3833        let b = OwnedView::<SimpleMessageView<'static>>::decode(encode_simple(1, "x")).unwrap();
3834        assert_eq!(a, b);
3835    }
3836
3837    #[test]
3838    fn owned_view_ne_different_data() {
3839        let a = OwnedView::<SimpleMessageView<'static>>::decode(encode_simple(1, "x")).unwrap();
3840        let b = OwnedView::<SimpleMessageView<'static>>::decode(encode_simple(2, "y")).unwrap();
3841        assert_ne!(a, b);
3842    }
3843
3844    #[test]
3845    fn owned_view_into_bytes_after_clone() {
3846        let bytes = encode_simple(42, "test");
3847        let expected = bytes.clone();
3848        let view = OwnedView::<SimpleMessageView<'static>>::decode(bytes).unwrap();
3849        let cloned = view.clone();
3850        drop(view); // drop original first
3851        let recovered = cloned.into_bytes();
3852        assert_eq!(recovered, expected);
3853    }
3854
3855    // The `owned_view_drop*` and `owned_view_into_bytes*` names below are
3856    // the filter for the `Miri (OwnedView soundness)` CI step; a renamed or
3857    // differently named test silently leaves that gate.
3858    #[test]
3859    fn owned_view_drop_count() {
3860        use core::sync::atomic::{AtomicUsize, Ordering};
3861
3862        static DROP_COUNT: AtomicUsize = AtomicUsize::new(0);
3863
3864        /// A wrapper view that counts drops.
3865        struct DropCountingView<'a> {
3866            inner: SimpleMessageView<'a>,
3867        }
3868
3869        impl Drop for DropCountingView<'_> {
3870            fn drop(&mut self) {
3871                DROP_COUNT.fetch_add(1, Ordering::SeqCst);
3872            }
3873        }
3874
3875        impl<'a> MessageView<'a> for DropCountingView<'a> {
3876            type Owned = SimpleMessage;
3877            fn merge_view_field(
3878                &mut self,
3879                _tag: crate::encoding::Tag,
3880                cur: &'a [u8],
3881                _before_tag: &'a [u8],
3882                _ctx: crate::DecodeContext<'_>,
3883            ) -> Result<&'a [u8], DecodeError> {
3884                Ok(cur)
3885            }
3886
3887            fn decode_view(buf: &'a [u8]) -> Result<Self, DecodeError> {
3888                Ok(DropCountingView {
3889                    inner: SimpleMessageView::decode_view(buf)?,
3890                })
3891            }
3892
3893            fn to_owned_message(&self) -> Result<SimpleMessage, DecodeError> {
3894                self.inner.to_owned_message()
3895            }
3896        }
3897
3898        // Test normal drop: view drops exactly once.
3899        DROP_COUNT.store(0, Ordering::SeqCst);
3900        {
3901            let bytes = encode_simple(1, "drop");
3902            let _view = OwnedView::<DropCountingView<'static>>::decode(bytes).unwrap();
3903        }
3904        assert_eq!(DROP_COUNT.load(Ordering::SeqCst), 1, "normal drop");
3905
3906        // Test into_bytes: view drops exactly once.
3907        DROP_COUNT.store(0, Ordering::SeqCst);
3908        {
3909            let bytes = encode_simple(2, "into");
3910            let view = OwnedView::<DropCountingView<'static>>::decode(bytes).unwrap();
3911            let _bytes = view.into_bytes();
3912        }
3913        assert_eq!(DROP_COUNT.load(Ordering::SeqCst), 1, "into_bytes drop");
3914    }
3915
3916    /// Dropping an `OwnedView` that arrived as a by-value argument frees the
3917    /// buffer inside a call that still holds the view's forged `'static`
3918    /// borrows. Under Miri's field retagging that is UB unless the view is
3919    /// behind `MaybeDangling`, so this is a Miri regression test (it cannot
3920    /// fail under plain `cargo test`).
3921    #[test]
3922    fn owned_view_drop_by_value_argument() {
3923        fn consume<V>(v: OwnedView<V>) {
3924            drop(v);
3925        }
3926        let view =
3927            OwnedView::<SimpleMessageView<'static>>::decode(encode_simple(4, "arg")).unwrap();
3928        consume(view);
3929    }
3930
3931    /// A `V::drop` that panics during `into_bytes` must not drop the view a
3932    /// second time on the way out.
3933    #[cfg(feature = "std")]
3934    #[test]
3935    fn owned_view_into_bytes_unwinding_view_drop_runs_once() {
3936        use core::sync::atomic::{AtomicUsize, Ordering};
3937
3938        static DROP_COUNT: AtomicUsize = AtomicUsize::new(0);
3939
3940        /// Panics on its first drop only: a re-entrant second drop must not
3941        /// panic again, or the unwind would abort the process instead of
3942        /// reaching the assertion below.
3943        struct PanicOnFirstDropView<'a> {
3944            inner: SimpleMessageView<'a>,
3945            /// A heap allocation, so that a regression to dropping the view
3946            /// twice is a real double free (which Miri flags), not just a
3947            /// count of two.
3948            _owned: alloc::string::String,
3949        }
3950
3951        impl Drop for PanicOnFirstDropView<'_> {
3952            fn drop(&mut self) {
3953                if DROP_COUNT.fetch_add(1, Ordering::SeqCst) == 0 {
3954                    panic!("first drop");
3955                }
3956            }
3957        }
3958
3959        impl<'a> MessageView<'a> for PanicOnFirstDropView<'a> {
3960            type Owned = SimpleMessage;
3961            fn merge_view_field(
3962                &mut self,
3963                _tag: crate::encoding::Tag,
3964                cur: &'a [u8],
3965                _before_tag: &'a [u8],
3966                _ctx: crate::DecodeContext<'_>,
3967            ) -> Result<&'a [u8], DecodeError> {
3968                Ok(cur)
3969            }
3970
3971            fn decode_view(buf: &'a [u8]) -> Result<Self, DecodeError> {
3972                Ok(PanicOnFirstDropView {
3973                    inner: SimpleMessageView::decode_view(buf)?,
3974                    _owned: alloc::string::String::from("owned"),
3975                })
3976            }
3977
3978            fn to_owned_message(&self) -> Result<SimpleMessage, DecodeError> {
3979                self.inner.to_owned_message()
3980            }
3981        }
3982
3983        DROP_COUNT.store(0, Ordering::SeqCst);
3984        let bytes = encode_simple(3, "unwind");
3985        let view = OwnedView::<PanicOnFirstDropView<'static>>::decode(bytes).unwrap();
3986        let result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| view.into_bytes()));
3987        assert!(result.is_err(), "the view's panic must propagate");
3988        assert_eq!(
3989            DROP_COUNT.load(Ordering::SeqCst),
3990            1,
3991            "view dropped exactly once"
3992        );
3993    }
3994
3995    #[test]
3996    fn owned_view_name_borrows_from_bytes_buffer() {
3997        let bytes = encode_simple(42, "borrowed");
3998        let view = OwnedView::<SimpleMessageView<'static>>::decode(bytes).unwrap();
3999        let buf = view.bytes();
4000        let buf_start = buf.as_ptr() as usize;
4001        let buf_end = buf_start + buf.len();
4002        let name_ptr = view.reborrow().name.as_ptr() as usize;
4003        assert!(
4004            (buf_start..buf_end).contains(&name_ptr),
4005            "view name should point into the Bytes buffer"
4006        );
4007    }
4008
4009    #[test]
4010    fn owned_view_concurrent_read() {
4011        use alloc::sync::Arc;
4012
4013        let bytes = encode_simple(42, "concurrent");
4014        let view = Arc::new(OwnedView::<SimpleMessageView<'static>>::decode(bytes).unwrap());
4015        let handles: alloc::vec::Vec<_> = (0..4)
4016            .map(|_| {
4017                let v = Arc::clone(&view);
4018                std::thread::spawn(move || {
4019                    assert_eq!(v.reborrow().id, 42);
4020                    assert_eq!(v.reborrow().name, "concurrent");
4021                })
4022            })
4023            .collect();
4024        for h in handles {
4025            h.join().unwrap();
4026        }
4027    }
4028
4029    #[test]
4030    fn owned_view_from_parts_roundtrip() {
4031        let bytes = encode_simple(42, "parts");
4032        // Decode a view from the bytes, then wrap via from_parts.
4033        // SAFETY: `view` was decoded from `bytes`.
4034        let view = unsafe {
4035            let slice: &'static [u8] = core::mem::transmute::<&[u8], &'static [u8]>(&bytes);
4036            let decoded = SimpleMessageView::decode_view(slice).unwrap();
4037            OwnedView::<SimpleMessageView<'static>>::from_parts(bytes, decoded)
4038        };
4039        assert_eq!(view.reborrow().id, 42);
4040        assert_eq!(view.reborrow().name, "parts");
4041    }
4042
4043    // ── ViewReborrow / OwnedView::reborrow ───────────────────────────────
4044
4045    #[test]
4046    fn reborrow_fields_match_original() {
4047        let bytes = encode_simple(7, "hello");
4048        let owned = OwnedView::<SimpleMessageView<'static>>::decode(bytes).unwrap();
4049        let reborrowed: &SimpleMessageView<'_> = owned.reborrow();
4050        assert_eq!(reborrowed.id, 7);
4051        assert_eq!(reborrowed.name, "hello");
4052        // The reborrowed &str must point into the Bytes buffer, not a copy.
4053        let buf_start = owned.bytes().as_ptr() as usize;
4054        let buf_end = buf_start + owned.bytes().len();
4055        assert!((buf_start..buf_end).contains(&(reborrowed.name.as_ptr() as usize)));
4056    }
4057
4058    #[test]
4059    fn reborrow_does_not_consume_owned_view() {
4060        let bytes = encode_simple(1, "world");
4061        let owned = OwnedView::<SimpleMessageView<'static>>::decode(bytes).unwrap();
4062        let r1: &SimpleMessageView<'_> = owned.reborrow();
4063        let r2: &SimpleMessageView<'_> = owned.reborrow();
4064        assert_eq!(r1.name, r2.name);
4065        // `owned` still usable here
4066        assert_eq!(owned.reborrow().name, "world");
4067    }
4068    // ── Lazy views ───────────────────────────────────────────────────────
4069
4070    /// Hand-written lazy view of `SimpleMessage`, shaped like generated
4071    /// `FooLazyView` code: scalars borrowed, one flat scan, fragment merge.
4072    #[derive(Clone, Debug, Default, PartialEq)]
4073    struct SimpleLazyView<'a> {
4074        pub id: i32,
4075        pub name: &'a str,
4076    }
4077
4078    impl<'a> LazyMessageView<'a> for SimpleLazyView<'a> {
4079        type Owned = SimpleMessage;
4080
4081        fn decode_lazy(buf: &'a [u8]) -> Result<Self, DecodeError> {
4082            let limit = core::cell::Cell::new(crate::DEFAULT_UNKNOWN_FIELD_LIMIT);
4083            Self::decode_lazy_with_ctx(
4084                buf,
4085                crate::DecodeContext::new(crate::RECURSION_LIMIT, &limit),
4086            )
4087        }
4088
4089        fn decode_lazy_with_ctx(
4090            buf: &'a [u8],
4091            ctx: crate::DecodeContext<'_>,
4092        ) -> Result<Self, DecodeError> {
4093            let mut view = SimpleLazyView::default();
4094            view.merge_lazy(buf, ctx)?;
4095            Ok(view)
4096        }
4097
4098        fn merge_lazy(
4099            &mut self,
4100            buf: &'a [u8],
4101            ctx: crate::DecodeContext<'_>,
4102        ) -> Result<(), DecodeError> {
4103            let mut cursor: &'a [u8] = buf;
4104            while !cursor.is_empty() {
4105                let tag = crate::encoding::Tag::decode(&mut cursor)?;
4106                match tag.field_number() {
4107                    1 => self.id = crate::types::decode_int32(&mut cursor)?,
4108                    2 => self.name = crate::types::borrow_str(&mut cursor)?,
4109                    _ => crate::encoding::skip_field_depth(tag, &mut cursor, ctx.depth())?,
4110                }
4111            }
4112            Ok(())
4113        }
4114
4115        fn to_owned_message(&self) -> Result<SimpleMessage, DecodeError> {
4116            Ok(SimpleMessage {
4117                id: self.id,
4118                name: self.name.into(),
4119            })
4120        }
4121    }
4122
4123    fn full_budget_ctx(cell: &core::cell::Cell<usize>) -> crate::DecodeContext<'_> {
4124        crate::DecodeContext::new(crate::RECURSION_LIMIT, cell)
4125    }
4126
4127    #[test]
4128    fn lazy_message_field_view_decodes_on_access() {
4129        let bytes = encode_simple(42, "lazy");
4130        let unset = LazyMessageFieldView::<SimpleLazyView<'_>>::unset();
4131        assert!(unset.is_unset());
4132        assert!(unset.fragments().is_empty());
4133        assert!(unset.get().unwrap().is_none());
4134        assert_eq!(unset.get_or_default().unwrap(), SimpleLazyView::default());
4135
4136        let lazy = LazyMessageFieldView::<SimpleLazyView<'_>>::from_bytes(&bytes);
4137        assert!(lazy.is_set());
4138        assert_eq!(lazy.fragments(), &[&bytes[..]]);
4139        let v = lazy.get().unwrap().expect("set");
4140        assert_eq!((v.id, v.name), (42, "lazy"));
4141        // Re-decodes each call (no cache).
4142        assert_eq!(lazy.get().unwrap().unwrap().id, 42);
4143        assert_eq!(v.to_owned_message().unwrap().name, "lazy");
4144    }
4145
4146    #[test]
4147    fn lazy_message_field_view_merges_fragments() {
4148        // A singular message field split across wire occurrences must merge:
4149        // fragment 1 sets `name`, fragment 2 sets `id`; the merged view has
4150        // both, matching the eager/owned decoders.
4151        let frag1 = encode_simple(0, "from-frag-1");
4152        let frag2 = encode_simple(7, "");
4153        let cell = core::cell::Cell::new(crate::DEFAULT_UNKNOWN_FIELD_LIMIT);
4154
4155        let mut lazy = LazyMessageFieldView::<SimpleLazyView<'_>>::unset();
4156        lazy.push_fragment(&frag1, full_budget_ctx(&cell));
4157        assert_eq!(lazy.fragments().len(), 1);
4158        lazy.push_fragment(&frag2, full_budget_ctx(&cell));
4159        assert_eq!(lazy.fragments(), &[&frag1[..], &frag2[..]]);
4160
4161        let v = lazy.get().unwrap().expect("set");
4162        assert_eq!((v.id, v.name), (7, "from-frag-1"));
4163
4164        // Later fragments overwrite singular scalars (last-wins).
4165        let frag3 = encode_simple(9, "final");
4166        lazy.push_fragment(&frag3, full_budget_ctx(&cell));
4167        assert_eq!(lazy.fragments().len(), 3);
4168        let v = lazy.get().unwrap().expect("set");
4169        assert_eq!((v.id, v.name), (9, "final"));
4170    }
4171
4172    #[test]
4173    fn lazy_message_field_view_records_smallest_budgets() {
4174        // Budgets recorded across pushes are min-combined, and the recorded
4175        // allowance replays per access (capture-then-replay).
4176        let bytes = encode_simple(1, "x");
4177        let cell_big = core::cell::Cell::new(500);
4178        let cell_small = core::cell::Cell::new(3);
4179
4180        let mut lazy = LazyMessageFieldView::<SimpleLazyView<'_>>::unset();
4181        lazy.push_fragment(&bytes, crate::DecodeContext::new(80, &cell_big));
4182        lazy.push_fragment(&bytes, crate::DecodeContext::new(50, &cell_small));
4183        // Decoding succeeds — SimpleLazyView has no unknowns or nesting here;
4184        // the recorded budgets only bound what access may consume.
4185        assert!(lazy.get().unwrap().is_some());
4186    }
4187
4188    #[test]
4189    fn lazy_message_field_view_clone_default_debug() {
4190        let bytes = encode_simple(1, "x");
4191        let cell = core::cell::Cell::new(crate::DEFAULT_UNKNOWN_FIELD_LIMIT);
4192        let mut lazy = LazyMessageFieldView::<SimpleLazyView<'_>>::default();
4193        assert!(lazy.is_unset());
4194        lazy.push_fragment(&bytes, full_budget_ctx(&cell));
4195        lazy.push_fragment(&bytes, full_budget_ctx(&cell));
4196        let cloned = lazy.clone();
4197        assert_eq!(cloned.fragments(), lazy.fragments());
4198        let dbg = alloc::format!("{lazy:?}");
4199        assert!(dbg.contains("is_set: true"), "{dbg}");
4200        assert!(dbg.contains("fragments: 2"), "{dbg}");
4201    }
4202
4203    #[test]
4204    fn lazy_message_field_view_malformed_errors_on_access() {
4205        // 0xFF starts a tag whose varint never terminates — invalid.
4206        let malformed = [0xFFu8; 3];
4207        let lazy = LazyMessageFieldView::<SimpleLazyView<'_>>::from_bytes(&malformed);
4208        // Deferred validation: construction succeeds, access fails.
4209        assert!(lazy.is_set());
4210        assert!(lazy.get().is_err());
4211    }
4212
4213    #[test]
4214    fn lazy_repeated_view_decodes_per_element() {
4215        let b0 = encode_simple(1, "a");
4216        let b1 = encode_simple(2, "b");
4217        let cell = core::cell::Cell::new(crate::DEFAULT_UNKNOWN_FIELD_LIMIT);
4218        let mut rep = LazyRepeatedView::<SimpleLazyView<'_>>::new();
4219        assert!(rep.is_empty());
4220        rep.push_bytes(&b0, full_budget_ctx(&cell));
4221        rep.push_bytes(&b1, full_budget_ctx(&cell));
4222        assert_eq!(rep.len(), 2);
4223        assert_eq!(rep.raw_elements(), &[&b0[..], &b1[..]]);
4224        assert_eq!(rep.get(0).unwrap().unwrap().name, "a");
4225        assert_eq!(rep.get(1).unwrap().unwrap().id, 2);
4226        assert!(rep.get(2).is_none());
4227    }
4228
4229    #[test]
4230    fn lazy_repeated_view_iter() {
4231        let bufs: alloc::vec::Vec<Bytes> = (1..=3)
4232            .map(|i| encode_simple(i, core::str::from_utf8(&[b'a' + i as u8]).unwrap()))
4233            .collect();
4234        let cell = core::cell::Cell::new(crate::DEFAULT_UNKNOWN_FIELD_LIMIT);
4235        let mut rep = LazyRepeatedView::<SimpleLazyView<'_>>::new();
4236        for b in &bufs {
4237            rep.push_bytes(b, full_budget_ctx(&cell));
4238        }
4239
4240        let iter = rep.iter();
4241        assert_eq!(iter.len(), 3);
4242        let ids: alloc::vec::Vec<i32> = iter.map(|r| r.unwrap().id).collect();
4243        assert_eq!(ids, [1, 2, 3]);
4244
4245        // IntoIterator for &LazyRepeatedView.
4246        let names: alloc::vec::Vec<&str> = (&rep).into_iter().map(|r| r.unwrap().name).collect();
4247        assert_eq!(names, ["b", "c", "d"]);
4248
4249        // DoubleEndedIterator.
4250        let rev_ids: alloc::vec::Vec<i32> = rep.iter().rev().map(|r| r.unwrap().id).collect();
4251        assert_eq!(rev_ids, [3, 2, 1]);
4252    }
4253
4254    #[test]
4255    fn lazy_repeated_view_iter_surfaces_element_errors() {
4256        let good = encode_simple(1, "ok");
4257        let malformed = [0xFFu8; 3];
4258        let cell = core::cell::Cell::new(crate::DEFAULT_UNKNOWN_FIELD_LIMIT);
4259        let mut rep = LazyRepeatedView::<SimpleLazyView<'_>>::new();
4260        rep.push_bytes(&good, full_budget_ctx(&cell));
4261        rep.push_bytes(&malformed, full_budget_ctx(&cell));
4262        let results: alloc::vec::Vec<_> = rep.iter().collect();
4263        assert!(results[0].is_ok());
4264        assert!(results[1].is_err());
4265        let cloned = rep.clone();
4266        assert_eq!(cloned.len(), 2);
4267    }
4268
4269    // ── Encode-side 2 GiB guard tests ──────────────────────────────────
4270
4271    /// Test double whose `compute_size` reports a caller-chosen value and
4272    /// whose `write_to` writes nothing — exercises the over-limit paths
4273    /// without materializing gigabytes.
4274    #[derive(Clone, Debug, Default, PartialEq)]
4275    struct SizedView {
4276        reported_size: u32,
4277    }
4278
4279    impl<'a> MessageView<'a> for SizedView {
4280        type Owned = SimpleMessage;
4281        fn merge_view_field(
4282            &mut self,
4283            _tag: crate::encoding::Tag,
4284            cur: &'a [u8],
4285            _before_tag: &'a [u8],
4286            _ctx: crate::DecodeContext<'_>,
4287        ) -> Result<&'a [u8], DecodeError> {
4288            Ok(cur)
4289        }
4290        fn decode_view(_buf: &'a [u8]) -> Result<Self, DecodeError> {
4291            Ok(Self::default())
4292        }
4293        fn to_owned_message(&self) -> Result<SimpleMessage, DecodeError> {
4294            Ok(SimpleMessage::default())
4295        }
4296    }
4297
4298    impl<'a> ViewEncode<'a> for SizedView {
4299        fn compute_size(&self, _cache: &mut crate::SizeCache) -> u32 {
4300            self.reported_size
4301        }
4302        fn write_to(&self, _cache: &mut crate::SizeCache, _buf: &mut impl EncodeSink) {}
4303    }
4304
4305    const OVER_LIMIT: u32 = crate::MAX_MESSAGE_BYTES + 1;
4306
4307    /// View double over the shared [`SizedMsg`](crate::test_doubles::SizedMsg)
4308    /// owned double, so `OwnedView::from_owned` can hit the over-limit
4309    /// encode path without materializing gigabytes.
4310    #[derive(Clone, Debug, Default, PartialEq)]
4311    struct SizedOwnedView;
4312
4313    impl<'a> MessageView<'a> for SizedOwnedView {
4314        type Owned = crate::test_doubles::SizedMsg;
4315        fn merge_view_field(
4316            &mut self,
4317            _tag: crate::encoding::Tag,
4318            cur: &'a [u8],
4319            _before_tag: &'a [u8],
4320            _ctx: crate::DecodeContext<'_>,
4321        ) -> Result<&'a [u8], DecodeError> {
4322            Ok(cur)
4323        }
4324        fn decode_view(_buf: &'a [u8]) -> Result<Self, DecodeError> {
4325            Ok(Self)
4326        }
4327        fn to_owned_message(&self) -> Result<crate::test_doubles::SizedMsg, DecodeError> {
4328            Ok(crate::test_doubles::SizedMsg::default())
4329        }
4330    }
4331
4332    #[test]
4333    fn owned_view_from_owned_over_limit_errs_not_panics() {
4334        // from_owned is a Result-returning API: an over-limit message must
4335        // surface as Err(MessageTooLarge), never a panic from the interior
4336        // encode.
4337        let msg = crate::test_doubles::SizedMsg {
4338            reported_size: OVER_LIMIT,
4339        };
4340        let res = OwnedView::<SizedOwnedView>::from_owned(&msg);
4341        assert!(matches!(res, Err(DecodeError::MessageTooLarge)));
4342    }
4343
4344    #[test]
4345    #[should_panic(expected = "2 GiB protobuf limit")]
4346    fn view_encode_over_limit_panics() {
4347        let view = SizedView {
4348            reported_size: OVER_LIMIT,
4349        };
4350        let mut buf = alloc::vec::Vec::new();
4351        view.encode(&mut buf);
4352    }
4353
4354    #[test]
4355    #[should_panic(expected = "2 GiB protobuf limit")]
4356    fn view_encoded_len_over_limit_panics() {
4357        let view = SizedView {
4358            reported_size: OVER_LIMIT,
4359        };
4360        let _ = view.encoded_len();
4361    }
4362
4363    #[test]
4364    #[should_panic(expected = "2 GiB protobuf limit")]
4365    fn view_encode_length_delimited_over_limit_panics() {
4366        let view = SizedView {
4367            reported_size: OVER_LIMIT,
4368        };
4369        let mut buf = alloc::vec::Vec::new();
4370        view.encode_length_delimited(&mut buf);
4371    }
4372
4373    #[test]
4374    #[should_panic(expected = "2 GiB protobuf limit")]
4375    fn view_encode_to_vec_over_limit_panics() {
4376        let view = SizedView {
4377            reported_size: OVER_LIMIT,
4378        };
4379        let _ = view.encode_to_vec();
4380    }
4381
4382    #[test]
4383    #[should_panic(expected = "2 GiB protobuf limit")]
4384    fn view_encode_to_bytes_over_limit_panics() {
4385        let view = SizedView {
4386            reported_size: OVER_LIMIT,
4387        };
4388        let _ = view.encode_to_bytes();
4389    }
4390
4391    #[test]
4392    #[should_panic(expected = "2 GiB protobuf limit")]
4393    fn view_encode_with_cache_over_limit_panics() {
4394        let view = SizedView {
4395            reported_size: OVER_LIMIT,
4396        };
4397        let mut cache = crate::SizeCache::new();
4398        let mut buf = alloc::vec::Vec::new();
4399        view.encode_with_cache(&mut cache, &mut buf);
4400    }
4401
4402    #[cfg(debug_assertions)]
4403    #[test]
4404    #[should_panic(expected = "two-pass traversal mismatch")]
4405    fn view_encode_to_vec_ledger_catches_size_write_disagreement() {
4406        // An under-limit reported size with a no-op write_to: the guard
4407        // passes, then the debug ledger flags the two-pass divergence.
4408        let view = SizedView { reported_size: 3 };
4409        let _ = view.encode_to_vec();
4410    }
4411
4412    #[test]
4413    fn view_try_encode_over_limit_errors_and_writes_nothing() {
4414        let view = SizedView {
4415            reported_size: OVER_LIMIT,
4416        };
4417        let mut buf = alloc::vec::Vec::new();
4418        assert_eq!(
4419            view.try_encode(&mut buf),
4420            Err(crate::EncodeError::MessageTooLarge)
4421        );
4422        assert!(buf.is_empty(), "no bytes may reach the buffer on Err");
4423        let mut cache = crate::SizeCache::new();
4424        assert_eq!(
4425            view.try_encode_with_cache(&mut cache, &mut buf),
4426            Err(crate::EncodeError::MessageTooLarge)
4427        );
4428        assert!(buf.is_empty(), "no bytes may reach the buffer on Err");
4429        assert_eq!(
4430            view.try_encode_length_delimited(&mut buf),
4431            Err(crate::EncodeError::MessageTooLarge)
4432        );
4433        assert!(buf.is_empty(), "not even the length prefix");
4434        assert_eq!(
4435            view.try_encode_to_vec(),
4436            Err(crate::EncodeError::MessageTooLarge)
4437        );
4438        assert_eq!(
4439            view.try_encode_to_bytes(),
4440            Err(crate::EncodeError::MessageTooLarge)
4441        );
4442        assert_eq!(
4443            view.try_encoded_len(),
4444            Err(crate::EncodeError::MessageTooLarge)
4445        );
4446    }
4447
4448    #[test]
4449    fn view_try_encode_matches_encode_for_normal_views() {
4450        let view = SimpleMessageView {
4451            id: 42,
4452            name: "hello",
4453        };
4454        let mut expected = alloc::vec::Vec::new();
4455        view.encode(&mut expected);
4456        let mut actual = alloc::vec::Vec::new();
4457        view.try_encode(&mut actual).unwrap();
4458        assert_eq!(actual, expected);
4459        assert_eq!(view.try_encode_to_vec().unwrap(), expected);
4460        assert_eq!(view.try_encode_to_bytes().unwrap(), expected);
4461        assert_eq!(view.try_encoded_len().unwrap(), expected.len() as u32);
4462    }
4463
4464    #[test]
4465    fn view_try_encode_bounded_within_budget_encodes_and_returns_len() {
4466        let view = SimpleMessageView {
4467            id: 42,
4468            name: "hello",
4469        };
4470        let mut expected = alloc::vec::Vec::new();
4471        view.encode(&mut expected);
4472        let budget = expected.len() as u32;
4473
4474        let mut buf = alloc::vec::Vec::new();
4475        let len = view.try_encode_bounded(budget, &mut buf).unwrap();
4476        assert_eq!(buf, expected);
4477        assert_eq!(len, budget);
4478
4479        // with_cache variant agrees
4480        let mut cache = crate::SizeCache::new();
4481        let mut buf2 = alloc::vec::Vec::new();
4482        let len2 = view
4483            .try_encode_bounded_with_cache(budget, &mut cache, &mut buf2)
4484            .unwrap();
4485        assert_eq!(buf2, expected);
4486        assert_eq!(len2, budget);
4487    }
4488
4489    #[test]
4490    fn view_try_encode_bounded_over_budget_errors_and_writes_nothing() {
4491        let view = SimpleMessageView {
4492            id: 42,
4493            name: "hello",
4494        };
4495        let len = view.encoded_len();
4496        let budget = len - 1;
4497
4498        let mut buf = alloc::vec::Vec::new();
4499        assert_eq!(
4500            view.try_encode_bounded(budget, &mut buf),
4501            Err(crate::EncodeError::ExceedsBudget {
4502                len,
4503                max_bytes: budget
4504            })
4505        );
4506        assert!(buf.is_empty(), "nothing written on budget exceeded");
4507    }
4508
4509    #[test]
4510    fn view_try_encode_bounded_over_protobuf_limit_errors_as_too_large() {
4511        let view = SizedView {
4512            reported_size: OVER_LIMIT,
4513        };
4514        let mut buf = alloc::vec::Vec::new();
4515        assert_eq!(
4516            view.try_encode_bounded(u32::MAX, &mut buf),
4517            Err(crate::EncodeError::MessageTooLarge)
4518        );
4519        assert!(buf.is_empty());
4520    }
4521
4522    #[test]
4523    fn pool_try_encode_view_bounded_within_budget_encodes_and_returns_len() {
4524        let view = SimpleMessageView {
4525            id: 7,
4526            name: "pooled",
4527        };
4528        let mut expected = alloc::vec::Vec::new();
4529        view.encode(&mut expected);
4530        let budget = expected.len() as u32;
4531
4532        let mut pool = crate::SizeCachePool::sequential(64);
4533        let mut buf = alloc::vec::Vec::new();
4534        let len = pool
4535            .try_encode_view_bounded(&view, budget, &mut buf)
4536            .unwrap();
4537        assert_eq!(buf, expected);
4538        assert_eq!(len, budget);
4539    }
4540
4541    #[test]
4542    fn pool_try_encode_view_bounded_over_budget_errors_and_buffer_returned() {
4543        let view = SimpleMessageView {
4544            id: 7,
4545            name: "pooled",
4546        };
4547        let len = view.encoded_len();
4548        let budget = len - 1;
4549
4550        let mut pool = crate::SizeCachePool::sequential(64);
4551        let mut buf = alloc::vec::Vec::new();
4552        assert_eq!(
4553            pool.try_encode_view_bounded(&view, budget, &mut buf),
4554            Err(crate::EncodeError::ExceedsBudget {
4555                len,
4556                max_bytes: budget
4557            })
4558        );
4559        assert!(buf.is_empty());
4560        // Pool buffer must be returned on Err — a subsequent call must succeed.
4561        assert_eq!(
4562            pool.try_encode_view_bounded(&view, len, &mut buf).unwrap(),
4563            len
4564        );
4565    }
4566}
4567
4568#[cfg(test)]
4569mod unknown_fields_view_repr {
4570    use super::UnknownFieldsView;
4571
4572    // Every generated view embeds this by value, so it must stay pointer-sized
4573    // and hold no inline heap owner; otherwise views regress to being moved by
4574    // out-of-line `memcpy` rather than inline vector stores.
4575    #[test]
4576    fn handle_is_pointer_sized() {
4577        assert_eq!(
4578            core::mem::size_of::<UnknownFieldsView<'_>>(),
4579            core::mem::size_of::<usize>()
4580        );
4581    }
4582
4583    // `UnknownFieldsView` is reachable from every generated view, so it is part
4584    // of the public surface downstream code puts in its own types.
4585    #[test]
4586    fn is_send_and_sync() {
4587        fn assert_send<T: Send>() {}
4588        fn assert_sync<T: Sync>() {}
4589        assert_send::<UnknownFieldsView<'_>>();
4590        assert_sync::<UnknownFieldsView<'_>>();
4591    }
4592
4593    // The manual `Debug` impl exists to keep `last_tail` — which runs to the end
4594    // of the input buffer — out of the output, while still showing the records.
4595    #[test]
4596    fn debug_shows_records_and_hides_the_coalescing_cursor() {
4597        let mut ufv = UnknownFieldsView::new();
4598        assert!(format!("{ufv:?}").contains("records: []"));
4599
4600        ufv.push_raw(&[0x08, 0x2a]);
4601        let rendered = format!("{ufv:?}");
4602        assert!(rendered.contains("records: [Borrowed("), "{rendered}");
4603        assert!(!rendered.contains("last_tail"), "{rendered}");
4604    }
4605}