Skip to main content

mediaframe/buffa/
mod.rs

1//! `buffa::Message` implementations for the mediaframe wire-relevant
2//! types, behind the `buffa` feature. Used via `extern_path` from
3//! buffa-generated crates so a `.proto`-defined message can embed a
4//! mediaframe type without redefining it.
5//!
6//! These are hand-written inherent-trait impls — there is **no**
7//! codegen and **no** `.proto` in this crate (mirrors the
8//! `mediatime` design). The module needs no re-export: the impls are
9//! `impl Trait for crate::Type`.
10//!
11//! # Wire format (clean redesign — no compatibility with any prior
12//! encoding is required)
13//!
14//! ## Enums (each is a standalone message = one field)
15//!
16//! ```text
17//! Matrix    { uint32 value = 1; }   // value = to_u32()
18//! Primaries { string value = 1; }
19//! Transfer  { string value = 1; }
20//! DynamicRange     { string value = 1; }
21//! ChromaLocation { string value = 1; }
22//! DcpTargetGamut { string value = 1; }
23//! Rotation       { string value = 1; }
24//! FieldOrder     { string value = 1; }
25//! StereoMode     { string value = 1; }
26//! PixelFormat    { string value = 1; }
27//! ```
28//!
29//! Each enum encodes its `as_str()` slug as a single `string` at
30//! field #1, decoded via `FromStr` — the same shape the codec family
31//! has always used. The slug is the spelling because `Other(Utf8Bytes)`
32//! is the crate's one extension idiom: a value this build does not
33//! name still has a *name*, and a number would not carry it.
34//!
35//! **Default-elision (not proto3 zero-elision):** the field is
36//! written iff `*self != <Ty>::default()`. The decoder seeds the
37//! message from `Default` (= FFmpeg `UNSPECIFIED` for the colour
38//! enums — code `2` for primaries/transfer/matrix, `0` for
39//! range/chroma), so an absent field decodes back to `Default`. A
40//! *present* field always carries the exact `to_u32()` code —
41//! **including code `0`** (`Matrix::Rgb`, FFmpeg
42//! `AVCOL_SPC_RGB`), which is *non-default* and therefore explicitly
43//! encoded, so it is never conflated with an absent field. Plain
44//! proto3 zero-elision would be **unsound** here (it would drop the
45//! non-default code-`0` `Rgb`); default-elision is exact for every
46//! value. Wrong wire type on field #1 →
47//! `DecodeError::WireTypeMismatch`; unknown fields are skipped via
48//! `skip_field_depth`.
49//!
50//! ## Structs
51//!
52//! ```text
53//! Dimensions        { uint32 width = 1; uint32 height = 2; }
54//! Rect              { uint32 x = 1; uint32 y = 2; uint32 width = 3; uint32 height = 4; }
55//! SampleAspectRatio { int64  num = 1; int64  den = 2; }          // both ALWAYS encoded
56//! Rational          { int64  num = 1; int64  den = 2; }          // both ALWAYS encoded
57//! FrameRate         { Rational rate = 1;                         // rate ALWAYS encoded
58//!                     bool     is_vfr = 2; }                     // proto3 zero-elision
59//! DolbyVisionConfig { uint32 profile = 1; uint32 level = 2;      // proto3 zero-elision
60//!                     bool rpu_present = 3; bool el_present = 4; //   (all-zero default)
61//!                     uint32 bl_signal_compat_id = 5; }
62//! Info         { Primaries primaries = 1;              // all five ALWAYS
63//!                     Transfer  transfer  = 2;              //   encoded as the
64//!                     Matrix    matrix    = 3;              //   bare uint32 id
65//!                     DynamicRange     range     = 4;              //   (not nested msgs)
66//!                     ChromaLocation chroma    = 5; }
67//! ContentLightLevel { uint32 max_cll = 1; uint32 max_fall = 2; }
68//! ChromaCoord       { uint32 x = 1; uint32 y = 2; }              // u16 widened to uint32
69//! MasteringDisplay  { ChromaCoord primary_r   = 1;               // ALWAYS encoded
70//!                     ChromaCoord primary_g   = 2;               // ALWAYS encoded
71//!                     ChromaCoord primary_b   = 3;               // ALWAYS encoded
72//!                     ChromaCoord white_point = 4;               // ALWAYS encoded
73//!                     uint32 max_luminance = 5;
74//!                     uint32 min_luminance = 6; }
75//! HdrStaticMetadata { MasteringDisplay  mastering     = 1;       // absent when None
76//!                     ContentLightLevel content_light = 2; }     // absent when None
77//! ```
78//!
79//! Field numbers follow declaration order. proto3 zero-elision is
80//! used **only** where the decoder seed (`DefaultInstance`, i.e.
81//! `Default`/`new`) is the proto-zero for that field
82//! (`Dimensions`, `Rect`, `ContentLightLevel`, `ChromaCoord`, the
83//! `*_luminance` scalars). Where `Default` ≠ proto-zero the field is
84//! **always encoded** (the `mediatime::Timebase` reasoning):
85//!
86//! - `SampleAspectRatio` — `Default` is `1:1`. `num`'s default is
87//!   `1` (≠ 0) and `den` is `NonZeroI64` (never 0), so eliding a
88//!   zero would mis-decode. Both fields are always written. On the
89//!   way back in, both halves are clamped into the range
90//!   `Rational::new` accepts, so decode stays total: a negative
91//!   `num` becomes `0`, and a `den` that is zero *or negative*
92//!   becomes `1`. Neither is producible by this encoder — a peer
93//!   reaches them either directly or by writing a `uint64` above
94//!   `i64::MAX`, which `decode_int64` reinterprets as negative.
95//!   (Before `Rational` became signed, `den` was `NonZeroU32` and
96//!   only the zero case existed.)
97//! - `Rational` — same shape / reasoning as `SampleAspectRatio`
98//!   (`Default` is `1/1`, `num` default `1`, `den` `NonZeroI64`):
99//!   both fields always encoded, malformed `num`/`den` clamped the
100//!   same way.
101//! - `FrameRate` — `rate` is an always-encoded length-delimited
102//!   `Rational` sub-message (its inner `Default` is `1/1` ≠
103//!   proto-zero, so the nested-message-always-encoded
104//!   `mediatime::Timebase` stance applies, like `MasteringDisplay`'s
105//!   coords); `is_vfr` defaults to `false` == proto-zero so it uses
106//!   proto3 zero-elision.
107//! - `Info` — **all five enum fields are always encoded** as
108//!   the bare FFmpeg-code `uint32` id (not a nested message); tags
109//!   #1–#5 are single-byte. `Info`'s own seed is
110//!   `Info::UNSPECIFIED` (every field FFmpeg `UNSPECIFIED`).
111//!   Always-encoding keeps the round-trip exact regardless of which
112//!   FFmpeg code a field holds — in particular `matrix ==
113//!   Matrix::Rgb` (FFmpeg code `0`) survives because the id is
114//!   written unconditionally, never elided — the same defensive
115//!   `mediatime::Timebase` always-encode stance.
116//! - `MasteringDisplay` — the three primaries and the white point
117//!   are always-encoded length-delimited sub-messages so presence
118//!   is unambiguous and `decode(encode(x)) == x` holds regardless of
119//!   `ChromaCoord` content (nested-message presence, like
120//!   `mediatime`'s always-encoded `Timebase`).
121//! - `HdrStaticMetadata` — the two `Option` fields are
122//!   presence-encoded length-delimited messages, omitted entirely
123//!   when `None`.
124//!
125//! Every `merge_field` rejects a wrong wire type with
126//! `DecodeError::WireTypeMismatch` and skips unknown fields with
127//! `skip_field_depth`; `clear()` resets to `Default` / `new`.
128//!
129//! ## Audio + container types
130//!
131//! ```text
132//! ChannelLayout        { string value = 1; }   // value = as_str()
133//! BitRateMode          { uint32 value = 1; }   // value = to_u32() (Cbr=0)
134//! ChannelOrder         { uint32 value = 1; }   // value = to_u32() (Unspecified=0)
135//! SampleFormat          { uint32 value = 1; }   // value = to_u32() (FFmpeg AV_SAMPLE_FMT_* code, Other → u32::MAX)
136//! ContainerFormat { string value = 1; }   // value = as_str()
137//! Format      { string value = 1; }   // value = as_str()
138//!
139//! ChannelSpec { uint32 index = 1; uint32 raw_id = 2; string label = 3; }
140//! ChannelLayoutDescription
141//!                  { uint32 order       = 1;   // ChannelOrder::to_u32()
142//!                    uint32 channels    = 2;
143//!                    string known_kind  = 3;   // ChannelLayout::as_str()
144//!                    optional uint64 native_mask = 4;
145//!                    repeated ChannelSpec custom_channels = 5;
146//!                    string text        = 6; }
147//!
148//! Loudness         { float integrated_lufs = 1; float range_lu = 2;
149//!                    float true_peak_dbtp = 3; float sample_peak_dbfs = 4; }
150//! ReplayGain       { float track_gain_db = 1; float track_peak = 2;
151//!                    optional float album_gain_db = 3;
152//!                    optional float album_peak = 4; }
153//! Fingerprint { string algorithm = 1; bytes value = 2; }     // algorithm ALWAYS encoded
154//! CoverArt    { string mime      = 1; bytes data  = 2; }     // both ALWAYS encoded
155//! Tags        { string title        = 1; string artist        = 2;
156//!                    string album_artist = 3; string album         = 4;
157//!                    string composer     = 5; string genre         = 6;
158//!                    string comment      = 7;
159//!                    uint32 year         = 8; uint32 track_number  = 9;
160//!                    uint32 track_total  = 10; uint32 disc_number   = 11;
161//!                    uint32 disc_total   = 12; string language      = 13; }
162//! ```
163//!
164//! - **String-bearing enums** (`ChannelLayout`, `ContainerFormat`,
165//!   `Format`, `SampleFormat`) encode their `as_str()` slug. Default
166//!   (where defined) elides; `Other(Utf8Bytes)` round-trips losslessly.
167//!   `BitRateMode` and `ChannelOrder` are strictly closed and encode
168//!   their `to_u32()` id. Zero-elision is sound for both: each one's
169//!   `Default` (`Cbr` / `Unspecified`) *is* code `0`, so an absent field
170//!   decodes back to it exactly — unlike the colour enums, where a
171//!   non-default variant holds code `0` and eliding it would be a
172//!   silent loss.
173//! - **`ChannelSpec`** — `index` / `raw_id` (`uint32`) and `label`
174//!   (`string`) all use proto3 zero-elision: the seed is
175//!   `ChannelSpec::default()`, whose three fields are `0`, `0` and the
176//!   empty string, which is proto-zero for each.
177//! - **`ChannelLayoutDescription`** — `order`, `channels`,
178//!   `known_kind` and `text` use proto3 zero-elision, sound for the
179//!   same reason: the seed is the type's `Default`, whose order is code
180//!   `0`, channel count `0`, name `ChannelLayout::default()` (the
181//!   `Other("")` sentinel, so `as_str()` is `""`) and text empty.
182//!   `known_kind` decodes through `ChannelLayout`'s total `FromStr`, so
183//!   a name this build does not enumerate arrives as `Other(name)`
184//!   rather than as a decode error — the open-vocabulary rule, applied
185//!   to a field instead of a standalone message.
186//!   `native_mask` is an `optional uint64` using presence encoding
187//!   (emitted iff `Some`, including for `Some(0)`, so a layout that
188//!   reports an all-zero mask stays distinct from one that reports
189//!   none). `custom_channels` is the crate's first **repeated** field:
190//!   one length-delimited `ChannelSpec` sub-message per element, in
191//!   order, and an empty list writes nothing. The decoder appends each
192//!   element as it arrives rather than reading the list out and writing
193//!   it back, which would make decode quadratic in a length the peer
194//!   chooses.
195//! - **`Loudness`** — all four `f32` fields use proto3 zero-elision
196//!   (`Default` is all-zero == proto-zero for `f32`). Each present
197//!   field is wire-type `Fixed32` (4 bytes LE).
198//! - **`ReplayGain`** — `track_gain_db` / `track_peak` use proto3
199//!   zero-elision (`Default` is all-zero == proto-zero for `f32`);
200//!   `album_gain_db` / `album_peak` are `optional float` so a
201//!   distribution-absent album-level number round-trips as `None`
202//!   (the wire field is absent rather than zero). Each present field
203//!   is wire-type `Fixed32` (4 bytes LE).
204//! - **`Fingerprint`** — `algorithm` is ALWAYS encoded
205//!   (`try_new` rejects empty, so a default-constructed wire-empty
206//!   `algorithm` would not be a valid `Fingerprint` — encoding
207//!   it explicitly preserves the invariant on the wire round-trip).
208//!   `value` (bytes) uses proto3 zero-elision (an empty fingerprint
209//!   is legal). The decoder seed is `try_new("default", []).unwrap()`
210//!   so that an absent `algorithm` decodes to a synthetic non-empty
211//!   placeholder rather than violating the type invariant.
212//! - **`CoverArt`** — both `mime` and `data` are ALWAYS encoded
213//!   (`try_new` rejects empty in either, so default-constructed
214//!   wire-empty fields would violate the invariant). Same
215//!   placeholder-seed strategy as `Fingerprint`.
216//! - **`Tags`** — string fields use proto3 zero-elision (the
217//!   empty string is the canonical "absent" value); numeric `u16`
218//!   fields are widened to `uint32` and use proto3 zero-elision —
219//!   `Some(0)` (legal value) and `None` (absent) **cannot be
220//!   distinguished on the wire** in this codec; both round-trip to
221//!   `None`. A future codec revision can switch to wrapper messages
222//!   if the distinction becomes load-bearing. `language` is the
223//!   canonical BCP 47 tag as a string; the empty string means the
224//!   `Option<LanguageId>` was `None`.
225//!
226//! ## Subtitle + disposition
227//!
228//! Three stream-vocab types from the `subtitle` + `disposition`
229//! modules. All three are standalone one-field messages:
230//!
231//! ```text
232//! Format      { string value = 1; }   // FFmpeg-style slug from `as_str()`
233//! TrackOrigin { string value = 1; }   // value = as_str()
234//! TrackDisposition    { uint32 bits  = 1; }   // bits = to_u32() (= raw bitflags bits)
235//! ```
236//!
237//! - **`Format`** — a closed-ish enum with an `Other(Utf8Bytes)`
238//!   escape arm has no stable numeric id, so it encodes the
239//!   FFmpeg-style slug (`"srt"` / `"webvtt"` / `"hdmv_pgs_subtitle"` /
240//!   …) as a `string`. The decoder funnels through `FromStr` (total —
241//!   unknown slugs land in `Other`). Default-elision: the default is
242//!   not proto-zero (`Srt` is the inhabited representative — though
243//!   the encoder treats *every* value as non-default and always
244//!   encodes, to side-step the issue entirely). In practice we
245//!   always-encode the slug so an empty string can never be conflated
246//!   with `Srt`; on decode an empty string maps to `Other("")`,
247//!   matching `FromStr`.
248//! - **`TrackOrigin`** — an open enum since 0.5.0 (`Other(Utf8Bytes)`),
249//!   so its stable ids no longer span the value space and it encodes
250//!   the slug as a `string`, like `Format` above. Always-encoded for
251//!   the same reason: the empty string is `Other("")` on decode, a
252//!   distinct legal value that eliding would conflate with an absent
253//!   field. **Wire-incompatible with 0.4.x**, which wrote a varint id
254//!   in this field.
255//! - **`TrackDisposition`** — bitflags. Encoded as the raw `u32`
256//!   bits at field #1, decoded via [`TrackDisposition::from_u32`]
257//!   (`from_bits_retain` semantics — unknown bits round-trip
258//!   losslessly). Default-elision is sound: the default is the
259//!   empty flag set whose `bits()` is `0` (proto-zero).
260//!
261//! ## Capture + language
262//!
263//! Three alloc-gated types from the `capture` + `lang` modules:
264//!
265//! ```text
266//! Device      { string make = 1; string model = 2; }     // proto3 zero-elision (empty == absent)
267//! GeoLocation { double lat = 1; double lon = 2;          // lat/lon ALWAYS encoded
268//!               float altitude = 3; }                     // altitude emitted iff Some
269//! LanguageId  { string value = 1; }                      // BCP 47 canonical tag; never elides
270//! ```
271//!
272//! - **`Device`** — two empty strings == proto-zero, so proto3
273//!   zero-elision is sound. Empty string is the in-rust sentinel
274//!   for "absent" (matches the same convention used by `Tags`).
275//! - **`GeoLocation`** — the `(0.0, 0.0)` "Null Island" default is a
276//!   real, legal coordinate, so proto3 zero-elision on `lat`/`lon`
277//!   would be **unsound** (it would lose the Null-Island record).
278//!   Both fields are always encoded; the optional `altitude` field
279//!   uses presence encoding (emitted iff `Some`, including for
280//!   `Some(0.0)` so sea-level distinct from absent altitude). Same
281//!   defensive stance as `SampleAspectRatio`.
282//! - **`LanguageId`** — encoded as the canonical BCP 47 tag, which is
283//!   what `Display` writes and `LanguageId::new` reads back. Default
284//!   is `"und"` (ISO 639-3 undetermined), the value a muxer writes
285//!   when it looked and could not tell; the wire uses default-elision
286//!   (an absent field decodes to `und`), and since `"und"` is not the
287//!   empty string the encoder always writes it.
288//!
289//!   A wire string the door refuses coerces to `LanguageId::default()`
290//!   (`und`) — `buffa::DecodeError` has no general "invalid value" arm,
291//!   and the type's sentinel is the right fallback. That path is much
292//!   NARROWER than it used to be: the door is WIDE IN, so an mkv's
293//!   `ger` reaches `de`, a variant or private-use tail rides the
294//!   fourth seat verbatim, and only a structurally impossible tag
295//!   (`en-US-!!`, `日本語`) still falls back.
296
297use core::num::NonZeroI64;
298// `LanguageId`'s wire form is the canonical tag its `Display` writes, and the
299// `ToString` that reaches it is not in the prelude on a `no_std` + `alloc`
300// build — which the `buffa` feature is, since it implies `alloc` and not `std`.
301use std::string::ToString;
302
303use ::buffa::{
304  DecodeContext, DecodeError, DefaultInstance, EncodeSink, Message, SizeCache,
305  bytes::Buf,
306  encoding::{Tag, WireType, encode_varint, skip_field_depth, varint_len},
307  types::{
308    FIXED32_ENCODED_LEN, bytes_encoded_len, decode_bytes, decode_double, decode_float,
309    decode_int64, decode_string, decode_uint32, decode_uint64, encode_bytes, encode_double,
310    encode_float, encode_int64, encode_string, encode_uint32, encode_uint64, int64_encoded_len,
311    string_encoded_len, uint32_encoded_len, uint64_encoded_len,
312  },
313};
314use smol_bytes::Utf8Bytes;
315
316use crate::{
317  audio::{
318    BitRateMode, ChannelLayout, ChannelLayoutDescription, ChannelOrder, ChannelSpec,
319    ContainerFormat, CoverArt, Fingerprint, Loudness, ReplayGain, SampleFormat, Tags,
320  },
321  capture::{Device, GeoLocation},
322  color::{
323    ChromaCoord, ChromaLocation, ContentLightLevel, DcpTargetGamut, DolbyVisionConfig,
324    DynamicRange, HdrStaticMetadata, Info, MasteringDisplay, Matrix, Primaries, Transfer,
325  },
326  container::Format,
327  disposition::TrackDisposition,
328  frame::{
329    DEN_ONE, Dimensions, FieldOrder, FrameRate, Rational, Rect, Rotation, SampleAspectRatio,
330    StereoMode,
331  },
332  lang::LanguageId,
333  pixel_format::PixelFormat,
334};
335
336const VARINT: u8 = WireType::Varint as u8;
337const LEN: u8 = WireType::LengthDelimited as u8;
338
339// The colour / frame / pixel-format vocabularies carry names, not numbers:
340// `Other(Utf8Bytes)` is the escape, so the slug is the only spelling that
341// survives a value this build has never heard of. They therefore ride the
342// same one-field `{ string value = 1; }` shape as the codec family — see
343// `impl_string_enum_message!` below. The declarations sit there, beside it.
344
345// ----------------------------------------------------------------------------
346// Dimensions — { uint32 width = 1; uint32 height = 2; }
347// Default is (0, 0) == proto-zero, so zero-elision is sound.
348// ----------------------------------------------------------------------------
349
350impl DefaultInstance for Dimensions {
351  fn default_instance() -> &'static Self {
352    static VALUE: buffa::__private::OnceBox<Dimensions> = buffa::__private::OnceBox::new();
353    VALUE.get_or_init(|| buffa::alloc::boxed::Box::new(Dimensions::default()))
354  }
355}
356
357impl Message for Dimensions {
358  fn compute_size(&self, _cache: &mut SizeCache) -> u32 {
359    let mut size = 0u32;
360    // proto3 zero-elision: sound — seed is Dimensions::default() = (0, 0).
361    if self.width() != 0 {
362      size += 1 + uint32_encoded_len(self.width()) as u32;
363    }
364    if self.height() != 0 {
365      size += 1 + uint32_encoded_len(self.height()) as u32;
366    }
367    size
368  }
369
370  fn write_to(&self, _cache: &mut SizeCache, buf: &mut impl EncodeSink) {
371    // proto3 zero-elision: sound — see `compute_size`.
372    if self.width() != 0 {
373      Tag::new(1, WireType::Varint).encode(buf);
374      encode_uint32(self.width(), buf);
375    }
376    if self.height() != 0 {
377      Tag::new(2, WireType::Varint).encode(buf);
378      encode_uint32(self.height(), buf);
379    }
380  }
381
382  fn merge_field(
383    &mut self,
384    tag: Tag,
385    buf: &mut impl Buf,
386    ctx: DecodeContext<'_>,
387  ) -> Result<(), DecodeError> {
388    match tag.field_number() {
389      1 => {
390        if tag.wire_type() != WireType::Varint {
391          return Err(DecodeError::WireTypeMismatch {
392            field_number: 1,
393            expected: VARINT,
394            actual: tag.wire_type() as u8,
395          });
396        }
397        let w = decode_uint32(buf)?;
398        self.set_width(w);
399      }
400      2 => {
401        if tag.wire_type() != WireType::Varint {
402          return Err(DecodeError::WireTypeMismatch {
403            field_number: 2,
404            expected: VARINT,
405            actual: tag.wire_type() as u8,
406          });
407        }
408        let h = decode_uint32(buf)?;
409        self.set_height(h);
410      }
411      _ => skip_field_depth(tag, buf, ctx.depth())?,
412    }
413    Ok(())
414  }
415
416  fn clear(&mut self) {
417    *self = Dimensions::default();
418  }
419}
420
421// ----------------------------------------------------------------------------
422// Rect — { uint32 x = 1; uint32 y = 2; uint32 width = 3; uint32 height = 4; }
423// Default is all-zero == proto-zero, so zero-elision is sound.
424// ----------------------------------------------------------------------------
425
426impl DefaultInstance for Rect {
427  fn default_instance() -> &'static Self {
428    static VALUE: buffa::__private::OnceBox<Rect> = buffa::__private::OnceBox::new();
429    VALUE.get_or_init(|| buffa::alloc::boxed::Box::new(Rect::default()))
430  }
431}
432
433impl Message for Rect {
434  fn compute_size(&self, _cache: &mut SizeCache) -> u32 {
435    let mut size = 0u32;
436    // proto3 zero-elision: sound — seed is Rect::default() = all-zero.
437    if self.x() != 0 {
438      size += 1 + uint32_encoded_len(self.x()) as u32;
439    }
440    if self.y() != 0 {
441      size += 1 + uint32_encoded_len(self.y()) as u32;
442    }
443    if self.width() != 0 {
444      size += 1 + uint32_encoded_len(self.width()) as u32;
445    }
446    if self.height() != 0 {
447      size += 1 + uint32_encoded_len(self.height()) as u32;
448    }
449    size
450  }
451
452  fn write_to(&self, _cache: &mut SizeCache, buf: &mut impl EncodeSink) {
453    // proto3 zero-elision: sound — see `compute_size`.
454    if self.x() != 0 {
455      Tag::new(1, WireType::Varint).encode(buf);
456      encode_uint32(self.x(), buf);
457    }
458    if self.y() != 0 {
459      Tag::new(2, WireType::Varint).encode(buf);
460      encode_uint32(self.y(), buf);
461    }
462    if self.width() != 0 {
463      Tag::new(3, WireType::Varint).encode(buf);
464      encode_uint32(self.width(), buf);
465    }
466    if self.height() != 0 {
467      Tag::new(4, WireType::Varint).encode(buf);
468      encode_uint32(self.height(), buf);
469    }
470  }
471
472  fn merge_field(
473    &mut self,
474    tag: Tag,
475    buf: &mut impl Buf,
476    ctx: DecodeContext<'_>,
477  ) -> Result<(), DecodeError> {
478    match tag.field_number() {
479      1 => {
480        if tag.wire_type() != WireType::Varint {
481          return Err(DecodeError::WireTypeMismatch {
482            field_number: 1,
483            expected: VARINT,
484            actual: tag.wire_type() as u8,
485          });
486        }
487        let v = decode_uint32(buf)?;
488        self.set_x(v);
489      }
490      2 => {
491        if tag.wire_type() != WireType::Varint {
492          return Err(DecodeError::WireTypeMismatch {
493            field_number: 2,
494            expected: VARINT,
495            actual: tag.wire_type() as u8,
496          });
497        }
498        let v = decode_uint32(buf)?;
499        self.set_y(v);
500      }
501      3 => {
502        if tag.wire_type() != WireType::Varint {
503          return Err(DecodeError::WireTypeMismatch {
504            field_number: 3,
505            expected: VARINT,
506            actual: tag.wire_type() as u8,
507          });
508        }
509        let v = decode_uint32(buf)?;
510        self.set_width(v);
511      }
512      4 => {
513        if tag.wire_type() != WireType::Varint {
514          return Err(DecodeError::WireTypeMismatch {
515            field_number: 4,
516            expected: VARINT,
517            actual: tag.wire_type() as u8,
518          });
519        }
520        let v = decode_uint32(buf)?;
521        self.set_height(v);
522      }
523      _ => skip_field_depth(tag, buf, ctx.depth())?,
524    }
525    Ok(())
526  }
527
528  fn clear(&mut self) {
529    *self = Rect::default();
530  }
531}
532
533// ----------------------------------------------------------------------------
534// SampleAspectRatio — { int64 num = 1; int64 den = 2; }
535//
536// `num`/`den` are encoded UNCONDITIONALLY — no proto3 zero elision.
537// The decoder seeds from `SampleAspectRatio::default()` (1:1), NOT
538// proto-zero. Eliding `num == 0` would decode back as `num == 1`;
539// `den` is `NonZeroI64` and can never legitimately be 0. (Exactly
540// the `mediatime::Timebase` reasoning.) Both tags are single-byte.
541//
542// The fields were `uint32` before `Rational` became signed and 64-bit.
543// Protobuf's `int64` and `uint32` are the same plain (non-ZigZag)
544// varint over the values a `SampleAspectRatio` can hold — non-negative
545// and, for anything a `uint32` peer wrote, at most `u32::MAX` — so the
546// bytes are unchanged in both directions and previously-encoded
547// payloads still decode. `sint64` would have been the silent break:
548// ZigZag re-encodes every value. Note the widening is one-way at the
549// edges: a value above `u32::MAX` is writable now and a `uint32`
550// reader would truncate it.
551// ----------------------------------------------------------------------------
552
553impl DefaultInstance for SampleAspectRatio {
554  fn default_instance() -> &'static Self {
555    static VALUE: buffa::__private::OnceBox<SampleAspectRatio> = buffa::__private::OnceBox::new();
556    VALUE.get_or_init(|| buffa::alloc::boxed::Box::new(SampleAspectRatio::default()))
557  }
558}
559
560impl Message for SampleAspectRatio {
561  fn compute_size(&self, _cache: &mut SizeCache) -> u32 {
562    2 + int64_encoded_len(self.num()) as u32 + int64_encoded_len(self.den().get()) as u32
563  }
564
565  fn write_to(&self, _cache: &mut SizeCache, buf: &mut impl EncodeSink) {
566    Tag::new(1, WireType::Varint).encode(buf);
567    encode_int64(self.num(), buf);
568    Tag::new(2, WireType::Varint).encode(buf);
569    encode_int64(self.den().get(), buf);
570  }
571
572  fn merge_field(
573    &mut self,
574    tag: Tag,
575    buf: &mut impl Buf,
576    ctx: DecodeContext<'_>,
577  ) -> Result<(), DecodeError> {
578    match tag.field_number() {
579      1 => {
580        if tag.wire_type() != WireType::Varint {
581          return Err(DecodeError::WireTypeMismatch {
582            field_number: 1,
583            expected: VARINT,
584            actual: tag.wire_type() as u8,
585          });
586        }
587        // `Rational::new` panics on a negative numerator, so decode
588        // must not hand it one. Our own encoder never writes a
589        // negative; a peer can, either directly or by writing a
590        // `uint64` above `i64::MAX` that `decode_int64` reinterprets
591        // into the negative half. Clamp to the smallest legal
592        // numerator so decode stays total, as `den` does.
593        let num = decode_int64(buf)?.max(0);
594        self.set_num(num);
595      }
596      2 => {
597        if tag.wire_type() != WireType::Varint {
598          return Err(DecodeError::WireTypeMismatch {
599            field_number: 2,
600            expected: VARINT,
601            actual: tag.wire_type() as u8,
602          });
603        }
604        // `den` is NonZeroI64; a malformed den — zero, or negative by
605        // the same route as `num` above — is clamped to 1. Since
606        // `NonZeroI64::MIN` is `i64::MIN`, the clamp target is spelled
607        // out as `DEN_ONE`. This is the same decode policy as
608        // `mediatime::Timebase`'s in the published `mediatime` extern
609        // that SAR mirrors, and upholds the codec family's
610        // total-scalar-decode invariant (scalar values never raise
611        // decode errors; only structural errors do). Codex
612        // adversarial-review F6: resolved as a coordinated
613        // mediatime/buffa policy, NOT a mediaframe-only divergence.
614        let den = NonZeroI64::new(decode_int64(buf)?)
615          .filter(|d| d.get() > 0)
616          .unwrap_or(DEN_ONE);
617        self.set_den(den);
618      }
619      _ => skip_field_depth(tag, buf, ctx.depth())?,
620    }
621    Ok(())
622  }
623
624  fn clear(&mut self) {
625    *self = SampleAspectRatio::default();
626  }
627}
628
629// ----------------------------------------------------------------------------
630// Rational — { int64 num = 1; int64 den = 2; }
631//
632// Same shape and reasoning as `SampleAspectRatio`, including the
633// `uint32` → `int64` widening being byte-compatible in both
634// directions: `num`/`den` are encoded UNCONDITIONALLY (no proto3
635// zero-elision). The decoder seeds from `Rational::default()` (1/1),
636// NOT proto-zero; eliding `num == 0` would decode back as `num == 1`.
637// `den` is `NonZeroI64` and can never legitimately be 0; a malformed
638// wire `den` — zero or negative — is clamped to 1 to keep decode
639// total, as is a negative `num`. Both tags are single-byte.
640// ----------------------------------------------------------------------------
641
642impl DefaultInstance for Rational {
643  fn default_instance() -> &'static Self {
644    static VALUE: buffa::__private::OnceBox<Rational> = buffa::__private::OnceBox::new();
645    VALUE.get_or_init(|| buffa::alloc::boxed::Box::new(Rational::default()))
646  }
647}
648
649impl Message for Rational {
650  fn compute_size(&self, _cache: &mut SizeCache) -> u32 {
651    2 + int64_encoded_len(self.num()) as u32 + int64_encoded_len(self.den().get()) as u32
652  }
653
654  fn write_to(&self, _cache: &mut SizeCache, buf: &mut impl EncodeSink) {
655    Tag::new(1, WireType::Varint).encode(buf);
656    encode_int64(self.num(), buf);
657    Tag::new(2, WireType::Varint).encode(buf);
658    encode_int64(self.den().get(), buf);
659  }
660
661  fn merge_field(
662    &mut self,
663    tag: Tag,
664    buf: &mut impl Buf,
665    ctx: DecodeContext<'_>,
666  ) -> Result<(), DecodeError> {
667    match tag.field_number() {
668      1 => {
669        if tag.wire_type() != WireType::Varint {
670          return Err(DecodeError::WireTypeMismatch {
671            field_number: 1,
672            expected: VARINT,
673            actual: tag.wire_type() as u8,
674          });
675        }
676        // A negative numerator would trip `Rational::new`'s assert;
677        // clamp as `SampleAspectRatio` does to keep decode total.
678        let num = decode_int64(buf)?.max(0);
679        self.set_num(num);
680      }
681      2 => {
682        if tag.wire_type() != WireType::Varint {
683          return Err(DecodeError::WireTypeMismatch {
684            field_number: 2,
685            expected: VARINT,
686            actual: tag.wire_type() as u8,
687          });
688        }
689        // `den` is NonZeroI64; a malformed 0 or negative on the wire
690        // (never produced by our own encoder) is clamped to 1 —
691        // identical to `SampleAspectRatio`'s decode, upholding the
692        // codec family's total-scalar-decode invariant.
693        let den = NonZeroI64::new(decode_int64(buf)?)
694          .filter(|d| d.get() > 0)
695          .unwrap_or(DEN_ONE);
696        self.set_den(den);
697      }
698      _ => skip_field_depth(tag, buf, ctx.depth())?,
699    }
700    Ok(())
701  }
702
703  fn clear(&mut self) {
704    *self = Rational::default();
705  }
706}
707
708// ----------------------------------------------------------------------------
709// FrameRate — { Rational rate = 1; bool is_vfr = 2; }
710//
711// `rate` is an always-encoded length-delimited `Rational`
712// sub-message: its inner `Default` is `1/1` ≠ proto-zero, so the
713// nested-message-always-encoded `mediatime::Timebase` stance applies
714// (like `MasteringDisplay`'s coords) — presence is unambiguous and
715// `decode(encode(x)) == x` holds regardless of the inner ratio.
716// `is_vfr` defaults to `false` == proto-zero, so it uses sound proto3
717// zero-elision (only `true` is written).
718// ----------------------------------------------------------------------------
719
720impl DefaultInstance for FrameRate {
721  fn default_instance() -> &'static Self {
722    static VALUE: buffa::__private::OnceBox<FrameRate> = buffa::__private::OnceBox::new();
723    VALUE.get_or_init(|| buffa::alloc::boxed::Box::new(FrameRate::default()))
724  }
725}
726
727impl Message for FrameRate {
728  fn compute_size(&self, cache: &mut SizeCache) -> u32 {
729    let mut size = 0u32;
730    // rate (field 1) — always-encoded nested message.
731    {
732      let slot = cache.reserve();
733      let inner = self.rate().compute_size(cache);
734      cache.set(slot, inner);
735      size += 1 + varint_len(inner as u64) as u32 + inner;
736    }
737    // proto3 zero-elision: sound — seed `is_vfr` is `false`.
738    if self.is_vfr() {
739      size += 1 + 1; // tag + single-byte bool varint
740    }
741    size
742  }
743
744  fn write_to(&self, cache: &mut SizeCache, buf: &mut impl EncodeSink) {
745    Tag::new(1, WireType::LengthDelimited).encode(buf);
746    encode_varint(cache.consume_next() as u64, buf);
747    self.rate().write_to(cache, buf);
748    // proto3 zero-elision: sound — see `compute_size`.
749    if self.is_vfr() {
750      Tag::new(2, WireType::Varint).encode(buf);
751      encode_varint(1, buf);
752    }
753  }
754
755  fn merge_field(
756    &mut self,
757    tag: Tag,
758    buf: &mut impl Buf,
759    ctx: DecodeContext<'_>,
760  ) -> Result<(), DecodeError> {
761    match tag.field_number() {
762      1 => {
763        if tag.wire_type() != WireType::LengthDelimited {
764          return Err(DecodeError::WireTypeMismatch {
765            field_number: 1,
766            expected: LEN,
767            actual: tag.wire_type() as u8,
768          });
769        }
770        let mut rate = self.rate();
771        buffa::Message::merge_length_delimited(&mut rate, buf, ctx)?;
772        self.set_rate(rate);
773      }
774      2 => {
775        if tag.wire_type() != WireType::Varint {
776          return Err(DecodeError::WireTypeMismatch {
777            field_number: 2,
778            expected: VARINT,
779            actual: tag.wire_type() as u8,
780          });
781        }
782        self.update_is_vfr(decode_uint32(buf)? != 0);
783      }
784      _ => skip_field_depth(tag, buf, ctx.depth())?,
785    }
786    Ok(())
787  }
788
789  fn clear(&mut self) {
790    *self = FrameRate::default();
791  }
792}
793
794// ----------------------------------------------------------------------------
795// DolbyVisionConfig — { uint32 profile = 1; uint32 level = 2;
796//                       bool rpu_present = 3; bool el_present = 4;
797//                       uint32 bl_signal_compat_id = 5; }
798//
799// `Default` is all-zero == proto-zero for every field, so proto3
800// zero-elision is sound throughout. `u8` fields widen to the `uint32`
801// wire scalar; bools are 0/1 varints.
802// ----------------------------------------------------------------------------
803
804impl DefaultInstance for DolbyVisionConfig {
805  fn default_instance() -> &'static Self {
806    static VALUE: buffa::__private::OnceBox<DolbyVisionConfig> = buffa::__private::OnceBox::new();
807    VALUE.get_or_init(|| buffa::alloc::boxed::Box::new(DolbyVisionConfig::default()))
808  }
809}
810
811impl Message for DolbyVisionConfig {
812  fn compute_size(&self, _cache: &mut SizeCache) -> u32 {
813    let mut size = 0u32;
814    // proto3 zero-elision: sound — seed is all-zero default.
815    if self.profile() != 0 {
816      size += 1 + uint32_encoded_len(self.profile() as u32) as u32;
817    }
818    if self.level() != 0 {
819      size += 1 + uint32_encoded_len(self.level() as u32) as u32;
820    }
821    if self.rpu_present() {
822      size += 1 + 1;
823    }
824    if self.el_present() {
825      size += 1 + 1;
826    }
827    if self.bl_signal_compat_id() != 0 {
828      size += 1 + uint32_encoded_len(self.bl_signal_compat_id() as u32) as u32;
829    }
830    size
831  }
832
833  fn write_to(&self, _cache: &mut SizeCache, buf: &mut impl EncodeSink) {
834    // proto3 zero-elision: sound — see `compute_size`.
835    if self.profile() != 0 {
836      Tag::new(1, WireType::Varint).encode(buf);
837      encode_uint32(self.profile() as u32, buf);
838    }
839    if self.level() != 0 {
840      Tag::new(2, WireType::Varint).encode(buf);
841      encode_uint32(self.level() as u32, buf);
842    }
843    if self.rpu_present() {
844      Tag::new(3, WireType::Varint).encode(buf);
845      encode_varint(1, buf);
846    }
847    if self.el_present() {
848      Tag::new(4, WireType::Varint).encode(buf);
849      encode_varint(1, buf);
850    }
851    if self.bl_signal_compat_id() != 0 {
852      Tag::new(5, WireType::Varint).encode(buf);
853      encode_uint32(self.bl_signal_compat_id() as u32, buf);
854    }
855  }
856
857  fn merge_field(
858    &mut self,
859    tag: Tag,
860    buf: &mut impl Buf,
861    ctx: DecodeContext<'_>,
862  ) -> Result<(), DecodeError> {
863    match tag.field_number() {
864      1 => {
865        if tag.wire_type() != WireType::Varint {
866          return Err(DecodeError::WireTypeMismatch {
867            field_number: 1,
868            expected: VARINT,
869            actual: tag.wire_type() as u8,
870          });
871        }
872        self.set_profile(decode_uint32(buf)? as u8);
873      }
874      2 => {
875        if tag.wire_type() != WireType::Varint {
876          return Err(DecodeError::WireTypeMismatch {
877            field_number: 2,
878            expected: VARINT,
879            actual: tag.wire_type() as u8,
880          });
881        }
882        self.set_level(decode_uint32(buf)? as u8);
883      }
884      3 => {
885        if tag.wire_type() != WireType::Varint {
886          return Err(DecodeError::WireTypeMismatch {
887            field_number: 3,
888            expected: VARINT,
889            actual: tag.wire_type() as u8,
890          });
891        }
892        self.update_rpu_present(decode_uint32(buf)? != 0);
893      }
894      4 => {
895        if tag.wire_type() != WireType::Varint {
896          return Err(DecodeError::WireTypeMismatch {
897            field_number: 4,
898            expected: VARINT,
899            actual: tag.wire_type() as u8,
900          });
901        }
902        self.update_el_present(decode_uint32(buf)? != 0);
903      }
904      5 => {
905        if tag.wire_type() != WireType::Varint {
906          return Err(DecodeError::WireTypeMismatch {
907            field_number: 5,
908            expected: VARINT,
909            actual: tag.wire_type() as u8,
910          });
911        }
912        self.set_bl_signal_compat_id(decode_uint32(buf)? as u8);
913      }
914      _ => skip_field_depth(tag, buf, ctx.depth())?,
915    }
916    Ok(())
917  }
918
919  fn clear(&mut self) {
920    *self = DolbyVisionConfig::default();
921  }
922}
923
924// ----------------------------------------------------------------------------
925// Info — five enum slugs, each a bare `string`, ALL always encoded.
926// See the module doc: always-encoding (esp. `matrix`, whose semantic
927// default is `Bt709`) decouples the wire round-trip from the field's own
928// default — the `mediatime` always-encode-nontrivial-default stance.
929// Tags #1–#5 single-byte. The slug is the spelling because the member
930// enums' only escape is `Other(Utf8Bytes)`.
931// ----------------------------------------------------------------------------
932
933impl DefaultInstance for Info {
934  fn default_instance() -> &'static Self {
935    static VALUE: buffa::__private::OnceBox<Info> = buffa::__private::OnceBox::new();
936    VALUE.get_or_init(|| buffa::alloc::boxed::Box::new(Info::UNSPECIFIED))
937  }
938}
939
940impl Message for Info {
941  fn compute_size(&self, _cache: &mut SizeCache) -> u32 {
942    // All five are unconditionally encoded (presence-independent).
943    5 + string_encoded_len(self.primaries().as_str()) as u32
944      + string_encoded_len(self.transfer().as_str()) as u32
945      + string_encoded_len(self.matrix().as_str()) as u32
946      + string_encoded_len(self.range().as_str()) as u32
947      + string_encoded_len(self.chroma_location().as_str()) as u32
948  }
949
950  fn write_to(&self, _cache: &mut SizeCache, buf: &mut impl EncodeSink) {
951    Tag::new(1, WireType::LengthDelimited).encode(buf);
952    encode_string(self.primaries().as_str(), buf);
953    Tag::new(2, WireType::LengthDelimited).encode(buf);
954    encode_string(self.transfer().as_str(), buf);
955    Tag::new(3, WireType::LengthDelimited).encode(buf);
956    encode_string(self.matrix().as_str(), buf);
957    Tag::new(4, WireType::LengthDelimited).encode(buf);
958    encode_string(self.range().as_str(), buf);
959    Tag::new(5, WireType::LengthDelimited).encode(buf);
960    encode_string(self.chroma_location().as_str(), buf);
961  }
962
963  fn merge_field(
964    &mut self,
965    tag: Tag,
966    buf: &mut impl Buf,
967    ctx: DecodeContext<'_>,
968  ) -> Result<(), DecodeError> {
969    match tag.field_number() {
970      1 => {
971        if tag.wire_type() != WireType::LengthDelimited {
972          return Err(DecodeError::WireTypeMismatch {
973            field_number: 1,
974            expected: LEN,
975            actual: tag.wire_type() as u8,
976          });
977        }
978        let s = decode_string(buf)?;
979        self.set_primaries(s.parse().unwrap_or_else(|_| unreachable!()));
980      }
981      2 => {
982        if tag.wire_type() != WireType::LengthDelimited {
983          return Err(DecodeError::WireTypeMismatch {
984            field_number: 2,
985            expected: LEN,
986            actual: tag.wire_type() as u8,
987          });
988        }
989        let s = decode_string(buf)?;
990        self.set_transfer(s.parse().unwrap_or_else(|_| unreachable!()));
991      }
992      3 => {
993        if tag.wire_type() != WireType::LengthDelimited {
994          return Err(DecodeError::WireTypeMismatch {
995            field_number: 3,
996            expected: LEN,
997            actual: tag.wire_type() as u8,
998          });
999        }
1000        let s = decode_string(buf)?;
1001        self.set_matrix(s.parse().unwrap_or_else(|_| unreachable!()));
1002      }
1003      4 => {
1004        if tag.wire_type() != WireType::LengthDelimited {
1005          return Err(DecodeError::WireTypeMismatch {
1006            field_number: 4,
1007            expected: LEN,
1008            actual: tag.wire_type() as u8,
1009          });
1010        }
1011        let s = decode_string(buf)?;
1012        self.set_range(s.parse().unwrap_or_else(|_| unreachable!()));
1013      }
1014      5 => {
1015        if tag.wire_type() != WireType::LengthDelimited {
1016          return Err(DecodeError::WireTypeMismatch {
1017            field_number: 5,
1018            expected: LEN,
1019            actual: tag.wire_type() as u8,
1020          });
1021        }
1022        let s = decode_string(buf)?;
1023        self.set_chroma_location(s.parse().unwrap_or_else(|_| unreachable!()));
1024      }
1025      _ => skip_field_depth(tag, buf, ctx.depth())?,
1026    }
1027    Ok(())
1028  }
1029
1030  fn clear(&mut self) {
1031    *self = Info::UNSPECIFIED;
1032  }
1033}
1034
1035// ----------------------------------------------------------------------------
1036// ContentLightLevel — { uint32 max_cll = 1; uint32 max_fall = 2; }
1037// Default is (0, 0) == proto-zero, so zero-elision is sound.
1038// ----------------------------------------------------------------------------
1039
1040impl DefaultInstance for ContentLightLevel {
1041  fn default_instance() -> &'static Self {
1042    static VALUE: buffa::__private::OnceBox<ContentLightLevel> = buffa::__private::OnceBox::new();
1043    VALUE.get_or_init(|| buffa::alloc::boxed::Box::new(ContentLightLevel::default()))
1044  }
1045}
1046
1047impl Message for ContentLightLevel {
1048  fn compute_size(&self, _cache: &mut SizeCache) -> u32 {
1049    let mut size = 0u32;
1050    // proto3 zero-elision: sound — seed is ContentLightLevel::default() = (0, 0).
1051    if self.max_cll() != 0 {
1052      size += 1 + uint32_encoded_len(self.max_cll()) as u32;
1053    }
1054    if self.max_fall() != 0 {
1055      size += 1 + uint32_encoded_len(self.max_fall()) as u32;
1056    }
1057    size
1058  }
1059
1060  fn write_to(&self, _cache: &mut SizeCache, buf: &mut impl EncodeSink) {
1061    // proto3 zero-elision: sound — see `compute_size`.
1062    if self.max_cll() != 0 {
1063      Tag::new(1, WireType::Varint).encode(buf);
1064      encode_uint32(self.max_cll(), buf);
1065    }
1066    if self.max_fall() != 0 {
1067      Tag::new(2, WireType::Varint).encode(buf);
1068      encode_uint32(self.max_fall(), buf);
1069    }
1070  }
1071
1072  fn merge_field(
1073    &mut self,
1074    tag: Tag,
1075    buf: &mut impl Buf,
1076    ctx: DecodeContext<'_>,
1077  ) -> Result<(), DecodeError> {
1078    match tag.field_number() {
1079      1 => {
1080        if tag.wire_type() != WireType::Varint {
1081          return Err(DecodeError::WireTypeMismatch {
1082            field_number: 1,
1083            expected: VARINT,
1084            actual: tag.wire_type() as u8,
1085          });
1086        }
1087        let v = decode_uint32(buf)?;
1088        self.set_max_cll(v);
1089      }
1090      2 => {
1091        if tag.wire_type() != WireType::Varint {
1092          return Err(DecodeError::WireTypeMismatch {
1093            field_number: 2,
1094            expected: VARINT,
1095            actual: tag.wire_type() as u8,
1096          });
1097        }
1098        let v = decode_uint32(buf)?;
1099        self.set_max_fall(v);
1100      }
1101      _ => skip_field_depth(tag, buf, ctx.depth())?,
1102    }
1103    Ok(())
1104  }
1105
1106  fn clear(&mut self) {
1107    *self = ContentLightLevel::default();
1108  }
1109}
1110
1111// ----------------------------------------------------------------------------
1112// ChromaCoord — { uint32 x = 1; uint32 y = 2; }
1113// `x`/`y` are `u32` storage == the wire scalar; every value (incl.
1114// out-of-range / future / corrupt) round-trips losslessly — no
1115// saturation (Codex adversarial-review F3).
1116// Default is (0, 0) == proto-zero, so zero-elision is sound.
1117// ----------------------------------------------------------------------------
1118
1119impl DefaultInstance for ChromaCoord {
1120  fn default_instance() -> &'static Self {
1121    static VALUE: buffa::__private::OnceBox<ChromaCoord> = buffa::__private::OnceBox::new();
1122    VALUE.get_or_init(|| buffa::alloc::boxed::Box::new(ChromaCoord::default()))
1123  }
1124}
1125
1126impl Message for ChromaCoord {
1127  fn compute_size(&self, _cache: &mut SizeCache) -> u32 {
1128    let mut size = 0u32;
1129    // proto3 zero-elision: sound — seed is ChromaCoord::default() = (0, 0).
1130    if self.x() != 0 {
1131      size += 1 + uint32_encoded_len(self.x()) as u32;
1132    }
1133    if self.y() != 0 {
1134      size += 1 + uint32_encoded_len(self.y()) as u32;
1135    }
1136    size
1137  }
1138
1139  fn write_to(&self, _cache: &mut SizeCache, buf: &mut impl EncodeSink) {
1140    // proto3 zero-elision: sound — see `compute_size`.
1141    if self.x() != 0 {
1142      Tag::new(1, WireType::Varint).encode(buf);
1143      encode_uint32(self.x(), buf);
1144    }
1145    if self.y() != 0 {
1146      Tag::new(2, WireType::Varint).encode(buf);
1147      encode_uint32(self.y(), buf);
1148    }
1149  }
1150
1151  fn merge_field(
1152    &mut self,
1153    tag: Tag,
1154    buf: &mut impl Buf,
1155    ctx: DecodeContext<'_>,
1156  ) -> Result<(), DecodeError> {
1157    match tag.field_number() {
1158      1 => {
1159        if tag.wire_type() != WireType::Varint {
1160          return Err(DecodeError::WireTypeMismatch {
1161            field_number: 1,
1162            expected: VARINT,
1163            actual: tag.wire_type() as u8,
1164          });
1165        }
1166        // u32 storage == wire scalar: preserved verbatim, no
1167        // saturation (Codex F3).
1168        self.set_x(decode_uint32(buf)?);
1169      }
1170      2 => {
1171        if tag.wire_type() != WireType::Varint {
1172          return Err(DecodeError::WireTypeMismatch {
1173            field_number: 2,
1174            expected: VARINT,
1175            actual: tag.wire_type() as u8,
1176          });
1177        }
1178        self.set_y(decode_uint32(buf)?);
1179      }
1180      _ => skip_field_depth(tag, buf, ctx.depth())?,
1181    }
1182    Ok(())
1183  }
1184
1185  fn clear(&mut self) {
1186    *self = ChromaCoord::default();
1187  }
1188}
1189
1190// ----------------------------------------------------------------------------
1191// MasteringDisplay — { ChromaCoord primary_r = 1; primary_g = 2;
1192//                      primary_b = 3; white_point = 4;
1193//                      uint32 max_luminance = 5; uint32 min_luminance = 6; }
1194//
1195// The four nested ChromaCoords are ALWAYS encoded (length-delimited)
1196// so presence is unambiguous and round-trip holds regardless of
1197// content (the `mediatime` always-encoded-nested-message stance).
1198// The two luminance scalars default to 0 == proto-zero so they use
1199// proto3 zero-elision.
1200// ----------------------------------------------------------------------------
1201
1202impl DefaultInstance for MasteringDisplay {
1203  fn default_instance() -> &'static Self {
1204    static VALUE: buffa::__private::OnceBox<MasteringDisplay> = buffa::__private::OnceBox::new();
1205    VALUE.get_or_init(|| buffa::alloc::boxed::Box::new(MasteringDisplay::default()))
1206  }
1207}
1208
1209impl Message for MasteringDisplay {
1210  fn compute_size(&self, cache: &mut SizeCache) -> u32 {
1211    let mut size = 0u32;
1212    let primaries = self.display_primaries();
1213    // primary_r / g / b (fields 1..=3) — always encoded.
1214    for cc in &primaries {
1215      let slot = cache.reserve();
1216      let inner = cc.compute_size(cache);
1217      cache.set(slot, inner);
1218      size += 1 + varint_len(inner as u64) as u32 + inner;
1219    }
1220    // white_point (field 4) — always encoded.
1221    {
1222      let slot = cache.reserve();
1223      let inner = self.white_point().compute_size(cache);
1224      cache.set(slot, inner);
1225      size += 1 + varint_len(inner as u64) as u32 + inner;
1226    }
1227    // proto3 zero-elision: sound — seed is MasteringDisplay::default(),
1228    // whose luminances are 0.
1229    if self.max_luminance() != 0 {
1230      size += 1 + uint32_encoded_len(self.max_luminance()) as u32;
1231    }
1232    if self.min_luminance() != 0 {
1233      size += 1 + uint32_encoded_len(self.min_luminance()) as u32;
1234    }
1235    size
1236  }
1237
1238  fn write_to(&self, cache: &mut SizeCache, buf: &mut impl EncodeSink) {
1239    let primaries = self.display_primaries();
1240    for (i, cc) in primaries.iter().enumerate() {
1241      Tag::new(1 + i as u32, WireType::LengthDelimited).encode(buf);
1242      encode_varint(cache.consume_next() as u64, buf);
1243      cc.write_to(cache, buf);
1244    }
1245    Tag::new(4, WireType::LengthDelimited).encode(buf);
1246    encode_varint(cache.consume_next() as u64, buf);
1247    self.white_point().write_to(cache, buf);
1248    // proto3 zero-elision: sound — see `compute_size`.
1249    if self.max_luminance() != 0 {
1250      Tag::new(5, WireType::Varint).encode(buf);
1251      encode_uint32(self.max_luminance(), buf);
1252    }
1253    if self.min_luminance() != 0 {
1254      Tag::new(6, WireType::Varint).encode(buf);
1255      encode_uint32(self.min_luminance(), buf);
1256    }
1257  }
1258
1259  fn merge_field(
1260    &mut self,
1261    tag: Tag,
1262    buf: &mut impl Buf,
1263    ctx: DecodeContext<'_>,
1264  ) -> Result<(), DecodeError> {
1265    match tag.field_number() {
1266      n @ 1..=3 => {
1267        if tag.wire_type() != WireType::LengthDelimited {
1268          return Err(DecodeError::WireTypeMismatch {
1269            field_number: n,
1270            expected: LEN,
1271            actual: tag.wire_type() as u8,
1272          });
1273        }
1274        let mut primaries = self.display_primaries();
1275        let mut cc = primaries[(n - 1) as usize];
1276        buffa::Message::merge_length_delimited(&mut cc, buf, ctx)?;
1277        primaries[(n - 1) as usize] = cc;
1278        self.set_display_primaries(primaries);
1279      }
1280      4 => {
1281        if tag.wire_type() != WireType::LengthDelimited {
1282          return Err(DecodeError::WireTypeMismatch {
1283            field_number: 4,
1284            expected: LEN,
1285            actual: tag.wire_type() as u8,
1286          });
1287        }
1288        let mut wp = self.white_point();
1289        buffa::Message::merge_length_delimited(&mut wp, buf, ctx)?;
1290        self.set_white_point(wp);
1291      }
1292      5 => {
1293        if tag.wire_type() != WireType::Varint {
1294          return Err(DecodeError::WireTypeMismatch {
1295            field_number: 5,
1296            expected: VARINT,
1297            actual: tag.wire_type() as u8,
1298          });
1299        }
1300        let v = decode_uint32(buf)?;
1301        self.set_max_luminance(v);
1302      }
1303      6 => {
1304        if tag.wire_type() != WireType::Varint {
1305          return Err(DecodeError::WireTypeMismatch {
1306            field_number: 6,
1307            expected: VARINT,
1308            actual: tag.wire_type() as u8,
1309          });
1310        }
1311        let v = decode_uint32(buf)?;
1312        self.set_min_luminance(v);
1313      }
1314      _ => skip_field_depth(tag, buf, ctx.depth())?,
1315    }
1316    Ok(())
1317  }
1318
1319  fn clear(&mut self) {
1320    *self = MasteringDisplay::default();
1321  }
1322}
1323
1324// ----------------------------------------------------------------------------
1325// HdrStaticMetadata — { MasteringDisplay mastering = 1;
1326//                       ContentLightLevel content_light = 2; }
1327//
1328// Both fields are `Option`: presence-encoded length-delimited
1329// sub-messages, omitted entirely when `None`. (A present-but-default
1330// inner message still round-trips because each inner type's own
1331// codec is round-trip-safe and presence is carried by the tag.)
1332// ----------------------------------------------------------------------------
1333
1334impl DefaultInstance for HdrStaticMetadata {
1335  fn default_instance() -> &'static Self {
1336    static VALUE: buffa::__private::OnceBox<HdrStaticMetadata> = buffa::__private::OnceBox::new();
1337    VALUE.get_or_init(|| buffa::alloc::boxed::Box::new(HdrStaticMetadata::default()))
1338  }
1339}
1340
1341impl Message for HdrStaticMetadata {
1342  fn compute_size(&self, cache: &mut SizeCache) -> u32 {
1343    let mut size = 0u32;
1344    if let Some(md) = self.mastering() {
1345      let slot = cache.reserve();
1346      let inner = md.compute_size(cache);
1347      cache.set(slot, inner);
1348      size += 1 + varint_len(inner as u64) as u32 + inner;
1349    }
1350    if let Some(cll) = self.content_light() {
1351      let slot = cache.reserve();
1352      let inner = cll.compute_size(cache);
1353      cache.set(slot, inner);
1354      size += 1 + varint_len(inner as u64) as u32 + inner;
1355    }
1356    size
1357  }
1358
1359  fn write_to(&self, cache: &mut SizeCache, buf: &mut impl EncodeSink) {
1360    if let Some(md) = self.mastering() {
1361      Tag::new(1, WireType::LengthDelimited).encode(buf);
1362      encode_varint(cache.consume_next() as u64, buf);
1363      md.write_to(cache, buf);
1364    }
1365    if let Some(cll) = self.content_light() {
1366      Tag::new(2, WireType::LengthDelimited).encode(buf);
1367      encode_varint(cache.consume_next() as u64, buf);
1368      cll.write_to(cache, buf);
1369    }
1370  }
1371
1372  fn merge_field(
1373    &mut self,
1374    tag: Tag,
1375    buf: &mut impl Buf,
1376    ctx: DecodeContext<'_>,
1377  ) -> Result<(), DecodeError> {
1378    match tag.field_number() {
1379      1 => {
1380        if tag.wire_type() != WireType::LengthDelimited {
1381          return Err(DecodeError::WireTypeMismatch {
1382            field_number: 1,
1383            expected: LEN,
1384            actual: tag.wire_type() as u8,
1385          });
1386        }
1387        let mut md = self.mastering().unwrap_or_default();
1388        buffa::Message::merge_length_delimited(&mut md, buf, ctx)?;
1389        self.set_mastering(Some(md));
1390      }
1391      2 => {
1392        if tag.wire_type() != WireType::LengthDelimited {
1393          return Err(DecodeError::WireTypeMismatch {
1394            field_number: 2,
1395            expected: LEN,
1396            actual: tag.wire_type() as u8,
1397          });
1398        }
1399        let mut cll = self.content_light().unwrap_or_default();
1400        buffa::Message::merge_length_delimited(&mut cll, buf, ctx)?;
1401        self.set_content_light(Some(cll));
1402      }
1403      _ => skip_field_depth(tag, buf, ctx.depth())?,
1404    }
1405    Ok(())
1406  }
1407
1408  fn clear(&mut self) {
1409    *self = HdrStaticMetadata::default();
1410  }
1411}
1412
1413// ============================================================================
1414// Audio + container types — see the `## Audio + container types`
1415// sub-section of the module doc block at the top of this file for
1416// the full wire layout.
1417// ============================================================================
1418
1419// ----------------------------------------------------------------------------
1420// String-bearing enum codec helper.
1421//
1422// One-field message `{ string value = 1; }` where `value` is the
1423// `as_str()` slug — the crate's one wire shape for a name vocabulary.
1424// Default-elision: written iff `*self != $default_expr`. For enums with
1425// a `Default` that is a named variant, that default elides and an absent
1426// field decodes back to it; for enums without one, the "default" is the
1427// wire-zero state (empty string → `Other("")`).
1428// ----------------------------------------------------------------------------
1429
1430macro_rules! impl_string_enum_message {
1431  ($ty:ty, $default_expr:expr) => {
1432    impl DefaultInstance for $ty {
1433      fn default_instance() -> &'static Self {
1434        static VALUE: buffa::__private::OnceBox<$ty> = buffa::__private::OnceBox::new();
1435        VALUE.get_or_init(|| buffa::alloc::boxed::Box::new($default_expr))
1436      }
1437    }
1438
1439    impl Message for $ty {
1440      fn compute_size(&self, _cache: &mut SizeCache) -> u32 {
1441        // Default-elision: the decoder seeds from the same default, so an
1442        // absent field decodes back to it exactly. Every other value —
1443        // including the empty slug where that is not the default —
1444        // writes its name.
1445        if *self != $default_expr {
1446          1 + string_encoded_len(self.as_str()) as u32
1447        } else {
1448          0
1449        }
1450      }
1451
1452      fn write_to(&self, _cache: &mut SizeCache, buf: &mut impl EncodeSink) {
1453        if *self != $default_expr {
1454          Tag::new(1, WireType::LengthDelimited).encode(buf);
1455          encode_string(self.as_str(), buf);
1456        }
1457      }
1458
1459      fn merge_field(
1460        &mut self,
1461        tag: Tag,
1462        buf: &mut impl Buf,
1463        ctx: DecodeContext<'_>,
1464      ) -> Result<(), DecodeError> {
1465        match tag.field_number() {
1466          1 => {
1467            if tag.wire_type() != WireType::LengthDelimited {
1468              return Err(DecodeError::WireTypeMismatch {
1469                field_number: 1,
1470                expected: LEN,
1471                actual: tag.wire_type() as u8,
1472              });
1473            }
1474            let s = decode_string(buf)?;
1475            // Every vocabulary routed through this macro parses totally at
1476            // the `buffa` tier (`buffa` implies `alloc`, which is exactly
1477            // where each one's `Other` arm lives), so `FromStr::Err` is
1478            // `Infallible` and this binding is irrefutable. That is the
1479            // point of spelling it this way: add a type here whose parse
1480            // can refuse and this line stops compiling (`E0005`) instead
1481            // of silently acquiring an `unreachable!()` that is only
1482            // unreachable by argument.
1483            let Ok(parsed) = <$ty as core::str::FromStr>::from_str(&s);
1484            *self = parsed;
1485          }
1486          _ => skip_field_depth(tag, buf, ctx.depth())?,
1487        }
1488        Ok(())
1489      }
1490
1491      fn clear(&mut self) {
1492        *self = $default_expr;
1493      }
1494    }
1495  };
1496}
1497
1498// Closed-vocabulary string-bearing enums. They don't have a
1499// `Default` impl, so the decoder seed is the wire-zero `Other("")`
1500// (round-trips losslessly through the slug codec).
1501impl_string_enum_message!(ChannelLayout, ChannelLayout::Other(Utf8Bytes::new()));
1502impl_string_enum_message!(ContainerFormat, ContainerFormat::Other(Utf8Bytes::new()));
1503impl_string_enum_message!(Format, Format::Other(Utf8Bytes::new()));
1504
1505// Name vocabularies with a real `Default`: the seed is that default, and
1506// every value writes its slug. `Unknown(u32)` is gone, so a number is no
1507// longer a spelling any of these has.
1508impl_string_enum_message!(Matrix, Matrix::default());
1509impl_string_enum_message!(Primaries, Primaries::default());
1510impl_string_enum_message!(Transfer, Transfer::default());
1511impl_string_enum_message!(DynamicRange, DynamicRange::default());
1512impl_string_enum_message!(ChromaLocation, ChromaLocation::default());
1513impl_string_enum_message!(DcpTargetGamut, DcpTargetGamut::default());
1514impl_string_enum_message!(Rotation, Rotation::default());
1515impl_string_enum_message!(FieldOrder, FieldOrder::default());
1516impl_string_enum_message!(StereoMode, StereoMode::default());
1517impl_string_enum_message!(PixelFormat, PixelFormat::default());
1518impl_string_enum_message!(SampleFormat, SampleFormat::default());
1519
1520// ----------------------------------------------------------------------------
1521// BitRateMode — { uint32 value = 1; }
1522//
1523// `BitRateMode::default() == Cbr` whose `to_u32() == 0`, so proto3
1524// zero-elision is sound: an absent field decodes via
1525// `from_u32(0) == Cbr`.
1526// ----------------------------------------------------------------------------
1527
1528impl DefaultInstance for BitRateMode {
1529  fn default_instance() -> &'static Self {
1530    static VALUE: buffa::__private::OnceBox<BitRateMode> = buffa::__private::OnceBox::new();
1531    VALUE.get_or_init(|| buffa::alloc::boxed::Box::new(BitRateMode::default()))
1532  }
1533}
1534
1535impl Message for BitRateMode {
1536  fn compute_size(&self, _cache: &mut SizeCache) -> u32 {
1537    let v = self.to_u32();
1538    if v != 0 {
1539      1 + uint32_encoded_len(v) as u32
1540    } else {
1541      0
1542    }
1543  }
1544
1545  fn write_to(&self, _cache: &mut SizeCache, buf: &mut impl EncodeSink) {
1546    let v = self.to_u32();
1547    if v != 0 {
1548      Tag::new(1, WireType::Varint).encode(buf);
1549      encode_uint32(v, buf);
1550    }
1551  }
1552
1553  fn merge_field(
1554    &mut self,
1555    tag: Tag,
1556    buf: &mut impl Buf,
1557    ctx: DecodeContext<'_>,
1558  ) -> Result<(), DecodeError> {
1559    match tag.field_number() {
1560      1 => {
1561        if tag.wire_type() != WireType::Varint {
1562          return Err(DecodeError::WireTypeMismatch {
1563            field_number: 1,
1564            expected: VARINT,
1565            actual: tag.wire_type() as u8,
1566          });
1567        }
1568        *self = BitRateMode::from_u32(decode_uint32(buf)?);
1569      }
1570      _ => skip_field_depth(tag, buf, ctx.depth())?,
1571    }
1572    Ok(())
1573  }
1574
1575  fn clear(&mut self) {
1576    *self = BitRateMode::default();
1577  }
1578}
1579
1580// ----------------------------------------------------------------------------
1581// ChannelOrder — { uint32 value = 1; }
1582//
1583// Same shape and same reasoning as `BitRateMode`:
1584// `ChannelOrder::default() == Unspecified` whose `to_u32() == 0`, so
1585// proto3 zero-elision is sound — an absent field decodes via
1586// `from_u32(0) == Unspecified`.
1587// ----------------------------------------------------------------------------
1588
1589impl DefaultInstance for ChannelOrder {
1590  fn default_instance() -> &'static Self {
1591    static VALUE: buffa::__private::OnceBox<ChannelOrder> = buffa::__private::OnceBox::new();
1592    VALUE.get_or_init(|| buffa::alloc::boxed::Box::new(ChannelOrder::default()))
1593  }
1594}
1595
1596impl Message for ChannelOrder {
1597  fn compute_size(&self, _cache: &mut SizeCache) -> u32 {
1598    let v = self.to_u32();
1599    if v != 0 {
1600      1 + uint32_encoded_len(v) as u32
1601    } else {
1602      0
1603    }
1604  }
1605
1606  fn write_to(&self, _cache: &mut SizeCache, buf: &mut impl EncodeSink) {
1607    let v = self.to_u32();
1608    if v != 0 {
1609      Tag::new(1, WireType::Varint).encode(buf);
1610      encode_uint32(v, buf);
1611    }
1612  }
1613
1614  fn merge_field(
1615    &mut self,
1616    tag: Tag,
1617    buf: &mut impl Buf,
1618    ctx: DecodeContext<'_>,
1619  ) -> Result<(), DecodeError> {
1620    match tag.field_number() {
1621      1 => {
1622        if tag.wire_type() != WireType::Varint {
1623          return Err(DecodeError::WireTypeMismatch {
1624            field_number: 1,
1625            expected: VARINT,
1626            actual: tag.wire_type() as u8,
1627          });
1628        }
1629        *self = ChannelOrder::from_u32(decode_uint32(buf)?);
1630      }
1631      _ => skip_field_depth(tag, buf, ctx.depth())?,
1632    }
1633    Ok(())
1634  }
1635
1636  fn clear(&mut self) {
1637    *self = ChannelOrder::default();
1638  }
1639}
1640
1641// ----------------------------------------------------------------------------
1642// ChannelSpec — { uint32 index = 1; uint32 raw_id = 2; string label = 3; }
1643//
1644// Default is `(0, 0, "")`, which is proto-zero for all three, so proto3
1645// zero-elision is sound throughout.
1646// ----------------------------------------------------------------------------
1647
1648impl DefaultInstance for ChannelSpec {
1649  fn default_instance() -> &'static Self {
1650    static VALUE: buffa::__private::OnceBox<ChannelSpec> = buffa::__private::OnceBox::new();
1651    VALUE.get_or_init(|| buffa::alloc::boxed::Box::new(ChannelSpec::default()))
1652  }
1653}
1654
1655impl Message for ChannelSpec {
1656  fn compute_size(&self, _cache: &mut SizeCache) -> u32 {
1657    let mut size = 0u32;
1658    if self.index() != 0 {
1659      size += 1 + uint32_encoded_len(self.index()) as u32;
1660    }
1661    if self.raw_id() != 0 {
1662      size += 1 + uint32_encoded_len(self.raw_id()) as u32;
1663    }
1664    if !self.label().is_empty() {
1665      size += 1 + string_encoded_len(self.label()) as u32;
1666    }
1667    size
1668  }
1669
1670  fn write_to(&self, _cache: &mut SizeCache, buf: &mut impl EncodeSink) {
1671    if self.index() != 0 {
1672      Tag::new(1, WireType::Varint).encode(buf);
1673      encode_uint32(self.index(), buf);
1674    }
1675    if self.raw_id() != 0 {
1676      Tag::new(2, WireType::Varint).encode(buf);
1677      encode_uint32(self.raw_id(), buf);
1678    }
1679    if !self.label().is_empty() {
1680      Tag::new(3, WireType::LengthDelimited).encode(buf);
1681      encode_string(self.label(), buf);
1682    }
1683  }
1684
1685  fn merge_field(
1686    &mut self,
1687    tag: Tag,
1688    buf: &mut impl Buf,
1689    ctx: DecodeContext<'_>,
1690  ) -> Result<(), DecodeError> {
1691    match tag.field_number() {
1692      n @ 1..=2 => {
1693        if tag.wire_type() != WireType::Varint {
1694          return Err(DecodeError::WireTypeMismatch {
1695            field_number: n,
1696            expected: VARINT,
1697            actual: tag.wire_type() as u8,
1698          });
1699        }
1700        let v = decode_uint32(buf)?;
1701        match n {
1702          1 => {
1703            self.set_index(v);
1704          }
1705          2 => {
1706            self.set_raw_id(v);
1707          }
1708          _ => unreachable!(),
1709        }
1710      }
1711      3 => {
1712        if tag.wire_type() != WireType::LengthDelimited {
1713          return Err(DecodeError::WireTypeMismatch {
1714            field_number: 3,
1715            expected: LEN,
1716            actual: tag.wire_type() as u8,
1717          });
1718        }
1719        let s = decode_string(buf)?;
1720        self.set_label(Utf8Bytes::from(s));
1721      }
1722      _ => skip_field_depth(tag, buf, ctx.depth())?,
1723    }
1724    Ok(())
1725  }
1726
1727  fn clear(&mut self) {
1728    *self = ChannelSpec::default();
1729  }
1730}
1731
1732// ----------------------------------------------------------------------------
1733// ChannelLayoutDescription —
1734//   { uint32 order = 1; uint32 channels = 2; string known_kind = 3;
1735//     optional uint64 native_mask = 4;
1736//     repeated ChannelSpec custom_channels = 5; string text = 6; }
1737//
1738// Fields 1/2/3/6 use proto3 zero-elision: the seed is the type's
1739// `Default`, whose order is code 0, channel count 0, name
1740// `ChannelLayout::default()` (the `Other("")` sentinel, rendering `""`)
1741// and text empty — proto-zero in each case.
1742//
1743// `native_mask` is `optional`: emitted iff `Some`, including for
1744// `Some(0)`, so a reported all-zero mask stays distinct from no mask at
1745// all (the `ReplayGain` album-scalar stance).
1746//
1747// `custom_channels` is the crate's first repeated field — one
1748// length-delimited sub-message per element, in order. The decoder
1749// appends as elements arrive; reading the list out and writing it back
1750// per element would make decode quadratic in a length an untrusted peer
1751// chooses.
1752// ----------------------------------------------------------------------------
1753
1754impl DefaultInstance for ChannelLayoutDescription {
1755  fn default_instance() -> &'static Self {
1756    static VALUE: buffa::__private::OnceBox<ChannelLayoutDescription> =
1757      buffa::__private::OnceBox::new();
1758    VALUE.get_or_init(|| buffa::alloc::boxed::Box::new(ChannelLayoutDescription::default()))
1759  }
1760}
1761
1762impl Message for ChannelLayoutDescription {
1763  fn compute_size(&self, cache: &mut SizeCache) -> u32 {
1764    let mut size = 0u32;
1765    if self.order().to_u32() != 0 {
1766      size += 1 + uint32_encoded_len(self.order().to_u32()) as u32;
1767    }
1768    if self.channels() != 0 {
1769      size += 1 + uint32_encoded_len(self.channels()) as u32;
1770    }
1771    if !self.known_kind().as_str().is_empty() {
1772      size += 1 + string_encoded_len(self.known_kind().as_str()) as u32;
1773    }
1774    if let Some(mask) = self.native_mask() {
1775      size += 1 + uint64_encoded_len(mask) as u32;
1776    }
1777    for spec in self.custom_channels() {
1778      let slot = cache.reserve();
1779      let inner = spec.compute_size(cache);
1780      cache.set(slot, inner);
1781      size += 1 + varint_len(inner as u64) as u32 + inner;
1782    }
1783    if !self.text().is_empty() {
1784      size += 1 + string_encoded_len(self.text()) as u32;
1785    }
1786    size
1787  }
1788
1789  fn write_to(&self, cache: &mut SizeCache, buf: &mut impl EncodeSink) {
1790    if self.order().to_u32() != 0 {
1791      Tag::new(1, WireType::Varint).encode(buf);
1792      encode_uint32(self.order().to_u32(), buf);
1793    }
1794    if self.channels() != 0 {
1795      Tag::new(2, WireType::Varint).encode(buf);
1796      encode_uint32(self.channels(), buf);
1797    }
1798    if !self.known_kind().as_str().is_empty() {
1799      Tag::new(3, WireType::LengthDelimited).encode(buf);
1800      encode_string(self.known_kind().as_str(), buf);
1801    }
1802    if let Some(mask) = self.native_mask() {
1803      Tag::new(4, WireType::Varint).encode(buf);
1804      encode_uint64(mask, buf);
1805    }
1806    for spec in self.custom_channels() {
1807      Tag::new(5, WireType::LengthDelimited).encode(buf);
1808      encode_varint(cache.consume_next() as u64, buf);
1809      spec.write_to(cache, buf);
1810    }
1811    if !self.text().is_empty() {
1812      Tag::new(6, WireType::LengthDelimited).encode(buf);
1813      encode_string(self.text(), buf);
1814    }
1815  }
1816
1817  fn merge_field(
1818    &mut self,
1819    tag: Tag,
1820    buf: &mut impl Buf,
1821    ctx: DecodeContext<'_>,
1822  ) -> Result<(), DecodeError> {
1823    match tag.field_number() {
1824      n @ (1 | 2 | 4) => {
1825        if tag.wire_type() != WireType::Varint {
1826          return Err(DecodeError::WireTypeMismatch {
1827            field_number: n,
1828            expected: VARINT,
1829            actual: tag.wire_type() as u8,
1830          });
1831        }
1832        match n {
1833          1 => {
1834            self.set_order(ChannelOrder::from_u32(decode_uint32(buf)?));
1835          }
1836          2 => {
1837            self.set_channels(decode_uint32(buf)?);
1838          }
1839          4 => {
1840            self.set_native_mask(Some(decode_uint64(buf)?));
1841          }
1842          _ => unreachable!(),
1843        }
1844      }
1845      n @ (3 | 5 | 6) => {
1846        if tag.wire_type() != WireType::LengthDelimited {
1847          return Err(DecodeError::WireTypeMismatch {
1848            field_number: n,
1849            expected: LEN,
1850            actual: tag.wire_type() as u8,
1851          });
1852        }
1853        match n {
1854          3 => {
1855            let s = decode_string(buf)?;
1856            // `ChannelLayout`'s parse is total at this tier (`buffa`
1857            // implies `alloc`, which is where its `Other` arm lives), so
1858            // this binding is irrefutable. Spelled this way on purpose:
1859            // a future refusal stops it compiling (`E0005`) instead of
1860            // silently acquiring an `unreachable!()`.
1861            let Ok(parsed) = <ChannelLayout as core::str::FromStr>::from_str(&s);
1862            self.set_known_kind(parsed);
1863          }
1864          5 => {
1865            let mut spec = ChannelSpec::default();
1866            buffa::Message::merge_length_delimited(&mut spec, buf, ctx)?;
1867            self.push_custom_channel(spec);
1868          }
1869          6 => {
1870            let s = decode_string(buf)?;
1871            self.set_text(Utf8Bytes::from(s));
1872          }
1873          _ => unreachable!(),
1874        }
1875      }
1876      _ => skip_field_depth(tag, buf, ctx.depth())?,
1877    }
1878    Ok(())
1879  }
1880
1881  fn clear(&mut self) {
1882    *self = ChannelLayoutDescription::default();
1883  }
1884}
1885
1886// ----------------------------------------------------------------------------
1887// Loudness — four `float` fields (Fixed32 wire). Default is
1888// all-zero, which is proto-zero for `f32`, so proto3 zero-elision is
1889// sound throughout.
1890// ----------------------------------------------------------------------------
1891
1892const FIXED32: u8 = WireType::Fixed32 as u8;
1893
1894impl DefaultInstance for Loudness {
1895  fn default_instance() -> &'static Self {
1896    static VALUE: buffa::__private::OnceBox<Loudness> = buffa::__private::OnceBox::new();
1897    VALUE.get_or_init(|| buffa::alloc::boxed::Box::new(Loudness::default()))
1898  }
1899}
1900
1901impl Message for Loudness {
1902  fn compute_size(&self, _cache: &mut SizeCache) -> u32 {
1903    let mut size = 0u32;
1904    // proto3 zero-elision: sound — every field defaults to 0.0
1905    // (proto-zero for `f32`).
1906    if self.integrated_lufs() != 0.0 {
1907      size += 1 + FIXED32_ENCODED_LEN as u32;
1908    }
1909    if self.range_lu() != 0.0 {
1910      size += 1 + FIXED32_ENCODED_LEN as u32;
1911    }
1912    if self.true_peak_dbtp() != 0.0 {
1913      size += 1 + FIXED32_ENCODED_LEN as u32;
1914    }
1915    if self.sample_peak_dbfs() != 0.0 {
1916      size += 1 + FIXED32_ENCODED_LEN as u32;
1917    }
1918    size
1919  }
1920
1921  fn write_to(&self, _cache: &mut SizeCache, buf: &mut impl EncodeSink) {
1922    if self.integrated_lufs() != 0.0 {
1923      Tag::new(1, WireType::Fixed32).encode(buf);
1924      encode_float(self.integrated_lufs(), buf);
1925    }
1926    if self.range_lu() != 0.0 {
1927      Tag::new(2, WireType::Fixed32).encode(buf);
1928      encode_float(self.range_lu(), buf);
1929    }
1930    if self.true_peak_dbtp() != 0.0 {
1931      Tag::new(3, WireType::Fixed32).encode(buf);
1932      encode_float(self.true_peak_dbtp(), buf);
1933    }
1934    if self.sample_peak_dbfs() != 0.0 {
1935      Tag::new(4, WireType::Fixed32).encode(buf);
1936      encode_float(self.sample_peak_dbfs(), buf);
1937    }
1938  }
1939
1940  fn merge_field(
1941    &mut self,
1942    tag: Tag,
1943    buf: &mut impl Buf,
1944    ctx: DecodeContext<'_>,
1945  ) -> Result<(), DecodeError> {
1946    match tag.field_number() {
1947      n @ 1..=4 => {
1948        if tag.wire_type() != WireType::Fixed32 {
1949          return Err(DecodeError::WireTypeMismatch {
1950            field_number: n,
1951            expected: FIXED32,
1952            actual: tag.wire_type() as u8,
1953          });
1954        }
1955        let v = decode_float(buf)?;
1956        match n {
1957          1 => {
1958            self.set_integrated_lufs(v);
1959          }
1960          2 => {
1961            self.set_range_lu(v);
1962          }
1963          3 => {
1964            self.set_true_peak_dbtp(v);
1965          }
1966          4 => {
1967            self.set_sample_peak_dbfs(v);
1968          }
1969          _ => unreachable!(),
1970        }
1971      }
1972      _ => skip_field_depth(tag, buf, ctx.depth())?,
1973    }
1974    Ok(())
1975  }
1976
1977  fn clear(&mut self) {
1978    *self = Loudness::default();
1979  }
1980}
1981
1982// ----------------------------------------------------------------------------
1983// ReplayGain — `track_gain_db` / `track_peak` are `float` with proto3
1984// zero-elision (Default is all-zero == proto-zero for f32). The two
1985// album-level scalars are `optional float` so a distribution-absent
1986// album-level number round-trips as `None` (wire field absent rather
1987// than zero). All four are wire-type `Fixed32` (4 bytes LE).
1988// ----------------------------------------------------------------------------
1989
1990impl DefaultInstance for ReplayGain {
1991  fn default_instance() -> &'static Self {
1992    static VALUE: buffa::__private::OnceBox<ReplayGain> = buffa::__private::OnceBox::new();
1993    VALUE.get_or_init(|| buffa::alloc::boxed::Box::new(ReplayGain::default()))
1994  }
1995}
1996
1997impl Message for ReplayGain {
1998  fn compute_size(&self, _cache: &mut SizeCache) -> u32 {
1999    let mut size = 0u32;
2000    // proto3 zero-elision on the two `float` fields.
2001    if self.track_gain_db() != 0.0 {
2002      size += 1 + FIXED32_ENCODED_LEN as u32;
2003    }
2004    if self.track_peak() != 0.0 {
2005      size += 1 + FIXED32_ENCODED_LEN as u32;
2006    }
2007    // `optional float` — present iff `Some` (independent of value).
2008    if self.album_gain_db().is_some() {
2009      size += 1 + FIXED32_ENCODED_LEN as u32;
2010    }
2011    if self.album_peak().is_some() {
2012      size += 1 + FIXED32_ENCODED_LEN as u32;
2013    }
2014    size
2015  }
2016
2017  fn write_to(&self, _cache: &mut SizeCache, buf: &mut impl EncodeSink) {
2018    if self.track_gain_db() != 0.0 {
2019      Tag::new(1, WireType::Fixed32).encode(buf);
2020      encode_float(self.track_gain_db(), buf);
2021    }
2022    if self.track_peak() != 0.0 {
2023      Tag::new(2, WireType::Fixed32).encode(buf);
2024      encode_float(self.track_peak(), buf);
2025    }
2026    if let Some(v) = self.album_gain_db() {
2027      Tag::new(3, WireType::Fixed32).encode(buf);
2028      encode_float(v, buf);
2029    }
2030    if let Some(v) = self.album_peak() {
2031      Tag::new(4, WireType::Fixed32).encode(buf);
2032      encode_float(v, buf);
2033    }
2034  }
2035
2036  fn merge_field(
2037    &mut self,
2038    tag: Tag,
2039    buf: &mut impl Buf,
2040    ctx: DecodeContext<'_>,
2041  ) -> Result<(), DecodeError> {
2042    match tag.field_number() {
2043      n @ 1..=4 => {
2044        if tag.wire_type() != WireType::Fixed32 {
2045          return Err(DecodeError::WireTypeMismatch {
2046            field_number: n,
2047            expected: FIXED32,
2048            actual: tag.wire_type() as u8,
2049          });
2050        }
2051        let v = decode_float(buf)?;
2052        match n {
2053          1 => {
2054            self.set_track_gain_db(v);
2055          }
2056          2 => {
2057            self.set_track_peak(v);
2058          }
2059          3 => {
2060            self.set_album_gain_db(Some(v));
2061          }
2062          4 => {
2063            self.set_album_peak(Some(v));
2064          }
2065          _ => unreachable!(),
2066        }
2067      }
2068      _ => skip_field_depth(tag, buf, ctx.depth())?,
2069    }
2070    Ok(())
2071  }
2072
2073  fn clear(&mut self) {
2074    *self = ReplayGain::default();
2075  }
2076}
2077
2078// ----------------------------------------------------------------------------
2079// Fingerprint — { string algorithm = 1; bytes value = 2; }
2080//
2081// `try_new` rejects empty `algorithm`, so the type has no
2082// natural-zero `Default`. The decoder seed is a synthetic
2083// `Fingerprint { algorithm: "default", value: [] }` (the
2084// always-encoded `algorithm` overwrites it on decode). `algorithm`
2085// is encoded UNCONDITIONALLY; `value` (bytes) uses proto3
2086// zero-elision (empty fingerprint is a legal value).
2087// ----------------------------------------------------------------------------
2088
2089fn audio_fingerprint_seed() -> Fingerprint {
2090  // Safety: the literal is non-empty so `try_new` cannot fail.
2091  Fingerprint::try_new(Utf8Bytes::from_static("default"), std::vec::Vec::new())
2092    .unwrap_or_else(|_| unreachable!())
2093}
2094
2095impl DefaultInstance for Fingerprint {
2096  fn default_instance() -> &'static Self {
2097    static VALUE: buffa::__private::OnceBox<Fingerprint> = buffa::__private::OnceBox::new();
2098    VALUE.get_or_init(|| buffa::alloc::boxed::Box::new(audio_fingerprint_seed()))
2099  }
2100}
2101
2102impl Message for Fingerprint {
2103  fn compute_size(&self, _cache: &mut SizeCache) -> u32 {
2104    let mut size = 1 + string_encoded_len(self.algorithm()) as u32;
2105    if !self.value().is_empty() {
2106      size += 1 + bytes_encoded_len(self.value()) as u32;
2107    }
2108    size
2109  }
2110
2111  fn write_to(&self, _cache: &mut SizeCache, buf: &mut impl EncodeSink) {
2112    Tag::new(1, WireType::LengthDelimited).encode(buf);
2113    encode_string(self.algorithm(), buf);
2114    if !self.value().is_empty() {
2115      Tag::new(2, WireType::LengthDelimited).encode(buf);
2116      encode_bytes(self.value(), buf);
2117    }
2118  }
2119
2120  fn merge_field(
2121    &mut self,
2122    tag: Tag,
2123    buf: &mut impl Buf,
2124    ctx: DecodeContext<'_>,
2125  ) -> Result<(), DecodeError> {
2126    match tag.field_number() {
2127      1 => {
2128        if tag.wire_type() != WireType::LengthDelimited {
2129          return Err(DecodeError::WireTypeMismatch {
2130            field_number: 1,
2131            expected: LEN,
2132            actual: tag.wire_type() as u8,
2133          });
2134        }
2135        let algo = decode_string(buf)?;
2136        // Empty algorithm on the wire is malformed (the type
2137        // invariant forbids it); clamp to the seed's `"default"`
2138        // sentinel to keep decode total.
2139        let algo = if algo.is_empty() {
2140          Utf8Bytes::from_static("default")
2141        } else {
2142          Utf8Bytes::from(algo)
2143        };
2144        // Preserve existing `value`, swap `algorithm`. `try_new`
2145        // moves the bytes back in unchanged.
2146        let value = self.value().to_vec();
2147        *self = Fingerprint::try_new(algo, value).unwrap_or_else(|_| audio_fingerprint_seed());
2148      }
2149      2 => {
2150        if tag.wire_type() != WireType::LengthDelimited {
2151          return Err(DecodeError::WireTypeMismatch {
2152            field_number: 2,
2153            expected: LEN,
2154            actual: tag.wire_type() as u8,
2155          });
2156        }
2157        let bytes = decode_bytes(buf)?;
2158        // Preserve `algorithm`, replace `value`.
2159        let algo = Utf8Bytes::from(self.algorithm());
2160        *self = Fingerprint::try_new(algo, bytes).unwrap_or_else(|_| audio_fingerprint_seed());
2161      }
2162      _ => skip_field_depth(tag, buf, ctx.depth())?,
2163    }
2164    Ok(())
2165  }
2166
2167  fn clear(&mut self) {
2168    *self = audio_fingerprint_seed();
2169  }
2170}
2171
2172// ----------------------------------------------------------------------------
2173// CoverArt — { string mime = 1; bytes data = 2; }
2174//
2175// `try_new` rejects empty mime / empty data, so the type has no
2176// natural-zero `Default`. Decoder seed is a synthetic
2177// `CoverArt { mime: "application/octet-stream", data: [0u8] }`
2178// (sentinel that gets overwritten on decode; both fields are
2179// ALWAYS encoded on the write path).
2180// ----------------------------------------------------------------------------
2181
2182fn audio_cover_art_seed() -> CoverArt {
2183  CoverArt::try_new(
2184    Utf8Bytes::from_static("application/octet-stream"),
2185    std::vec![0u8],
2186  )
2187  .unwrap_or_else(|_| unreachable!())
2188}
2189
2190impl DefaultInstance for CoverArt {
2191  fn default_instance() -> &'static Self {
2192    static VALUE: buffa::__private::OnceBox<CoverArt> = buffa::__private::OnceBox::new();
2193    VALUE.get_or_init(|| buffa::alloc::boxed::Box::new(audio_cover_art_seed()))
2194  }
2195}
2196
2197impl Message for CoverArt {
2198  fn compute_size(&self, _cache: &mut SizeCache) -> u32 {
2199    2 + string_encoded_len(self.mime()) as u32 + bytes_encoded_len(self.data()) as u32
2200  }
2201
2202  fn write_to(&self, _cache: &mut SizeCache, buf: &mut impl EncodeSink) {
2203    Tag::new(1, WireType::LengthDelimited).encode(buf);
2204    encode_string(self.mime(), buf);
2205    Tag::new(2, WireType::LengthDelimited).encode(buf);
2206    encode_bytes(self.data(), buf);
2207  }
2208
2209  fn merge_field(
2210    &mut self,
2211    tag: Tag,
2212    buf: &mut impl Buf,
2213    ctx: DecodeContext<'_>,
2214  ) -> Result<(), DecodeError> {
2215    match tag.field_number() {
2216      1 => {
2217        if tag.wire_type() != WireType::LengthDelimited {
2218          return Err(DecodeError::WireTypeMismatch {
2219            field_number: 1,
2220            expected: LEN,
2221            actual: tag.wire_type() as u8,
2222          });
2223        }
2224        let mime = decode_string(buf)?;
2225        // Empty mime on the wire violates the invariant; clamp to
2226        // the sentinel to keep decode total.
2227        let mime = if mime.is_empty() {
2228          Utf8Bytes::from_static("application/octet-stream")
2229        } else {
2230          Utf8Bytes::from(mime)
2231        };
2232        let data = self.data().to_vec();
2233        let data = if data.is_empty() {
2234          std::vec![0u8]
2235        } else {
2236          data
2237        };
2238        *self = CoverArt::try_new(mime, data).unwrap_or_else(|_| audio_cover_art_seed());
2239      }
2240      2 => {
2241        if tag.wire_type() != WireType::LengthDelimited {
2242          return Err(DecodeError::WireTypeMismatch {
2243            field_number: 2,
2244            expected: LEN,
2245            actual: tag.wire_type() as u8,
2246          });
2247        }
2248        let data = decode_bytes(buf)?;
2249        // Empty data on the wire violates the invariant; clamp to
2250        // the single-byte sentinel.
2251        let data = if data.is_empty() {
2252          std::vec![0u8]
2253        } else {
2254          data
2255        };
2256        let mime = Utf8Bytes::from(self.mime());
2257        *self = CoverArt::try_new(mime, data).unwrap_or_else(|_| audio_cover_art_seed());
2258      }
2259      _ => skip_field_depth(tag, buf, ctx.depth())?,
2260    }
2261    Ok(())
2262  }
2263
2264  fn clear(&mut self) {
2265    *self = audio_cover_art_seed();
2266  }
2267}
2268
2269// ----------------------------------------------------------------------------
2270// Tags — every string field uses proto3 zero-elision ("" ==
2271// "absent" by the type's own convention); every numeric Option<u16>
2272// is widened to uint32 and uses proto3 zero-elision. `Some(0)`
2273// (theoretically legal) and `None` (absent) round-trip identically
2274// to `None` — documented limitation.
2275// ----------------------------------------------------------------------------
2276
2277impl DefaultInstance for Tags {
2278  fn default_instance() -> &'static Self {
2279    static VALUE: buffa::__private::OnceBox<Tags> = buffa::__private::OnceBox::new();
2280    VALUE.get_or_init(|| buffa::alloc::boxed::Box::new(Tags::default()))
2281  }
2282}
2283
2284impl Message for Tags {
2285  fn compute_size(&self, _cache: &mut SizeCache) -> u32 {
2286    let mut size = 0u32;
2287    if !self.title().is_empty() {
2288      size += 1 + string_encoded_len(self.title()) as u32;
2289    }
2290    if !self.artist().is_empty() {
2291      size += 1 + string_encoded_len(self.artist()) as u32;
2292    }
2293    if !self.album_artist().is_empty() {
2294      size += 1 + string_encoded_len(self.album_artist()) as u32;
2295    }
2296    if !self.album().is_empty() {
2297      size += 1 + string_encoded_len(self.album()) as u32;
2298    }
2299    if !self.composer().is_empty() {
2300      size += 1 + string_encoded_len(self.composer()) as u32;
2301    }
2302    if !self.genre().is_empty() {
2303      size += 1 + string_encoded_len(self.genre()) as u32;
2304    }
2305    if !self.comment().is_empty() {
2306      size += 1 + string_encoded_len(self.comment()) as u32;
2307    }
2308    // Numeric fields are bare `u16` with `0` = absent — proto3 zero-elision
2309    // applies directly (no `Option` to unwrap).
2310    if self.year() != 0 {
2311      size += 1 + uint32_encoded_len(self.year() as u32) as u32;
2312    }
2313    if self.track_number() != 0 {
2314      size += 1 + uint32_encoded_len(self.track_number() as u32) as u32;
2315    }
2316    if self.track_total() != 0 {
2317      size += 1 + uint32_encoded_len(self.track_total() as u32) as u32;
2318    }
2319    if self.disc_number() != 0 {
2320      size += 1 + uint32_encoded_len(self.disc_number() as u32) as u32;
2321    }
2322    if self.disc_total() != 0 {
2323      size += 1 + uint32_encoded_len(self.disc_total() as u32) as u32;
2324    }
2325    if let Some(lang) = self.language() {
2326      size += 1 + string_encoded_len(&lang.to_string()) as u32;
2327    }
2328    size
2329  }
2330
2331  fn write_to(&self, _cache: &mut SizeCache, buf: &mut impl EncodeSink) {
2332    if !self.title().is_empty() {
2333      Tag::new(1, WireType::LengthDelimited).encode(buf);
2334      encode_string(self.title(), buf);
2335    }
2336    if !self.artist().is_empty() {
2337      Tag::new(2, WireType::LengthDelimited).encode(buf);
2338      encode_string(self.artist(), buf);
2339    }
2340    if !self.album_artist().is_empty() {
2341      Tag::new(3, WireType::LengthDelimited).encode(buf);
2342      encode_string(self.album_artist(), buf);
2343    }
2344    if !self.album().is_empty() {
2345      Tag::new(4, WireType::LengthDelimited).encode(buf);
2346      encode_string(self.album(), buf);
2347    }
2348    if !self.composer().is_empty() {
2349      Tag::new(5, WireType::LengthDelimited).encode(buf);
2350      encode_string(self.composer(), buf);
2351    }
2352    if !self.genre().is_empty() {
2353      Tag::new(6, WireType::LengthDelimited).encode(buf);
2354      encode_string(self.genre(), buf);
2355    }
2356    if !self.comment().is_empty() {
2357      Tag::new(7, WireType::LengthDelimited).encode(buf);
2358      encode_string(self.comment(), buf);
2359    }
2360    if self.year() != 0 {
2361      Tag::new(8, WireType::Varint).encode(buf);
2362      encode_uint32(self.year() as u32, buf);
2363    }
2364    if self.track_number() != 0 {
2365      Tag::new(9, WireType::Varint).encode(buf);
2366      encode_uint32(self.track_number() as u32, buf);
2367    }
2368    if self.track_total() != 0 {
2369      Tag::new(10, WireType::Varint).encode(buf);
2370      encode_uint32(self.track_total() as u32, buf);
2371    }
2372    if self.disc_number() != 0 {
2373      Tag::new(11, WireType::Varint).encode(buf);
2374      encode_uint32(self.disc_number() as u32, buf);
2375    }
2376    if self.disc_total() != 0 {
2377      Tag::new(12, WireType::Varint).encode(buf);
2378      encode_uint32(self.disc_total() as u32, buf);
2379    }
2380    if let Some(lang) = self.language() {
2381      Tag::new(13, WireType::LengthDelimited).encode(buf);
2382      encode_string(&lang.to_string(), buf);
2383    }
2384  }
2385
2386  fn merge_field(
2387    &mut self,
2388    tag: Tag,
2389    buf: &mut impl Buf,
2390    ctx: DecodeContext<'_>,
2391  ) -> Result<(), DecodeError> {
2392    let n = tag.field_number();
2393    match n {
2394      1..=7 | 13 => {
2395        if tag.wire_type() != WireType::LengthDelimited {
2396          return Err(DecodeError::WireTypeMismatch {
2397            field_number: n,
2398            expected: LEN,
2399            actual: tag.wire_type() as u8,
2400          });
2401        }
2402        let s = decode_string(buf)?;
2403        let s = Utf8Bytes::from(s);
2404        match n {
2405          1 => {
2406            self.set_title(s);
2407          }
2408          2 => {
2409            self.set_artist(s);
2410          }
2411          3 => {
2412            self.set_album_artist(s);
2413          }
2414          4 => {
2415            self.set_album(s);
2416          }
2417          5 => {
2418            self.set_composer(s);
2419          }
2420          6 => {
2421            self.set_genre(s);
2422          }
2423          7 => {
2424            self.set_comment(s);
2425          }
2426          13 => {
2427            // An empty field-13 string means "no language tag" (`None`);
2428            // a non-empty value goes through the whole-tag door, coercing a
2429            // tag it refuses to `LanguageId::default()` (`und`) — the same
2430            // lenient semantics the standalone `LanguageId` codec uses
2431            // (`buffa::DecodeError` has no general "invalid value" arm).
2432            self.update_language(if s.is_empty() {
2433              None
2434            } else {
2435              Some(LanguageId::new(&s).unwrap_or_default())
2436            });
2437          }
2438          _ => unreachable!(),
2439        }
2440      }
2441      8..=12 => {
2442        if tag.wire_type() != WireType::Varint {
2443          return Err(DecodeError::WireTypeMismatch {
2444            field_number: n,
2445            expected: VARINT,
2446            actual: tag.wire_type() as u8,
2447          });
2448        }
2449        // Numeric fields are bare `u16` with `0` = absent — a decoded `0`
2450        // (or an elided, never-written field) is simply `0`.
2451        let v = decode_uint32(buf)? as u16;
2452        match n {
2453          8 => {
2454            self.set_year(v);
2455          }
2456          9 => {
2457            self.set_track_number(v);
2458          }
2459          10 => {
2460            self.set_track_total(v);
2461          }
2462          11 => {
2463            self.set_disc_number(v);
2464          }
2465          12 => {
2466            self.set_disc_total(v);
2467          }
2468          _ => unreachable!(),
2469        }
2470      }
2471      _ => skip_field_depth(tag, buf, ctx.depth())?,
2472    }
2473    Ok(())
2474  }
2475
2476  fn clear(&mut self) {
2477    *self = Tags::default();
2478  }
2479}
2480
2481// ----------------------------------------------------------------------------
2482// TrackDisposition — { uint32 bits = 1; }
2483// Default is the empty flag set (`bits() == 0`), so proto3 zero-elision is
2484// sound: an absent field decodes back to `TrackDisposition::empty()`. The
2485// `from_u32` (= `from_bits_retain`) decoder preserves every bit, so unknown
2486// bits introduced in a future FFmpeg release round-trip losslessly.
2487// ----------------------------------------------------------------------------
2488
2489impl DefaultInstance for TrackDisposition {
2490  fn default_instance() -> &'static Self {
2491    static VALUE: buffa::__private::OnceBox<TrackDisposition> = buffa::__private::OnceBox::new();
2492    VALUE.get_or_init(|| buffa::alloc::boxed::Box::new(TrackDisposition::default()))
2493  }
2494}
2495
2496impl Message for TrackDisposition {
2497  fn compute_size(&self, _cache: &mut SizeCache) -> u32 {
2498    // proto3 zero-elision: sound — default is the empty flag set
2499    // (`bits() == 0`).
2500    if self.to_u32() != 0 {
2501      1 + uint32_encoded_len(self.to_u32()) as u32
2502    } else {
2503      0
2504    }
2505  }
2506
2507  fn write_to(&self, _cache: &mut SizeCache, buf: &mut impl EncodeSink) {
2508    if self.to_u32() != 0 {
2509      Tag::new(1, WireType::Varint).encode(buf);
2510      encode_uint32(self.to_u32(), buf);
2511    }
2512  }
2513
2514  fn merge_field(
2515    &mut self,
2516    tag: Tag,
2517    buf: &mut impl Buf,
2518    ctx: DecodeContext<'_>,
2519  ) -> Result<(), DecodeError> {
2520    match tag.field_number() {
2521      1 => {
2522        if tag.wire_type() != WireType::Varint {
2523          return Err(DecodeError::WireTypeMismatch {
2524            field_number: 1,
2525            expected: VARINT,
2526            actual: tag.wire_type() as u8,
2527          });
2528        }
2529        let v = decode_uint32(buf)?;
2530        *self = TrackDisposition::from_u32(v);
2531      }
2532      _ => skip_field_depth(tag, buf, ctx.depth())?,
2533    }
2534    Ok(())
2535  }
2536
2537  fn clear(&mut self) {
2538    *self = TrackDisposition::default();
2539  }
2540}
2541
2542// ----------------------------------------------------------------------------
2543// TrackOrigin + Format live in `crate::subtitle`, which is
2544// `cfg`-gated on the `alloc` feature (the `Other(Utf8Bytes)` escape on
2545// `Format`). Mirror that gate on the wire impls so a
2546// `--no-default-features --features buffa` build (no `alloc`) still compiles.
2547// ----------------------------------------------------------------------------
2548
2549#[cfg(any(feature = "std", feature = "alloc"))]
2550mod subtitle_impls {
2551  use super::*;
2552  use ::buffa::types::{decode_string, encode_string, string_encoded_len};
2553  use core::str::FromStr;
2554
2555  use crate::subtitle::{Format, TrackOrigin};
2556
2557  // ----------------------------------------------------------------------------
2558  // TrackOrigin — { string value = 1; }
2559  // Open since 0.5.0 (`Other(Utf8Bytes)`), so there is no total numeric id;
2560  // encodes the slug from `as_str()`, exactly like `Format` below.
2561  // Always-encoded (NOT default-elision): the empty string decodes to
2562  // `Other("")`, a distinct legal value, so eliding would conflate it with
2563  // an absent field.
2564  // ----------------------------------------------------------------------------
2565
2566  impl DefaultInstance for TrackOrigin {
2567    fn default_instance() -> &'static Self {
2568      static VALUE: buffa::__private::OnceBox<TrackOrigin> = buffa::__private::OnceBox::new();
2569      VALUE.get_or_init(|| buffa::alloc::boxed::Box::new(TrackOrigin::default()))
2570    }
2571  }
2572
2573  impl Message for TrackOrigin {
2574    fn compute_size(&self, _cache: &mut SizeCache) -> u32 {
2575      // Always-encode the slug — see the wire-format note above.
2576      1 + string_encoded_len(self.as_str()) as u32
2577    }
2578
2579    fn write_to(&self, _cache: &mut SizeCache, buf: &mut impl EncodeSink) {
2580      Tag::new(1, WireType::LengthDelimited).encode(buf);
2581      encode_string(self.as_str(), buf);
2582    }
2583
2584    fn merge_field(
2585      &mut self,
2586      tag: Tag,
2587      buf: &mut impl Buf,
2588      ctx: DecodeContext<'_>,
2589    ) -> Result<(), DecodeError> {
2590      match tag.field_number() {
2591        1 => {
2592          if tag.wire_type() != WireType::LengthDelimited {
2593            return Err(DecodeError::WireTypeMismatch {
2594              field_number: 1,
2595              expected: LEN,
2596              actual: tag.wire_type() as u8,
2597            });
2598          }
2599          let s = decode_string(buf)?;
2600          // `FromStr for TrackOrigin` is `Infallible` (total — every
2601          // string decodes either to a named variant or to `Other(_)`),
2602          // so there is no failure branch to write.
2603          let Ok(parsed) = TrackOrigin::from_str(&s);
2604          *self = parsed;
2605        }
2606        _ => skip_field_depth(tag, buf, ctx.depth())?,
2607      }
2608      Ok(())
2609    }
2610
2611    fn clear(&mut self) {
2612      *self = TrackOrigin::default();
2613    }
2614  }
2615
2616  // ----------------------------------------------------------------------------
2617  // Format — { string value = 1; }
2618  // No stable numeric id; encodes the FFmpeg-style slug from `as_str()`.
2619  // Always-encoded (NOT proto3 zero-elision and NOT default-elision): the
2620  // empty string is `Other("")` on decode (per the total `FromStr`), which
2621  // is a distinct, legal value — eliding the field would conflate it with
2622  // an absent field. Writing the slug unconditionally side-steps the
2623  // ambiguity; on decode an absent field stays at the encoder's seed
2624  // (`Default::default()` = `Other("")`, defined ungated in
2625  // `crate::subtitle::format` — available regardless of the `buffa`
2626  // feature).
2627  // ----------------------------------------------------------------------------
2628
2629  impl DefaultInstance for Format {
2630    fn default_instance() -> &'static Self {
2631      static VALUE: buffa::__private::OnceBox<Format> = buffa::__private::OnceBox::new();
2632      VALUE.get_or_init(|| buffa::alloc::boxed::Box::new(Format::default()))
2633    }
2634  }
2635
2636  impl Message for Format {
2637    fn compute_size(&self, _cache: &mut SizeCache) -> u32 {
2638      // Always-encode the slug — see the module-level wire-format note
2639      // for the rationale (empty slug is `Other("")` ≠ absent).
2640      let slug = self.as_str();
2641      1 + string_encoded_len(slug) as u32
2642    }
2643
2644    fn write_to(&self, _cache: &mut SizeCache, buf: &mut impl EncodeSink) {
2645      let slug = self.as_str();
2646      Tag::new(1, WireType::LengthDelimited).encode(buf);
2647      encode_string(slug, buf);
2648    }
2649
2650    fn merge_field(
2651      &mut self,
2652      tag: Tag,
2653      buf: &mut impl Buf,
2654      ctx: DecodeContext<'_>,
2655    ) -> Result<(), DecodeError> {
2656      match tag.field_number() {
2657        1 => {
2658          if tag.wire_type() != WireType::LengthDelimited {
2659            return Err(DecodeError::WireTypeMismatch {
2660              field_number: 1,
2661              expected: LEN,
2662              actual: tag.wire_type() as u8,
2663            });
2664          }
2665          let s = decode_string(buf)?;
2666          // `FromStr for Format` is `Infallible` (total — every
2667          // string decodes either to a named variant or to `Other(_)`).
2668          let Ok(parsed) = Format::from_str(&s);
2669          *self = parsed;
2670        }
2671        _ => skip_field_depth(tag, buf, ctx.depth())?,
2672      }
2673      Ok(())
2674    }
2675
2676    fn clear(&mut self) {
2677      *self = Format::default();
2678    }
2679  }
2680}
2681
2682// ============================================================================
2683// Capture + language — `alloc`-gated wire impls. See the
2684// "## Capture + language" section in the module-level doc for the
2685// wire-format spec.
2686// ============================================================================
2687
2688// ----------------------------------------------------------------------------
2689// Device — { string make = 1; string model = 2; }
2690// Default is two empty strings == proto-zero, so proto3 zero-elision
2691// is sound. Empty string is the in-rust sentinel for "absent".
2692// ----------------------------------------------------------------------------
2693
2694#[cfg(any(feature = "std", feature = "alloc"))]
2695impl DefaultInstance for Device {
2696  fn default_instance() -> &'static Self {
2697    static VALUE: buffa::__private::OnceBox<Device> = buffa::__private::OnceBox::new();
2698    VALUE.get_or_init(|| buffa::alloc::boxed::Box::new(Device::default()))
2699  }
2700}
2701
2702#[cfg(any(feature = "std", feature = "alloc"))]
2703impl Message for Device {
2704  fn compute_size(&self, _cache: &mut SizeCache) -> u32 {
2705    let mut size = 0u32;
2706    // proto3 zero-elision: sound — seed is two empty strings.
2707    if !self.make().is_empty() {
2708      size += 1 + string_encoded_len(self.make()) as u32;
2709    }
2710    if !self.model().is_empty() {
2711      size += 1 + string_encoded_len(self.model()) as u32;
2712    }
2713    size
2714  }
2715
2716  fn write_to(&self, _cache: &mut SizeCache, buf: &mut impl EncodeSink) {
2717    // proto3 zero-elision: sound — see `compute_size`.
2718    if !self.make().is_empty() {
2719      Tag::new(1, WireType::LengthDelimited).encode(buf);
2720      encode_string(self.make(), buf);
2721    }
2722    if !self.model().is_empty() {
2723      Tag::new(2, WireType::LengthDelimited).encode(buf);
2724      encode_string(self.model(), buf);
2725    }
2726  }
2727
2728  fn merge_field(
2729    &mut self,
2730    tag: Tag,
2731    buf: &mut impl Buf,
2732    ctx: DecodeContext<'_>,
2733  ) -> Result<(), DecodeError> {
2734    match tag.field_number() {
2735      1 => {
2736        if tag.wire_type() != WireType::LengthDelimited {
2737          return Err(DecodeError::WireTypeMismatch {
2738            field_number: 1,
2739            expected: LEN,
2740            actual: tag.wire_type() as u8,
2741          });
2742        }
2743        let s = decode_string(buf)?;
2744        self.set_make(s.as_str());
2745      }
2746      2 => {
2747        if tag.wire_type() != WireType::LengthDelimited {
2748          return Err(DecodeError::WireTypeMismatch {
2749            field_number: 2,
2750            expected: LEN,
2751            actual: tag.wire_type() as u8,
2752          });
2753        }
2754        let s = decode_string(buf)?;
2755        self.set_model(s.as_str());
2756      }
2757      _ => skip_field_depth(tag, buf, ctx.depth())?,
2758    }
2759    Ok(())
2760  }
2761
2762  fn clear(&mut self) {
2763    *self = Device::default();
2764  }
2765}
2766
2767// ----------------------------------------------------------------------------
2768// GeoLocation — { double lat = 1; double lon = 2; float altitude = 3; }
2769//
2770// `lat` and `lon` are always encoded: the default `(0.0, 0.0)` is
2771// "Null Island" — a real, legal coordinate. Proto3 zero-elision would
2772// conflate it with an absent field, which is unsound (same defensive
2773// `mediatime::Timebase` stance as `SampleAspectRatio`).
2774//
2775// `altitude` is presence-encoded: field #3 is written iff
2776// `Some(_)`, including for an explicit `Some(0.0)` (sea level); an
2777// absent field #3 on the wire decodes back to `None`. No companion
2778// presence bit is needed because the encoder is the sole writer.
2779// ----------------------------------------------------------------------------
2780
2781#[cfg(any(feature = "std", feature = "alloc"))]
2782impl DefaultInstance for GeoLocation {
2783  fn default_instance() -> &'static Self {
2784    static VALUE: buffa::__private::OnceBox<GeoLocation> = buffa::__private::OnceBox::new();
2785    VALUE.get_or_init(|| {
2786      buffa::alloc::boxed::Box::new(GeoLocation::try_new(0.0, 0.0, None).expect("0,0 is valid"))
2787    })
2788  }
2789}
2790
2791#[cfg(any(feature = "std", feature = "alloc"))]
2792impl Message for GeoLocation {
2793  fn compute_size(&self, _cache: &mut SizeCache) -> u32 {
2794    // lat (Fixed64) + lon (Fixed64), always encoded: 1-byte tag + 8 bytes each.
2795    let mut size = (1 + 8) + (1 + 8);
2796    if self.altitude().is_some() {
2797      // altitude (Fixed32): 1-byte tag + 4 bytes.
2798      size += 1 + 4;
2799    }
2800    size
2801  }
2802
2803  fn write_to(&self, _cache: &mut SizeCache, buf: &mut impl EncodeSink) {
2804    Tag::new(1, WireType::Fixed64).encode(buf);
2805    encode_double(self.lat(), buf);
2806    Tag::new(2, WireType::Fixed64).encode(buf);
2807    encode_double(self.lon(), buf);
2808    if let Some(alt) = self.altitude() {
2809      Tag::new(3, WireType::Fixed32).encode(buf);
2810      encode_float(alt, buf);
2811    }
2812  }
2813
2814  fn merge_field(
2815    &mut self,
2816    tag: Tag,
2817    buf: &mut impl Buf,
2818    ctx: DecodeContext<'_>,
2819  ) -> Result<(), DecodeError> {
2820    match tag.field_number() {
2821      1 => {
2822        if tag.wire_type() != WireType::Fixed64 {
2823          return Err(DecodeError::WireTypeMismatch {
2824            field_number: 1,
2825            expected: WireType::Fixed64 as u8,
2826            actual: tag.wire_type() as u8,
2827          });
2828        }
2829        let v = decode_double(buf)?;
2830        let prev = *self;
2831        // Range-clamp at the boundary: a malformed wire value
2832        // outside [-90, 90] is replaced with the closest valid
2833        // extreme so decode is total (mirrors the
2834        // `SampleAspectRatio` `den == 0` → `1` defensive clamp).
2835        let lat = if v.is_finite() {
2836          v.clamp(-90.0, 90.0)
2837        } else {
2838          0.0
2839        };
2840        *self =
2841          GeoLocation::try_new(lat, prev.lon(), prev.altitude()).expect("clamped lat is in range");
2842      }
2843      2 => {
2844        if tag.wire_type() != WireType::Fixed64 {
2845          return Err(DecodeError::WireTypeMismatch {
2846            field_number: 2,
2847            expected: WireType::Fixed64 as u8,
2848            actual: tag.wire_type() as u8,
2849          });
2850        }
2851        let v = decode_double(buf)?;
2852        let prev = *self;
2853        let lon = if v.is_finite() {
2854          v.clamp(-180.0, 180.0)
2855        } else {
2856          0.0
2857        };
2858        *self =
2859          GeoLocation::try_new(prev.lat(), lon, prev.altitude()).expect("clamped lon is in range");
2860      }
2861      3 => {
2862        if tag.wire_type() != WireType::Fixed32 {
2863          return Err(DecodeError::WireTypeMismatch {
2864            field_number: 3,
2865            expected: WireType::Fixed32 as u8,
2866            actual: tag.wire_type() as u8,
2867          });
2868        }
2869        let v = decode_float(buf)?;
2870        self.set_altitude(v);
2871      }
2872      _ => skip_field_depth(tag, buf, ctx.depth())?,
2873    }
2874    Ok(())
2875  }
2876
2877  fn clear(&mut self) {
2878    *self = GeoLocation::try_new(0.0, 0.0, None).expect("0,0 is valid");
2879  }
2880}
2881
2882// ----------------------------------------------------------------------------
2883// LanguageId — { string value = 1; }
2884//
2885// Encodes the canonical BCP 47 tag at field #1. proto3 zero-elision
2886// applies to the empty string; since `LanguageId::default()` is the
2887// `"und"` tag (non-empty), the encoder always writes it. On decode, an
2888// absent field (empty buffer / unknown-field skip) seeds back to
2889// `Default` = `"und"`.
2890// ----------------------------------------------------------------------------
2891
2892#[cfg(any(feature = "std", feature = "alloc"))]
2893impl DefaultInstance for LanguageId {
2894  fn default_instance() -> &'static Self {
2895    static VALUE: buffa::__private::OnceBox<LanguageId> = buffa::__private::OnceBox::new();
2896    VALUE.get_or_init(|| buffa::alloc::boxed::Box::new(LanguageId::default()))
2897  }
2898}
2899
2900#[cfg(any(feature = "std", feature = "alloc"))]
2901impl Message for LanguageId {
2902  fn compute_size(&self, _cache: &mut SizeCache) -> u32 {
2903    let tag = self.to_string();
2904    if tag.is_empty() {
2905      0
2906    } else {
2907      1 + string_encoded_len(&tag) as u32
2908    }
2909  }
2910
2911  fn write_to(&self, _cache: &mut SizeCache, buf: &mut impl EncodeSink) {
2912    let tag = self.to_string();
2913    if !tag.is_empty() {
2914      Tag::new(1, WireType::LengthDelimited).encode(buf);
2915      encode_string(&tag, buf);
2916    }
2917  }
2918
2919  fn merge_field(
2920    &mut self,
2921    tag: Tag,
2922    buf: &mut impl Buf,
2923    ctx: DecodeContext<'_>,
2924  ) -> Result<(), DecodeError> {
2925    match tag.field_number() {
2926      1 => {
2927        if tag.wire_type() != WireType::LengthDelimited {
2928          return Err(DecodeError::WireTypeMismatch {
2929            field_number: 1,
2930            expected: LEN,
2931            actual: tag.wire_type() as u8,
2932          });
2933        }
2934        let s = decode_string(buf)?;
2935        // A wire value the whole-tag door refuses is mapped to
2936        // `LanguageId::default()` (the ISO 639-3 `"und"` "undetermined"
2937        // sentinel) rather than failing the decode — that is the same
2938        // semantics the type uses in-rust for "no usable language tag",
2939        // and keeps the decoder total. `buffa::DecodeError` has no
2940        // general "invalid value" arm, so silent coercion to the
2941        // already-existing sentinel is the least-bad choice.
2942        *self = LanguageId::new(&s).unwrap_or_default();
2943      }
2944      _ => skip_field_depth(tag, buf, ctx.depth())?,
2945    }
2946    Ok(())
2947  }
2948
2949  fn clear(&mut self) {
2950    *self = LanguageId::default();
2951  }
2952}
2953
2954#[cfg(test)]
2955mod tests;