Skip to main content

buffa/
extension.rs

1//! Typed access to protobuf extensions stored in unknown fields.
2//!
3//! Custom options — `(buf.validate.field)`, `(google.api.http)`, etc. — are
4//! declared with `extend google.protobuf.FieldOptions { ... }` and attached in
5//! proto source as `[(my.option) = {...}]`. Editions removed general-purpose
6//! message extensions but **custom options remain the sanctioned use of
7//! `extend`**: `descriptor.proto` still declares `extensions 1000 to max;` on
8//! every `*Options` message.
9//!
10//! On the wire, extension values are ordinary fields at their declared field
11//! numbers. When an extendee is decoded without the extension in its schema,
12//! those fields land in [`UnknownFields`] — already preserved. This module
13//! provides a typed extraction/injection path on top of that storage.
14//!
15//! # Usage
16//!
17//! Codegen emits a `pub const` for each `extend` declaration:
18//!
19//! ```ignore
20//! // Generated from: extend google.protobuf.FieldOptions { optional FieldRules field = 1159; }
21//! pub const FIELD: buffa::Extension<buffa::extension::codecs::MessageCodec<FieldRules>>
22//!     = buffa::Extension::new(1159, "google.protobuf.FieldOptions");
23//! ```
24//!
25//! The extendee (any message with unknown-field preservation) implements
26//! [`ExtensionSet`]:
27//!
28//! ```ignore
29//! use buffa::ExtensionSet;
30//! let rules: Option<FieldRules> = field.options.extension(&buf_validate::FIELD);
31//! opts.set_extension(&buf_validate::FIELD, my_rules);
32//! ```
33//!
34//! # Panics
35//!
36//! [`extension`], [`set_extension`], and [`clear_extension`] panic if the
37//! descriptor's [`extendee`](Extension::extendee) does not match the extendee
38//! message's [`PROTO_FQN`](ExtensionSet::PROTO_FQN). This catches bugs like
39//! `field_options.extension(&MESSAGE_LEVEL_OPTION)` at the first call site
40//! (matches protobuf-go, which panics, and protobuf-es, which throws).
41//! [`has_extension`] returns `false` gracefully on mismatch — "is this
42//! extension set here" when it can't extend here has a legitimate answer.
43//!
44//! # Defaults
45//!
46//! Proto2 `[default = ...]` values are surfaced by [`extension_or_default`],
47//! which returns the declared default when the extension is absent. Presence
48//! is still distinguishable via [`extension`] (returns `None`) or
49//! [`has_extension`].
50//!
51//! # JSON
52//!
53//! Extension fields serialize as `"[pkg.ext]"` keys in proto3 JSON. This
54//! requires a populated `TypeRegistry` — see the `type_registry` module
55//! (available under the `json` or `text` feature). Without a registry,
56//! extension bytes stay in `__buffa_unknown_fields` and are silently
57//! dropped from JSON output.
58//!
59//! # Presence semantics
60//!
61//! Extensions **always** have explicit field presence, regardless of proto3 or
62//! editions `IMPLICIT` file defaults (see protocolbuffers/protobuf#8234). This
63//! falls out naturally from unknown-field storage: `set_extension(&ext, 0)`
64//! pushes a record with value 0, so `has_extension` returns true. Singular
65//! `Output` is therefore `Option<T>`, not `T` with a sentinel.
66//!
67//! [`extension`]: ExtensionSet::extension
68//! [`set_extension`]: ExtensionSet::set_extension
69//! [`clear_extension`]: ExtensionSet::clear_extension
70//! [`has_extension`]: ExtensionSet::has_extension
71//! [`extension_or_default`]: ExtensionSet::extension_or_default
72
73use core::marker::PhantomData;
74
75use crate::unknown_fields::UnknownFields;
76
77/// Typed extension descriptor.
78///
79/// Emitted by codegen as a `pub const` for each `extend` declaration. The
80/// type parameter `C` is an [`ExtensionCodec`] — a zero-sized codec struct
81/// that encodes the proto field type. Users don't name `C` directly; it flows
82/// through inference from the `const` to the [`ExtensionSet`] method call.
83///
84/// For proto2 extensions declared with `[default = ...]`, codegen stores a
85/// function pointer that lazily produces the default value. See
86/// [`Extension::with_default`] and [`ExtensionSet::extension_or_default`].
87#[derive(Debug)]
88pub struct Extension<C: ExtensionCodec> {
89    number: u32,
90    /// Fully-qualified proto name of the extendee (e.g.
91    /// `"google.protobuf.FieldOptions"`), no leading dot.
92    ///
93    /// Checked against [`ExtensionSet::PROTO_FQN`] on `extension()`,
94    /// `set_extension()`, and `clear_extension()` — a mismatch panics.
95    /// `has_extension()` stays graceful (returns `false`), matching
96    /// protobuf-go and protobuf-es precedent.
97    extendee: &'static str,
98    default: Option<fn() -> C::Value>,
99    _codec: PhantomData<fn() -> C>,
100}
101
102impl<C: ExtensionCodec> Extension<C> {
103    /// Construct an extension descriptor for the given field number and
104    /// extendee message.
105    ///
106    /// `const fn` so that generated `pub const` items can use it.
107    ///
108    /// `extendee` is the fully-qualified proto type name (no leading dot) of
109    /// the message this extension extends — e.g. `"google.protobuf.FieldOptions"`.
110    /// Passing an extension with a mismatched extendee to `extension()` /
111    /// `set_extension()` / `clear_extension()` will panic.
112    ///
113    /// Field number `0` is invalid in protobuf. Codegen never emits it;
114    /// a descriptor constructed with `0` will never match valid wire data.
115    pub const fn new(number: u32, extendee: &'static str) -> Self {
116        Self {
117            number,
118            extendee,
119            default: None,
120            _codec: PhantomData,
121        }
122    }
123
124    /// Construct an extension descriptor with a proto2 `[default = ...]` value.
125    ///
126    /// The default is returned by [`ExtensionSet::extension_or_default`] when
127    /// the extension is absent. [`ExtensionSet::extension`] continues to return
128    /// `None` when absent — this is additive, not a semantic change.
129    ///
130    /// The function pointer is called lazily on each `extension_or_default`
131    /// call. For `Copy` scalars codegen emits a `const fn`; for `String` and
132    /// `bytes` a regular `fn` (allocates on each call — same cost as a
133    /// hand-written `.unwrap_or_else(|| "x".into())`).
134    pub const fn with_default(
135        number: u32,
136        extendee: &'static str,
137        default: fn() -> C::Value,
138    ) -> Self {
139        Self {
140            number,
141            extendee,
142            default: Some(default),
143            _codec: PhantomData,
144        }
145    }
146
147    /// The extension's field number on the extendee.
148    pub const fn number(&self) -> u32 {
149        self.number
150    }
151
152    /// The fully-qualified proto name of the extendee message.
153    pub const fn extendee(&self) -> &'static str {
154        self.extendee
155    }
156}
157
158/// Asserts that `ext` actually extends `Self`. Called from `extension()`,
159/// `set_extension()`, and `clear_extension()` (but NOT `has_extension()` —
160/// asking "is this extension set here" has a legitimate answer of `false`
161/// when it can't extend here, matching protobuf-go and protobuf-es).
162///
163/// `#[track_caller]` so the panic points at the user's call site, not here.
164#[track_caller]
165#[inline]
166fn assert_extendee<C: ExtensionCodec>(ext: &Extension<C>, expected: &'static str) {
167    assert_eq!(
168        ext.extendee, expected,
169        "extension at field {} extends `{}`, not `{}`",
170        ext.number, ext.extendee, expected
171    );
172}
173
174// Manual impls avoid a `C: Clone` / `C: Copy` bound that `#[derive]` would add.
175// `Option<fn() -> T>` is `Copy` for any `T` (fn pointers are always `Copy`),
176// so the struct remains `Copy` regardless of the codec's `Value` type.
177impl<C: ExtensionCodec> Clone for Extension<C> {
178    fn clone(&self) -> Self {
179        *self
180    }
181}
182impl<C: ExtensionCodec> Copy for Extension<C> {}
183
184/// One impl per proto field type. `Value` is what users pass to `set`;
185/// `Output` is what `get` returns (`Option<Value>` for singular,
186/// `Vec<Elem>` for repeated).
187pub trait ExtensionCodec {
188    /// The value type passed to [`ExtensionSet::set_extension`].
189    type Value;
190    /// The return type of [`ExtensionSet::extension`].
191    type Output;
192
193    /// Decode this extension's value from the extendee's unknown fields.
194    fn decode(number: u32, fields: &UnknownFields) -> Self::Output;
195
196    /// Encode `value` into the extendee's unknown fields.
197    ///
198    /// The caller is responsible for clearing any prior occurrences (see
199    /// [`ExtensionSet::set_extension`]).
200    fn encode(number: u32, value: Self::Value, fields: &mut UnknownFields);
201}
202
203/// Implemented by codegen on every message that preserves unknown fields.
204///
205/// The only required methods are the two `unknown_fields*` accessors; all
206/// extension operations are defaulted on top of them. The generated impl is
207/// therefore a two-line body.
208///
209/// Not object-safe (the default methods are generic over `C`). Extension
210/// access is always statically dispatched from a `const` descriptor.
211pub trait ExtensionSet {
212    /// Fully-qualified proto type name of this message (no leading dot),
213    /// e.g. `"google.protobuf.FieldOptions"`.
214    ///
215    /// Checked against [`Extension::extendee`] on every `extension()`,
216    /// `set_extension()`, and `clear_extension()` call. A mismatch panics:
217    /// passing an extension for the wrong message is a bug in the caller.
218    const PROTO_FQN: &'static str;
219
220    /// Immutable access to the extendee's unknown-field storage.
221    fn unknown_fields(&self) -> &UnknownFields;
222    /// Mutable access to the extendee's unknown-field storage.
223    fn unknown_fields_mut(&mut self) -> &mut UnknownFields;
224
225    /// Read an extension value.
226    ///
227    /// For singular extensions: `Option<T>` — `None` if absent or if the
228    /// stored wire data is malformed for this codec. For repeated: `Vec<T>`.
229    ///
230    /// # Panics
231    ///
232    /// Panics if `ext.extendee()` does not match `Self::PROTO_FQN`.
233    #[track_caller]
234    fn extension<C: ExtensionCodec>(&self, ext: &Extension<C>) -> C::Output {
235        assert_extendee(ext, Self::PROTO_FQN);
236        C::decode(ext.number, self.unknown_fields())
237    }
238
239    /// Write an extension value, replacing any prior occurrences.
240    ///
241    /// # Panics
242    ///
243    /// Panics if `ext.extendee()` does not match `Self::PROTO_FQN`.
244    #[track_caller]
245    fn set_extension<C: ExtensionCodec>(&mut self, ext: &Extension<C>, value: C::Value) {
246        assert_extendee(ext, Self::PROTO_FQN);
247        self.unknown_fields_mut().retain(|f| f.number != ext.number);
248        C::encode(ext.number, value, self.unknown_fields_mut());
249    }
250
251    /// Returns `true` if any record at the extension's field number is present.
252    ///
253    /// Does not check wire-type validity — this is a fast presence test, not
254    /// a decode. Also does not check extendee identity: asking "is this
255    /// extension set here" when it can't extend here has a legitimate answer
256    /// (`false`). This matches protobuf-go's `HasExtension` and protobuf-es's
257    /// `hasExtension`, both of which return `false` gracefully on mismatch.
258    fn has_extension<C: ExtensionCodec>(&self, ext: &Extension<C>) -> bool {
259        if ext.extendee != Self::PROTO_FQN {
260            return false;
261        }
262        self.unknown_fields().iter().any(|f| f.number == ext.number)
263    }
264
265    /// Remove all records at the extension's field number.
266    ///
267    /// # Panics
268    ///
269    /// Panics if `ext.extendee()` does not match `Self::PROTO_FQN`.
270    #[track_caller]
271    fn clear_extension<C: ExtensionCodec>(&mut self, ext: &Extension<C>) {
272        assert_extendee(ext, Self::PROTO_FQN);
273        self.unknown_fields_mut().retain(|f| f.number != ext.number);
274    }
275
276    /// Read a singular extension value, returning the proto2 `[default = ...]`
277    /// value if absent, or the type's `Default` if no proto default was declared.
278    ///
279    /// Only meaningful for singular codecs (`Output = Option<Value>`). For
280    /// repeated codecs use [`extension`](Self::extension) — there is no such
281    /// thing as a repeated default.
282    ///
283    /// Presence is still distinguishable via [`extension`](Self::extension)
284    /// (returns `None`) or [`has_extension`](Self::has_extension).
285    ///
286    /// # Panics
287    ///
288    /// Panics if `ext.extendee()` does not match `Self::PROTO_FQN`
289    /// (transitively, via the inner `extension()` call).
290    #[must_use]
291    #[track_caller]
292    fn extension_or_default<C>(&self, ext: &Extension<C>) -> C::Value
293    where
294        C: ExtensionCodec<Output = Option<<C as ExtensionCodec>::Value>>,
295        C::Value: Default,
296    {
297        self.extension(ext)
298            .or_else(|| ext.default.map(|f| f()))
299            .unwrap_or_default()
300    }
301}
302
303/// Codec types — one per proto field type.
304///
305/// These live in a submodule so they don't clutter the crate root. Generated
306/// consts mention the codec type (`Extension<codecs::MessageCodec<FieldRules>>`)
307/// but users never type it out — they just `opts.extension(&FIELD)` and
308/// inference handles the rest.
309pub mod codecs {
310    use core::marker::PhantomData;
311
312    use alloc::string::String;
313    use alloc::vec::Vec;
314    use bytes::Buf;
315
316    use crate::encoding::{decode_varint, encode_varint};
317    use crate::message::Message;
318    use crate::types::{
319        zigzag_decode_i32, zigzag_decode_i64, zigzag_encode_i32, zigzag_encode_i64,
320    };
321    use crate::unknown_fields::{UnknownField, UnknownFieldData, UnknownFields};
322
323    use super::ExtensionCodec;
324
325    /// Codecs that can appear as elements of [`Repeated`] / [`PackedRepeated`].
326    ///
327    /// Separated from [`ExtensionCodec`] because the singular decode semantics
328    /// differ by type: scalars use last-wins, but singular messages merge all
329    /// records. This trait provides the per-record primitives; each codec
330    /// assembles them into its own [`ExtensionCodec::decode`].
331    pub trait SingularCodec {
332        type Value;
333
334        /// Decode one value from one unknown-field record's data.
335        ///
336        /// Returns `None` on wire-type mismatch (and, for string/message,
337        /// on malformed payload).
338        fn decode_one(data: &UnknownFieldData) -> Option<Self::Value>;
339
340        /// Decode all values from a packed `LengthDelimited` payload.
341        ///
342        /// Non-packable types (string, bytes, message) **must leave `out`
343        /// unmodified**: `decode_repeated` falls through to this method when
344        /// [`decode_one`](Self::decode_one) returns `None` for a
345        /// `LengthDelimited` record, relying on the no-op to skip malformed
346        /// elements. A `LengthDelimited` record at their field number IS the
347        /// single value — there is no packed form.
348        fn decode_packed(bytes: &[u8], out: &mut Vec<Self::Value>);
349
350        /// Encode one value as a single unknown-field record.
351        fn encode_one(value: &Self::Value) -> UnknownFieldData;
352    }
353
354    /// Codecs whose elements can be concatenated into a packed wire form.
355    ///
356    /// Only varint-family and fixed-width scalars are packable. String, bytes,
357    /// and message use `LengthDelimited` for a single value, so there's no
358    /// distinct packed encoding.
359    pub trait PackableCodec: SingularCodec {
360        /// Write one value's wire payload (without tag) into `buf`.
361        fn encode_packed(value: &Self::Value, buf: &mut Vec<u8>);
362    }
363
364    // ─────────────────────────────────────────────────────────────────────
365    // Varint-family scalar codecs
366    // ─────────────────────────────────────────────────────────────────────
367
368    macro_rules! varint_codec {
369        ($name:ident, $ty:ty, |$d:ident| $decode:expr, |$e:ident| $encode:expr $(,)?) => {
370            #[doc = concat!("Codec for the `", stringify!($name), "` proto scalar type.")]
371            pub struct $name;
372
373            impl ExtensionCodec for $name {
374                type Value = $ty;
375                type Output = Option<$ty>;
376                fn decode(number: u32, fields: &UnknownFields) -> Option<$ty> {
377                    fields
378                        .iter()
379                        .rev()
380                        .filter(|f| f.number == number)
381                        .find_map(|f| Self::decode_one(&f.data))
382                }
383                fn encode(number: u32, value: $ty, fields: &mut UnknownFields) {
384                    fields.push(UnknownField {
385                        number,
386                        data: Self::encode_one(&value),
387                    });
388                }
389            }
390
391            impl SingularCodec for $name {
392                type Value = $ty;
393                fn decode_one(data: &UnknownFieldData) -> Option<$ty> {
394                    match *data {
395                        UnknownFieldData::Varint($d) => Some($decode),
396                        _ => None,
397                    }
398                }
399                fn decode_packed(bytes: &[u8], out: &mut Vec<$ty>) {
400                    let mut buf = bytes;
401                    while buf.has_remaining() {
402                        match decode_varint(&mut buf) {
403                            Ok($d) => out.push($decode),
404                            Err(_) => return,
405                        }
406                    }
407                }
408                fn encode_one($e: &$ty) -> UnknownFieldData {
409                    let $e = *$e;
410                    UnknownFieldData::Varint($encode)
411                }
412            }
413
414            impl PackableCodec for $name {
415                fn encode_packed($e: &$ty, buf: &mut Vec<u8>) {
416                    let $e = *$e;
417                    encode_varint($encode, buf);
418                }
419            }
420        };
421    }
422
423    // `int32` negative values are sign-extended to 64 bits before varint
424    // encoding (matching protoc's behavior — a negative int32 is 10 bytes on
425    // the wire). `sint32` uses zigzag instead.
426    varint_codec!(Int32, i32, |v| v as i32, |v| v as i64 as u64);
427    varint_codec!(Int64, i64, |v| v as i64, |v| v as u64);
428    varint_codec!(Uint32, u32, |v| v as u32, |v| v as u64);
429    varint_codec!(Uint64, u64, |v| v, |v| v);
430    varint_codec!(
431        Sint32,
432        i32,
433        |v| zigzag_decode_i32(v as u32),
434        |v| zigzag_encode_i32(v) as u64
435    );
436    varint_codec!(
437        Sint64,
438        i64,
439        |v| zigzag_decode_i64(v),
440        |v| zigzag_encode_i64(v)
441    );
442    varint_codec!(Bool, bool, |v| v != 0, |v| v as u64);
443    /// Codec for proto `enum` extension fields.
444    ///
445    /// `Value = i32`; cast via `EnumValue::from_i32` at the call site.
446    /// A type-directed enum codec (emitting `Extension<MyEnum>`) is deferred.
447    pub struct EnumI32;
448    // EnumI32 is wire-identical to Int32 — delegate rather than re-expand.
449    impl ExtensionCodec for EnumI32 {
450        type Value = i32;
451        type Output = Option<i32>;
452        fn decode(number: u32, fields: &UnknownFields) -> Option<i32> {
453            Int32::decode(number, fields)
454        }
455        fn encode(number: u32, value: i32, fields: &mut UnknownFields) {
456            Int32::encode(number, value, fields)
457        }
458    }
459    impl SingularCodec for EnumI32 {
460        type Value = i32;
461        fn decode_one(data: &UnknownFieldData) -> Option<i32> {
462            Int32::decode_one(data)
463        }
464        fn decode_packed(bytes: &[u8], out: &mut Vec<i32>) {
465            Int32::decode_packed(bytes, out)
466        }
467        fn encode_one(value: &i32) -> UnknownFieldData {
468            Int32::encode_one(value)
469        }
470    }
471    impl PackableCodec for EnumI32 {
472        fn encode_packed(value: &i32, buf: &mut Vec<u8>) {
473            Int32::encode_packed(value, buf)
474        }
475    }
476
477    // ─────────────────────────────────────────────────────────────────────
478    // Fixed-width scalar codecs
479    // ─────────────────────────────────────────────────────────────────────
480
481    macro_rules! fixed32_codec {
482        ($name:ident, $ty:ty, |$d:ident| $decode:expr, |$e:ident| $encode:expr $(,)?) => {
483            #[doc = concat!("Codec for the `", stringify!($name), "` proto scalar type.")]
484            pub struct $name;
485
486            impl ExtensionCodec for $name {
487                type Value = $ty;
488                type Output = Option<$ty>;
489                fn decode(number: u32, fields: &UnknownFields) -> Option<$ty> {
490                    fields
491                        .iter()
492                        .rev()
493                        .filter(|f| f.number == number)
494                        .find_map(|f| Self::decode_one(&f.data))
495                }
496                fn encode(number: u32, value: $ty, fields: &mut UnknownFields) {
497                    fields.push(UnknownField {
498                        number,
499                        data: Self::encode_one(&value),
500                    });
501                }
502            }
503
504            impl SingularCodec for $name {
505                type Value = $ty;
506                fn decode_one(data: &UnknownFieldData) -> Option<$ty> {
507                    match *data {
508                        UnknownFieldData::Fixed32($d) => Some($decode),
509                        _ => None,
510                    }
511                }
512                fn decode_packed(bytes: &[u8], out: &mut Vec<$ty>) {
513                    let mut buf = bytes;
514                    while buf.remaining() >= 4 {
515                        let $d = buf.get_u32_le();
516                        out.push($decode);
517                    }
518                }
519                fn encode_one($e: &$ty) -> UnknownFieldData {
520                    let $e = *$e;
521                    UnknownFieldData::Fixed32($encode)
522                }
523            }
524
525            impl PackableCodec for $name {
526                fn encode_packed($e: &$ty, buf: &mut Vec<u8>) {
527                    use bytes::BufMut;
528                    let $e = *$e;
529                    buf.put_u32_le($encode);
530                }
531            }
532        };
533    }
534
535    macro_rules! fixed64_codec {
536        ($name:ident, $ty:ty, |$d:ident| $decode:expr, |$e:ident| $encode:expr $(,)?) => {
537            #[doc = concat!("Codec for the `", stringify!($name), "` proto scalar type.")]
538            pub struct $name;
539
540            impl ExtensionCodec for $name {
541                type Value = $ty;
542                type Output = Option<$ty>;
543                fn decode(number: u32, fields: &UnknownFields) -> Option<$ty> {
544                    fields
545                        .iter()
546                        .rev()
547                        .filter(|f| f.number == number)
548                        .find_map(|f| Self::decode_one(&f.data))
549                }
550                fn encode(number: u32, value: $ty, fields: &mut UnknownFields) {
551                    fields.push(UnknownField {
552                        number,
553                        data: Self::encode_one(&value),
554                    });
555                }
556            }
557
558            impl SingularCodec for $name {
559                type Value = $ty;
560                fn decode_one(data: &UnknownFieldData) -> Option<$ty> {
561                    match *data {
562                        UnknownFieldData::Fixed64($d) => Some($decode),
563                        _ => None,
564                    }
565                }
566                fn decode_packed(bytes: &[u8], out: &mut Vec<$ty>) {
567                    let mut buf = bytes;
568                    while buf.remaining() >= 8 {
569                        let $d = buf.get_u64_le();
570                        out.push($decode);
571                    }
572                }
573                fn encode_one($e: &$ty) -> UnknownFieldData {
574                    let $e = *$e;
575                    UnknownFieldData::Fixed64($encode)
576                }
577            }
578
579            impl PackableCodec for $name {
580                fn encode_packed($e: &$ty, buf: &mut Vec<u8>) {
581                    use bytes::BufMut;
582                    let $e = *$e;
583                    buf.put_u64_le($encode);
584                }
585            }
586        };
587    }
588
589    fixed32_codec!(Fixed32, u32, |v| v, |v| v);
590    fixed32_codec!(Sfixed32, i32, |v| v as i32, |v| v as u32);
591    fixed32_codec!(Float, f32, |v| f32::from_bits(v), |v| v.to_bits());
592    fixed64_codec!(Fixed64, u64, |v| v, |v| v);
593    fixed64_codec!(Sfixed64, i64, |v| v as i64, |v| v as u64);
594    fixed64_codec!(Double, f64, |v| f64::from_bits(v), |v| v.to_bits());
595
596    // ─────────────────────────────────────────────────────────────────────
597    // String / bytes / message codecs (hand-written, not packable)
598    // ─────────────────────────────────────────────────────────────────────
599
600    /// Codec for the `string` proto type.
601    pub struct StringCodec;
602
603    impl ExtensionCodec for StringCodec {
604        type Value = String;
605        type Output = Option<String>;
606        fn decode(number: u32, fields: &UnknownFields) -> Option<String> {
607            fields
608                .iter()
609                .rev()
610                .filter(|f| f.number == number)
611                .find_map(|f| Self::decode_one(&f.data))
612        }
613        fn encode(number: u32, value: String, fields: &mut UnknownFields) {
614            fields.push(UnknownField {
615                number,
616                data: UnknownFieldData::LengthDelimited(value.into_bytes()),
617            });
618        }
619    }
620
621    impl SingularCodec for StringCodec {
622        type Value = String;
623        fn decode_one(data: &UnknownFieldData) -> Option<String> {
624            match data {
625                UnknownFieldData::LengthDelimited(bytes) => String::from_utf8(bytes.clone()).ok(),
626                _ => None,
627            }
628        }
629        fn decode_packed(_bytes: &[u8], _out: &mut Vec<String>) {}
630        fn encode_one(value: &String) -> UnknownFieldData {
631            UnknownFieldData::LengthDelimited(value.clone().into_bytes())
632        }
633    }
634
635    /// Codec for the `bytes` proto type.
636    pub struct BytesCodec;
637
638    impl ExtensionCodec for BytesCodec {
639        type Value = Vec<u8>;
640        type Output = Option<Vec<u8>>;
641        fn decode(number: u32, fields: &UnknownFields) -> Option<Vec<u8>> {
642            fields
643                .iter()
644                .rev()
645                .filter(|f| f.number == number)
646                .find_map(|f| Self::decode_one(&f.data))
647        }
648        fn encode(number: u32, value: Vec<u8>, fields: &mut UnknownFields) {
649            fields.push(UnknownField {
650                number,
651                data: UnknownFieldData::LengthDelimited(value),
652            });
653        }
654    }
655
656    impl SingularCodec for BytesCodec {
657        type Value = Vec<u8>;
658        fn decode_one(data: &UnknownFieldData) -> Option<Vec<u8>> {
659            match data {
660                UnknownFieldData::LengthDelimited(bytes) => Some(bytes.clone()),
661                _ => None,
662            }
663        }
664        fn decode_packed(_bytes: &[u8], _out: &mut Vec<Vec<u8>>) {}
665        fn encode_one(value: &Vec<u8>) -> UnknownFieldData {
666            UnknownFieldData::LengthDelimited(value.clone())
667        }
668    }
669
670    /// Codec for message-typed extension fields.
671    ///
672    /// Singular decode **merges all** `LengthDelimited` records at the field
673    /// number (proto spec: split messages merge). Any malformed record aborts
674    /// the merge and returns `None`.
675    pub struct MessageCodec<M>(PhantomData<fn() -> M>);
676
677    impl<M: Message + Default> ExtensionCodec for MessageCodec<M> {
678        type Value = M;
679        type Output = Option<M>;
680        fn decode(number: u32, fields: &UnknownFields) -> Option<M> {
681            let mut msg: Option<M> = None;
682            for f in fields.iter().filter(|f| f.number == number) {
683                if let UnknownFieldData::LengthDelimited(bytes) = &f.data {
684                    let m = msg.get_or_insert_with(M::default);
685                    if m.merge_from_slice(bytes).is_err() {
686                        return None;
687                    }
688                }
689            }
690            msg
691        }
692        fn encode(number: u32, value: M, fields: &mut UnknownFields) {
693            fields.push(UnknownField {
694                number,
695                data: UnknownFieldData::LengthDelimited(value.encode_to_vec()),
696            });
697        }
698    }
699
700    impl<M: Message + Default> SingularCodec for MessageCodec<M> {
701        type Value = M;
702        fn decode_one(data: &UnknownFieldData) -> Option<M> {
703            match data {
704                UnknownFieldData::LengthDelimited(bytes) => {
705                    let mut m = M::default();
706                    m.merge_from_slice(bytes).ok()?;
707                    Some(m)
708                }
709                _ => None,
710            }
711        }
712        fn decode_packed(_bytes: &[u8], _out: &mut Vec<M>) {}
713        fn encode_one(value: &M) -> UnknownFieldData {
714            UnknownFieldData::LengthDelimited(value.encode_to_vec())
715        }
716    }
717
718    /// Codec for group-encoded message extension fields (proto2 `group` syntax
719    /// or editions `features.message_encoding = DELIMITED`).
720    ///
721    /// The wire data is [`UnknownFieldData::Group`] — the inner fields are
722    /// already parsed into an [`UnknownFields`] sub-tree by the group decoder.
723    /// Decode re-serializes the inner fields to a temporary buffer then merges
724    /// into `M`; encode does the reverse via [`UnknownFields::decode_from_slice`].
725    ///
726    /// The round-trip through bytes is correct but not optimal. The alternative
727    /// (a `Message::write_to_unknown_fields()` trait method) would be invasive
728    /// for a rare-in-practice path: group-encoded extensions don't appear in
729    /// real custom options.
730    ///
731    /// Singular decode **merges all** `Group` records at the field number
732    /// (same as [`MessageCodec`]). Any malformed record aborts and returns
733    /// `None`.
734    pub struct GroupCodec<M>(PhantomData<fn() -> M>);
735
736    impl<M: Message + Default> ExtensionCodec for GroupCodec<M> {
737        type Value = M;
738        type Output = Option<M>;
739        fn decode(number: u32, fields: &UnknownFields) -> Option<M> {
740            let mut msg: Option<M> = None;
741            for f in fields.iter().filter(|f| f.number == number) {
742                if let UnknownFieldData::Group(inner) = &f.data {
743                    let m = msg.get_or_insert_with(M::default);
744                    let mut buf = Vec::with_capacity(inner.encoded_len());
745                    inner.write_to(&mut buf);
746                    if m.merge_from_slice(&buf).is_err() {
747                        return None;
748                    }
749                }
750            }
751            msg
752        }
753        fn encode(number: u32, value: M, fields: &mut UnknownFields) {
754            let bytes = value.encode_to_vec();
755            // We just encoded `value` — re-decoding its bytes cannot fail
756            // unless there's a bug in the Message encoder itself.
757            let inner = UnknownFields::decode_from_slice(&bytes)
758                .expect("BUG: re-decoding freshly-encoded message bytes failed");
759            fields.push(UnknownField {
760                number,
761                data: UnknownFieldData::Group(inner),
762            });
763        }
764    }
765
766    impl<M: Message + Default> SingularCodec for GroupCodec<M> {
767        type Value = M;
768        fn decode_one(data: &UnknownFieldData) -> Option<M> {
769            match data {
770                UnknownFieldData::Group(inner) => {
771                    let mut buf = Vec::with_capacity(inner.encoded_len());
772                    inner.write_to(&mut buf);
773                    let mut m = M::default();
774                    m.merge_from_slice(&buf).ok()?;
775                    Some(m)
776                }
777                _ => None,
778            }
779        }
780        // Groups are never packed — leave `out` unmodified (see
781        // `SingularCodec::decode_packed` contract).
782        fn decode_packed(_bytes: &[u8], _out: &mut Vec<M>) {}
783        fn encode_one(value: &M) -> UnknownFieldData {
784            let bytes = value.encode_to_vec();
785            // We just encoded `value` — re-decoding cannot fail.
786            let inner = UnknownFields::decode_from_slice(&bytes)
787                .expect("BUG: re-decoding freshly-encoded message bytes failed");
788            UnknownFieldData::Group(inner)
789        }
790    }
791
792    // ─────────────────────────────────────────────────────────────────────
793    // Repeated wrappers
794    // ─────────────────────────────────────────────────────────────────────
795
796    /// Codec for `repeated T` extension fields, unpacked wire encoding.
797    ///
798    /// Decode accepts both packed and unpacked wire forms (proto spec
799    /// requires this). Encode emits one record per element — this is the
800    /// proto2 default for extensions and what `*Options` extendees expect.
801    pub struct Repeated<C>(PhantomData<fn() -> C>);
802
803    impl<C: SingularCodec> ExtensionCodec for Repeated<C> {
804        type Value = Vec<C::Value>;
805        type Output = Vec<C::Value>;
806        fn decode(number: u32, fields: &UnknownFields) -> Vec<C::Value> {
807            decode_repeated::<C>(number, fields)
808        }
809        fn encode(number: u32, value: Vec<C::Value>, fields: &mut UnknownFields) {
810            for v in &value {
811                fields.push(UnknownField {
812                    number,
813                    data: C::encode_one(v),
814                });
815            }
816        }
817    }
818
819    /// Codec for `repeated T` extension fields, packed wire encoding.
820    ///
821    /// Decode accepts both packed and unpacked wire forms (identical to
822    /// [`Repeated`]). Encode emits a single `LengthDelimited` record
823    /// containing concatenated wire values. Only valid for packable scalar
824    /// element types (varint / fixed families).
825    ///
826    /// Codegen picks this over [`Repeated`] when `field.options.packed ==
827    /// Some(true)` or the resolved edition feature `repeated_field_encoding
828    /// == PACKED`.
829    pub struct PackedRepeated<C>(PhantomData<fn() -> C>);
830
831    impl<C: PackableCodec> ExtensionCodec for PackedRepeated<C> {
832        type Value = Vec<C::Value>;
833        type Output = Vec<C::Value>;
834        fn decode(number: u32, fields: &UnknownFields) -> Vec<C::Value> {
835            decode_repeated::<C>(number, fields)
836        }
837        fn encode(number: u32, value: Vec<C::Value>, fields: &mut UnknownFields) {
838            if value.is_empty() {
839                return;
840            }
841            let mut buf = Vec::new();
842            for v in &value {
843                C::encode_packed(v, &mut buf);
844            }
845            fields.push(UnknownField {
846                number,
847                data: UnknownFieldData::LengthDelimited(buf),
848            });
849        }
850    }
851
852    /// Shared repeated-decode logic: accepts both unpacked (one record per
853    /// value) and packed (`LengthDelimited` of concatenated values).
854    fn decode_repeated<C: SingularCodec>(number: u32, fields: &UnknownFields) -> Vec<C::Value> {
855        let mut out = Vec::new();
856        for f in fields.iter().filter(|f| f.number == number) {
857            if let Some(v) = C::decode_one(&f.data) {
858                out.push(v);
859            } else if let UnknownFieldData::LengthDelimited(bytes) = &f.data {
860                C::decode_packed(bytes, &mut out);
861            }
862        }
863        out
864    }
865}
866
867// ─────────────────────────────────────────────────────────────────────────────
868// Tests
869// ─────────────────────────────────────────────────────────────────────────────
870
871#[cfg(test)]
872mod tests {
873    use super::codecs::*;
874    use super::*;
875    use crate::unknown_fields::{UnknownField, UnknownFieldData};
876    use alloc::string::{String, ToString};
877    use alloc::{vec, vec::Vec};
878
879    // Fake extendee — manually implements ExtensionSet over an UnknownFields.
880    // All test `Extension<_>` consts use `CARRIER` as their extendee so the
881    // identity check passes.
882    const CARRIER: &str = "test.Carrier";
883
884    #[derive(Default)]
885    struct Carrier {
886        unknown: UnknownFields,
887    }
888    impl ExtensionSet for Carrier {
889        const PROTO_FQN: &'static str = CARRIER;
890        fn unknown_fields(&self) -> &UnknownFields {
891            &self.unknown
892        }
893        fn unknown_fields_mut(&mut self) -> &mut UnknownFields {
894            &mut self.unknown
895        }
896    }
897
898    fn varint(number: u32, v: u64) -> UnknownField {
899        UnknownField {
900            number,
901            data: UnknownFieldData::Varint(v),
902        }
903    }
904    fn fixed32(number: u32, v: u32) -> UnknownField {
905        UnknownField {
906            number,
907            data: UnknownFieldData::Fixed32(v),
908        }
909    }
910    fn fixed64(number: u32, v: u64) -> UnknownField {
911        UnknownField {
912            number,
913            data: UnknownFieldData::Fixed64(v),
914        }
915    }
916    fn ld(number: u32, data: Vec<u8>) -> UnknownField {
917        UnknownField {
918            number,
919            data: UnknownFieldData::LengthDelimited(data),
920        }
921    }
922    fn group(number: u32, inner: UnknownFields) -> UnknownField {
923        UnknownField {
924            number,
925            data: UnknownFieldData::Group(inner),
926        }
927    }
928
929    // ── Extension<C> basics ─────────────────────────────────────────────────
930
931    #[test]
932    fn extension_const_fn() {
933        const EXT: Extension<Int32> = Extension::new(50001, CARRIER);
934        assert_eq!(EXT.number(), 50001);
935        assert_eq!(EXT.extendee(), CARRIER);
936        let copy = EXT; // Copy
937        assert_eq!(copy.number(), 50001);
938    }
939
940    #[test]
941    fn extension_with_default_const_fn() {
942        // Naming a non-const fn in a const context is fine; only *calling*
943        // it would not be. `with_default` just stores the pointer.
944        const fn seven() -> i32 {
945            7
946        }
947        const E: Extension<Int32> = Extension::with_default(1, CARRIER, seven);
948        assert_eq!(E.number(), 1);
949        assert_eq!(E.extendee(), CARRIER);
950        let copy = E; // still Copy with the fn-pointer field
951        assert_eq!(copy.number(), 1);
952    }
953
954    // ── Extendee identity check ─────────────────────────────────────────────
955
956    // An extension declared for a different message. Using it on `Carrier`
957    // is a bug in the caller — get/set/clear panic, has returns false.
958    const WRONG: Extension<Int32> = Extension::new(1, "other.Message");
959
960    #[test]
961    #[should_panic(expected = "extends `other.Message`, not `test.Carrier`")]
962    fn extension_panics_on_extendee_mismatch() {
963        let c = Carrier::default();
964        let _ = c.extension(&WRONG);
965    }
966
967    #[test]
968    #[should_panic(expected = "extends `other.Message`, not `test.Carrier`")]
969    fn set_extension_panics_on_extendee_mismatch() {
970        let mut c = Carrier::default();
971        c.set_extension(&WRONG, 42);
972    }
973
974    #[test]
975    #[should_panic(expected = "extends `other.Message`, not `test.Carrier`")]
976    fn clear_extension_panics_on_extendee_mismatch() {
977        let mut c = Carrier::default();
978        c.clear_extension(&WRONG);
979    }
980
981    #[test]
982    #[should_panic(expected = "extends `other.Message`, not `test.Carrier`")]
983    fn extension_or_default_panics_on_extendee_mismatch() {
984        // Transitively via the inner extension() call.
985        let c = Carrier::default();
986        let _ = c.extension_or_default(&WRONG);
987    }
988
989    #[test]
990    fn has_extension_returns_false_on_extendee_mismatch() {
991        // has_extension is graceful: matches protobuf-go's HasExtension
992        // (extension.go:24-26) and protobuf-es's hasExtension
993        // (extensions.ts:134), both of which return false rather than
994        // panic/throw on mismatch.
995        let mut c = Carrier::default();
996        // Even with a record at the same field number.
997        c.unknown.push(varint(1, 42));
998        assert!(!c.has_extension(&WRONG));
999        // Same number, matching extendee → true.
1000        const RIGHT: Extension<Int32> = Extension::new(1, CARRIER);
1001        assert!(c.has_extension(&RIGHT));
1002    }
1003
1004    // ── extension_or_default ────────────────────────────────────────────────
1005
1006    #[test]
1007    fn extension_or_default_returns_declared_default_when_absent() {
1008        const fn seven() -> i32 {
1009            7
1010        }
1011        const E: Extension<Int32> = Extension::with_default(1, CARRIER, seven);
1012        let c = Carrier::default();
1013        // extension() still returns None — presence is distinguishable.
1014        assert_eq!(c.extension(&E), None);
1015        assert!(!c.has_extension(&E));
1016        // extension_or_default() returns the declared default.
1017        assert_eq!(c.extension_or_default(&E), 7);
1018    }
1019
1020    #[test]
1021    fn extension_or_default_set_value_wins() {
1022        const fn seven() -> i32 {
1023            7
1024        }
1025        const E: Extension<Int32> = Extension::with_default(1, CARRIER, seven);
1026        let mut c = Carrier::default();
1027        c.set_extension(&E, 99);
1028        // Set value wins over the declared default.
1029        assert_eq!(c.extension_or_default(&E), 99);
1030        assert_eq!(c.extension(&E), Some(99));
1031    }
1032
1033    #[test]
1034    fn extension_or_default_falls_back_to_type_default() {
1035        // No [default] declared → type default (0 for i32).
1036        const E: Extension<Int32> = Extension::new(1, CARRIER);
1037        let c = Carrier::default();
1038        assert_eq!(c.extension_or_default(&E), 0);
1039        assert_eq!(c.extension(&E), None);
1040    }
1041
1042    #[test]
1043    fn extension_or_default_string_allocates_per_call() {
1044        // String default: non-const fn (allocates each call).
1045        fn hello() -> String {
1046            String::from("hello")
1047        }
1048        const E: Extension<StringCodec> = Extension::with_default(1, CARRIER, hello);
1049        let c = Carrier::default();
1050        assert_eq!(c.extension_or_default(&E), "hello");
1051        // Each call is a fresh allocation — the two strings are distinct.
1052        let a = c.extension_or_default(&E);
1053        let b = c.extension_or_default(&E);
1054        assert_eq!(a, b);
1055        assert_ne!(a.as_ptr(), b.as_ptr());
1056    }
1057
1058    #[test]
1059    fn extension_or_default_bytes() {
1060        fn blob() -> Vec<u8> {
1061            alloc::vec![0xDE, 0xAD]
1062        }
1063        const E: Extension<BytesCodec> = Extension::with_default(1, CARRIER, blob);
1064        let c = Carrier::default();
1065        assert_eq!(c.extension_or_default(&E), alloc::vec![0xDE, 0xAD]);
1066    }
1067
1068    #[test]
1069    fn extension_or_default_zero_is_present_not_default() {
1070        // Explicit presence: an explicitly-set 0 is returned, not the default.
1071        const fn seven() -> i32 {
1072            7
1073        }
1074        const E: Extension<Int32> = Extension::with_default(1, CARRIER, seven);
1075        let mut c = Carrier::default();
1076        c.set_extension(&E, 0);
1077        assert_eq!(c.extension_or_default(&E), 0);
1078    }
1079
1080    // ── Singular scalar: roundtrip, last-wins, wire-type mismatch ──────────
1081
1082    #[test]
1083    fn singular_scalar_roundtrip() {
1084        // One representative per wire family plus the zigzag cases.
1085        // Int32 sign-extend: -7 → `as i64 as u64` = 0xFFFF_FFFF_FFFF_FFF9.
1086        #[rustfmt::skip]
1087        let int32_cases: &[(i32, u64)] = &[
1088            (0,   0),
1089            (42,  42),
1090            (-7,  (-7_i64) as u64),
1091        ];
1092        for &(v, wire) in int32_cases {
1093            let mut c = Carrier::default();
1094            const E: Extension<Int32> = Extension::new(1, CARRIER);
1095            c.set_extension(&E, v);
1096            assert_eq!(
1097                c.unknown.iter().next().unwrap().data,
1098                UnknownFieldData::Varint(wire),
1099                "int32 {v}"
1100            );
1101            assert_eq!(c.extension(&E), Some(v), "int32 {v}");
1102        }
1103
1104        // Sint32 zigzag: -1 → 1, 1 → 2, -2 → 3.
1105        #[rustfmt::skip]
1106        let sint32_cases: &[(i32, u64)] = &[
1107            (0,  0),
1108            (-1, 1),
1109            (1,  2),
1110            (-2, 3),
1111        ];
1112        for &(v, wire) in sint32_cases {
1113            let mut c = Carrier::default();
1114            const E: Extension<Sint32> = Extension::new(1, CARRIER);
1115            c.set_extension(&E, v);
1116            assert_eq!(
1117                c.unknown.iter().next().unwrap().data,
1118                UnknownFieldData::Varint(wire),
1119                "sint32 {v}"
1120            );
1121            assert_eq!(c.extension(&E), Some(v), "sint32 {v}");
1122        }
1123
1124        // Sfixed32: bit-cast.
1125        let mut c = Carrier::default();
1126        const SF32: Extension<Sfixed32> = Extension::new(1, CARRIER);
1127        c.set_extension(&SF32, -1);
1128        assert_eq!(
1129            c.unknown.iter().next().unwrap().data,
1130            UnknownFieldData::Fixed32(u32::MAX)
1131        );
1132        assert_eq!(c.extension(&SF32), Some(-1));
1133
1134        // Bool: any nonzero varint decodes as true.
1135        const B: Extension<Bool> = Extension::new(1, CARRIER);
1136        let mut c = Carrier::default();
1137        c.unknown.push(varint(1, 7));
1138        assert_eq!(c.extension(&B), Some(true));
1139        let mut c = Carrier::default();
1140        c.set_extension(&B, true);
1141        assert_eq!(
1142            c.unknown.iter().next().unwrap().data,
1143            UnknownFieldData::Varint(1)
1144        );
1145
1146        // Float/Double: bit roundtrip.
1147        const F: Extension<Float> = Extension::new(1, CARRIER);
1148        let mut c = Carrier::default();
1149        c.set_extension(&F, 1.5_f32);
1150        assert_eq!(c.extension(&F), Some(1.5_f32));
1151        const D: Extension<Double> = Extension::new(2, CARRIER);
1152        c.set_extension(&D, -0.25_f64);
1153        assert_eq!(c.extension(&D), Some(-0.25_f64));
1154
1155        // Uint32: truncates high bits of oversized varint on decode.
1156        const U: Extension<Uint32> = Extension::new(1, CARRIER);
1157        let mut c = Carrier::default();
1158        c.unknown.push(varint(1, 0x1_0000_002A)); // top bit truncated
1159        assert_eq!(c.extension(&U), Some(0x0000_002A));
1160    }
1161
1162    #[test]
1163    fn singular_scalar_last_wins() {
1164        const E: Extension<Int32> = Extension::new(1, CARRIER);
1165        let mut c = Carrier::default();
1166        c.unknown.push(varint(1, 5));
1167        c.unknown.push(varint(1, 7));
1168        assert_eq!(c.extension(&E), Some(7));
1169    }
1170
1171    #[test]
1172    fn singular_scalar_wrong_wire_type_skipped() {
1173        const E: Extension<Int32> = Extension::new(1, CARRIER);
1174        let mut c = Carrier::default();
1175        c.unknown.push(varint(1, 5));
1176        c.unknown.push(ld(1, vec![0x00])); // wrong wire type, skipped
1177        assert_eq!(c.extension(&E), Some(5));
1178
1179        // Only wrong-type records → None.
1180        let mut c = Carrier::default();
1181        c.unknown.push(ld(1, vec![0x00]));
1182        assert_eq!(c.extension(&E), None);
1183    }
1184
1185    #[test]
1186    fn singular_absent_returns_none() {
1187        const E: Extension<Int32> = Extension::new(1, CARRIER);
1188        let c = Carrier::default();
1189        assert_eq!(c.extension(&E), None);
1190        // Other field numbers don't count.
1191        let mut c = Carrier::default();
1192        c.unknown.push(varint(2, 5));
1193        assert_eq!(c.extension(&E), None);
1194    }
1195
1196    // ── Explicit presence (#8234 invariant) ─────────────────────────────────
1197
1198    #[test]
1199    fn explicit_presence_with_zero_value() {
1200        // Extensions always have explicit presence: setting 0 makes it present.
1201        const E: Extension<Int32> = Extension::new(1, CARRIER);
1202        let mut c = Carrier::default();
1203        assert!(!c.has_extension(&E));
1204        c.set_extension(&E, 0);
1205        assert!(c.has_extension(&E));
1206        assert_eq!(c.extension(&E), Some(0));
1207    }
1208
1209    // ── set/clear/has ───────────────────────────────────────────────────────
1210
1211    #[test]
1212    fn set_clears_prior_occurrences() {
1213        const E: Extension<Int32> = Extension::new(1, CARRIER);
1214        let mut c = Carrier::default();
1215        c.set_extension(&E, 5);
1216        c.set_extension(&E, 7);
1217        // Exactly one record after second set.
1218        assert_eq!(c.unknown.iter().filter(|f| f.number == 1).count(), 1);
1219        assert_eq!(c.extension(&E), Some(7));
1220    }
1221
1222    #[test]
1223    fn set_preserves_other_fields() {
1224        const E: Extension<Int32> = Extension::new(1, CARRIER);
1225        let mut c = Carrier::default();
1226        c.unknown.push(varint(2, 99));
1227        c.set_extension(&E, 5);
1228        assert_eq!(c.unknown.len(), 2);
1229        // Field 2 survived.
1230        assert!(c.unknown.iter().any(|f| f.number == 2));
1231    }
1232
1233    #[test]
1234    fn clear_extension() {
1235        const E: Extension<Int32> = Extension::new(1, CARRIER);
1236        let mut c = Carrier::default();
1237        c.set_extension(&E, 5);
1238        c.unknown.push(varint(2, 99));
1239        c.clear_extension(&E);
1240        assert!(!c.has_extension(&E));
1241        assert_eq!(c.unknown.len(), 1); // field 2 survived
1242    }
1243
1244    // ── String / Bytes ──────────────────────────────────────────────────────
1245
1246    #[test]
1247    fn string_roundtrip() {
1248        const E: Extension<StringCodec> = Extension::new(1, CARRIER);
1249        let mut c = Carrier::default();
1250        c.set_extension(&E, "hello".to_string());
1251        assert_eq!(c.extension(&E), Some("hello".to_string()));
1252    }
1253
1254    #[test]
1255    fn string_invalid_utf8_is_none() {
1256        const E: Extension<StringCodec> = Extension::new(1, CARRIER);
1257        let mut c = Carrier::default();
1258        c.unknown.push(ld(1, vec![0xFF, 0xFE]));
1259        assert_eq!(c.extension(&E), None);
1260    }
1261
1262    #[test]
1263    fn bytes_roundtrip() {
1264        const E: Extension<BytesCodec> = Extension::new(1, CARRIER);
1265        let mut c = Carrier::default();
1266        c.set_extension(&E, vec![0xDE, 0xAD, 0xBE, 0xEF]);
1267        assert_eq!(c.extension(&E), Some(vec![0xDE, 0xAD, 0xBE, 0xEF]));
1268    }
1269
1270    // ── Repeated scalar ─────────────────────────────────────────────────────
1271
1272    #[test]
1273    fn repeated_scalar_unpacked() {
1274        const E: Extension<Repeated<Int32>> = Extension::new(1, CARRIER);
1275        let mut c = Carrier::default();
1276        c.unknown.push(varint(1, 1));
1277        c.unknown.push(varint(1, 2));
1278        c.unknown.push(varint(1, 3));
1279        assert_eq!(c.extension(&E), vec![1, 2, 3]);
1280    }
1281
1282    #[test]
1283    fn repeated_scalar_packed() {
1284        // Packed varint payload for [1, 2, 300]: 0x01 0x02 0xAC 0x02
1285        const E: Extension<Repeated<Int32>> = Extension::new(1, CARRIER);
1286        let mut c = Carrier::default();
1287        c.unknown.push(ld(1, vec![0x01, 0x02, 0xAC, 0x02]));
1288        assert_eq!(c.extension(&E), vec![1, 2, 300]);
1289    }
1290
1291    #[test]
1292    fn repeated_scalar_mixed_packed_unpacked() {
1293        const E: Extension<Repeated<Int32>> = Extension::new(1, CARRIER);
1294        let mut c = Carrier::default();
1295        c.unknown.push(varint(1, 1));
1296        c.unknown.push(ld(1, vec![0x02, 0x03])); // packed [2, 3]
1297        c.unknown.push(varint(1, 4));
1298        assert_eq!(c.extension(&E), vec![1, 2, 3, 4]);
1299    }
1300
1301    #[test]
1302    fn repeated_scalar_fixed32_packed() {
1303        // Packed fixed32 payload for [1, 2]: 01 00 00 00 02 00 00 00
1304        const E: Extension<Repeated<Fixed32>> = Extension::new(1, CARRIER);
1305        let mut c = Carrier::default();
1306        c.unknown.push(ld(1, vec![1, 0, 0, 0, 2, 0, 0, 0]));
1307        assert_eq!(c.extension(&E), vec![1_u32, 2_u32]);
1308    }
1309
1310    #[test]
1311    fn repeated_scalar_wrong_wire_type_skipped() {
1312        const E: Extension<Repeated<Int32>> = Extension::new(1, CARRIER);
1313        let mut c = Carrier::default();
1314        c.unknown.push(varint(1, 1));
1315        c.unknown.push(fixed32(1, 0xDEAD)); // wrong, skipped
1316        c.unknown.push(varint(1, 2));
1317        assert_eq!(c.extension(&E), vec![1, 2]);
1318    }
1319
1320    #[test]
1321    fn repeated_scalar_set_roundtrip() {
1322        const E: Extension<Repeated<Sint32>> = Extension::new(1, CARRIER);
1323        let mut c = Carrier::default();
1324        c.set_extension(&E, vec![-1, 0, 1, -100]);
1325        assert_eq!(c.extension(&E), vec![-1, 0, 1, -100]);
1326        // One record per element.
1327        assert_eq!(c.unknown.len(), 4);
1328    }
1329
1330    #[test]
1331    fn repeated_string() {
1332        const E: Extension<Repeated<StringCodec>> = Extension::new(1, CARRIER);
1333        let mut c = Carrier::default();
1334        c.set_extension(&E, vec!["a".to_string(), "b".to_string()]);
1335        assert_eq!(c.extension(&E), vec!["a".to_string(), "b".to_string()]);
1336    }
1337
1338    #[test]
1339    fn repeated_string_malformed_element_skipped() {
1340        const E: Extension<Repeated<StringCodec>> = Extension::new(1, CARRIER);
1341        let mut c = Carrier::default();
1342        c.unknown.push(ld(1, b"ok".to_vec()));
1343        c.unknown.push(ld(1, vec![0xFF])); // invalid UTF-8, skipped
1344        c.unknown.push(ld(1, b"also ok".to_vec()));
1345        // StringCodec::decode_packed is a no-op, so the malformed element
1346        // contributes nothing.
1347        assert_eq!(
1348            c.extension(&E),
1349            vec!["ok".to_string(), "also ok".to_string()]
1350        );
1351    }
1352
1353    #[test]
1354    fn repeated_empty_set_not_present() {
1355        const E: Extension<Repeated<Int32>> = Extension::new(1, CARRIER);
1356        let mut c = Carrier::default();
1357        c.set_extension(&E, vec![]);
1358        assert!(!c.has_extension(&E));
1359        assert_eq!(c.extension(&E), Vec::<i32>::new());
1360    }
1361
1362    #[test]
1363    fn packed_repeated_set_twice_one_record() {
1364        const E: Extension<PackedRepeated<Int32>> = Extension::new(1, CARRIER);
1365        let mut c = Carrier::default();
1366        c.set_extension(&E, vec![1, 2]);
1367        c.set_extension(&E, vec![3, 4, 5]);
1368        assert_eq!(c.unknown.len(), 1);
1369        assert_eq!(c.extension(&E), vec![3, 4, 5]);
1370    }
1371
1372    // ── PackedRepeated ──────────────────────────────────────────────────────
1373
1374    #[test]
1375    fn packed_repeated_encode_one_record() {
1376        const E: Extension<PackedRepeated<Int32>> = Extension::new(1, CARRIER);
1377        let mut c = Carrier::default();
1378        c.set_extension(&E, vec![1, 2, 300]);
1379        // Exactly one record.
1380        assert_eq!(c.unknown.len(), 1);
1381        assert_eq!(
1382            c.unknown.iter().next().unwrap().data,
1383            UnknownFieldData::LengthDelimited(vec![0x01, 0x02, 0xAC, 0x02])
1384        );
1385        // And it roundtrips.
1386        assert_eq!(c.extension(&E), vec![1, 2, 300]);
1387    }
1388
1389    #[test]
1390    fn packed_repeated_decode_accepts_unpacked() {
1391        // PackedRepeated decode is identical to Repeated decode — accepts both.
1392        const E: Extension<PackedRepeated<Int32>> = Extension::new(1, CARRIER);
1393        let mut c = Carrier::default();
1394        c.unknown.push(varint(1, 1));
1395        c.unknown.push(varint(1, 2));
1396        assert_eq!(c.extension(&E), vec![1, 2]);
1397    }
1398
1399    #[test]
1400    fn packed_repeated_empty_not_present() {
1401        const E: Extension<PackedRepeated<Int32>> = Extension::new(1, CARRIER);
1402        let mut c = Carrier::default();
1403        c.set_extension(&E, vec![]);
1404        assert!(!c.has_extension(&E));
1405    }
1406
1407    #[test]
1408    fn packed_repeated_fixed64_roundtrip() {
1409        const E: Extension<PackedRepeated<Sfixed64>> = Extension::new(1, CARRIER);
1410        let mut c = Carrier::default();
1411        c.set_extension(&E, vec![-1_i64, 0, i64::MAX]);
1412        assert_eq!(c.unknown.len(), 1);
1413        assert_eq!(c.extension(&E), vec![-1_i64, 0, i64::MAX]);
1414    }
1415
1416    // ── MessageCodec ────────────────────────────────────────────────────────
1417
1418    // Minimal test message: two i32 fields (numbers 1 and 2) + unknown preservation.
1419    // Hand-written to avoid a codegen dependency in the runtime crate's tests.
1420    #[derive(Clone, Default, PartialEq, Debug)]
1421    struct TestMsg {
1422        a: i32,
1423        b: i32,
1424        unknown: UnknownFields,
1425    }
1426
1427    impl crate::DefaultInstance for TestMsg {
1428        fn default_instance() -> &'static Self {
1429            static INST: crate::__private::OnceBox<TestMsg> = crate::__private::OnceBox::new();
1430            INST.get_or_init(|| alloc::boxed::Box::new(TestMsg::default()))
1431        }
1432    }
1433
1434    impl crate::Message for TestMsg {
1435        fn compute_size(&self, _cache: &mut crate::SizeCache) -> u32 {
1436            let mut n = 0;
1437            if self.a != 0 {
1438                n += 1 + crate::encoding::varint_len(self.a as i64 as u64);
1439            }
1440            if self.b != 0 {
1441                n += 1 + crate::encoding::varint_len(self.b as i64 as u64);
1442            }
1443            n += self.unknown.encoded_len();
1444            n as u32
1445        }
1446        fn write_to(&self, _cache: &mut crate::SizeCache, buf: &mut impl bytes::BufMut) {
1447            use crate::encoding::encode_varint;
1448            if self.a != 0 {
1449                encode_varint(1 << 3, buf);
1450                encode_varint(self.a as i64 as u64, buf);
1451            }
1452            if self.b != 0 {
1453                encode_varint(2 << 3, buf);
1454                encode_varint(self.b as i64 as u64, buf);
1455            }
1456            self.unknown.write_to(buf);
1457        }
1458        fn merge_field(
1459            &mut self,
1460            tag: crate::encoding::Tag,
1461            buf: &mut impl bytes::Buf,
1462            _depth: u32,
1463        ) -> Result<(), crate::DecodeError> {
1464            match tag.field_number() {
1465                1 => self.a = crate::types::decode_int32(buf)?,
1466                2 => self.b = crate::types::decode_int32(buf)?,
1467                _ => crate::encoding::skip_field(tag, buf)?,
1468            }
1469            Ok(())
1470        }
1471        fn clear(&mut self) {
1472            *self = Self::default();
1473        }
1474    }
1475
1476    #[test]
1477    fn message_single_record() {
1478        const E: Extension<MessageCodec<TestMsg>> = Extension::new(1, CARRIER);
1479        let mut c = Carrier::default();
1480        // Wire for TestMsg{a:5, b:0}: tag(1,varint)=0x08, value=0x05.
1481        c.unknown.push(ld(1, vec![0x08, 0x05]));
1482        let got = c.extension(&E).expect("decoded");
1483        assert_eq!(got.a, 5);
1484        assert_eq!(got.b, 0);
1485    }
1486
1487    #[test]
1488    fn message_split_records_merge() {
1489        // Proto spec: multiple records at the same field number merge.
1490        // Record 1 sets a=5, record 2 sets b=7 — result has both.
1491        const E: Extension<MessageCodec<TestMsg>> = Extension::new(1, CARRIER);
1492        let mut c = Carrier::default();
1493        c.unknown.push(ld(1, vec![0x08, 0x05])); // a=5
1494        c.unknown.push(ld(1, vec![0x10, 0x07])); // b=7
1495        let got = c.extension(&E).expect("decoded");
1496        assert_eq!(got.a, 5);
1497        assert_eq!(got.b, 7);
1498    }
1499
1500    #[test]
1501    fn message_absent_is_none() {
1502        const E: Extension<MessageCodec<TestMsg>> = Extension::new(1, CARRIER);
1503        let c = Carrier::default();
1504        assert!(c.extension(&E).is_none());
1505    }
1506
1507    #[test]
1508    fn message_malformed_is_none() {
1509        const E: Extension<MessageCodec<TestMsg>> = Extension::new(1, CARRIER);
1510        let mut c = Carrier::default();
1511        // Truncated varint: high bit set, no continuation.
1512        c.unknown.push(ld(1, vec![0x08, 0x80]));
1513        assert!(c.extension(&E).is_none());
1514    }
1515
1516    #[test]
1517    fn message_set_get_roundtrip() {
1518        const E: Extension<MessageCodec<TestMsg>> = Extension::new(1, CARRIER);
1519        let mut c = Carrier::default();
1520        c.set_extension(
1521            &E,
1522            TestMsg {
1523                a: 3,
1524                b: -1,
1525                unknown: UnknownFields::new(),
1526            },
1527        );
1528        let got = c.extension(&E).expect("decoded");
1529        assert_eq!(got.a, 3);
1530        assert_eq!(got.b, -1);
1531    }
1532
1533    #[test]
1534    fn message_unknown_fields_survive_roundtrip() {
1535        // The extension message's *own* unknown fields survive get→set→get.
1536        const E: Extension<MessageCodec<TestMsg>> = Extension::new(1, CARRIER);
1537        let mut c = Carrier::default();
1538        // Wire for TestMsg with a=5 AND an unknown field 99 (tag=99<<3|0=0x318, varint 42).
1539        // 0x318 = 792 → varint: 0x98 0x06. Value 42 → 0x2A.
1540        c.unknown.push(ld(1, vec![0x08, 0x05, 0x98, 0x06, 0x2A]));
1541        let got = c.extension(&E).expect("decoded");
1542        assert_eq!(got.a, 5);
1543        // The unknown field was preserved inside TestMsg — actually wait,
1544        // our TestMsg::merge_field skips unknowns rather than storing them.
1545        // Redo this test with set→get instead.
1546        let mut inner_unk = UnknownFields::new();
1547        inner_unk.push(varint(99, 42));
1548        let msg = TestMsg {
1549            a: 5,
1550            b: 0,
1551            unknown: inner_unk,
1552        };
1553        let mut c = Carrier::default();
1554        c.set_extension(&E, msg);
1555        // Re-encode to bytes and decode — the unknown bytes are in the payload.
1556        use crate::Message;
1557        let mut roundtrip = TestMsg::default();
1558        if let UnknownFieldData::LengthDelimited(bytes) = &c.unknown.iter().next().unwrap().data {
1559            // Our TestMsg doesn't actually preserve unknowns on decode, so
1560            // verify the *wire* contains them instead.
1561            assert!(bytes.len() > 2, "payload includes unknown-field bytes");
1562            // Find the tag for field 99 in the encoded bytes.
1563            assert!(bytes.windows(3).any(|w| w == [0x98, 0x06, 0x2A]));
1564            // And decode of field 1 still works.
1565            roundtrip.merge_from_slice(bytes).unwrap();
1566            assert_eq!(roundtrip.a, 5);
1567        } else {
1568            panic!("expected LengthDelimited");
1569        }
1570    }
1571
1572    #[test]
1573    fn repeated_message() {
1574        const E: Extension<Repeated<MessageCodec<TestMsg>>> = Extension::new(1, CARRIER);
1575        let mut c = Carrier::default();
1576        c.unknown.push(ld(1, vec![0x08, 0x01])); // a=1
1577        c.unknown.push(ld(1, vec![0x08, 0x02])); // a=2
1578        let got = c.extension(&E);
1579        assert_eq!(got.len(), 2);
1580        assert_eq!(got[0].a, 1);
1581        assert_eq!(got[1].a, 2);
1582    }
1583
1584    #[test]
1585    fn repeated_message_malformed_element_skipped() {
1586        const E: Extension<Repeated<MessageCodec<TestMsg>>> = Extension::new(1, CARRIER);
1587        let mut c = Carrier::default();
1588        c.unknown.push(ld(1, vec![0x08, 0x01])); // a=1, ok
1589        c.unknown.push(ld(1, vec![0x08, 0x80])); // truncated, skipped
1590        c.unknown.push(ld(1, vec![0x08, 0x03])); // a=3, ok
1591        let got = c.extension(&E);
1592        assert_eq!(got.len(), 2);
1593        assert_eq!(got[0].a, 1);
1594        assert_eq!(got[1].a, 3);
1595    }
1596
1597    // ── GroupCodec ──────────────────────────────────────────────────────────
1598
1599    // Group-encoded message extensions (proto2 `group` syntax, editions
1600    // DELIMITED). Wire data is UnknownFieldData::Group(inner) instead of
1601    // LengthDelimited(bytes); inner is an already-parsed UnknownFields tree.
1602
1603    /// Build an `UnknownFields` containing field-1-varint-v — matches
1604    /// `TestMsg{a: v as i32}` when re-serialized and merged.
1605    fn inner_a(v: u64) -> UnknownFields {
1606        let mut inner = UnknownFields::new();
1607        inner.push(varint(1, v));
1608        inner
1609    }
1610
1611    #[test]
1612    fn group_single_record() {
1613        const E: Extension<GroupCodec<TestMsg>> = Extension::new(1, CARRIER);
1614        let mut c = Carrier::default();
1615        c.unknown.push(group(1, inner_a(5)));
1616        let got = c.extension(&E).expect("decoded");
1617        assert_eq!(got.a, 5);
1618        assert_eq!(got.b, 0);
1619    }
1620
1621    #[test]
1622    fn group_split_records_merge() {
1623        // Proto spec: multiple records at the same field number merge.
1624        // Record 1 sets a=5, record 2 sets b=7 — result has both.
1625        const E: Extension<GroupCodec<TestMsg>> = Extension::new(1, CARRIER);
1626        let mut c = Carrier::default();
1627        c.unknown.push(group(1, inner_a(5)));
1628        let mut inner_b = UnknownFields::new();
1629        inner_b.push(varint(2, 7));
1630        c.unknown.push(group(1, inner_b));
1631        let got = c.extension(&E).expect("decoded");
1632        assert_eq!(got.a, 5);
1633        assert_eq!(got.b, 7);
1634    }
1635
1636    #[test]
1637    fn group_absent_is_none() {
1638        const E: Extension<GroupCodec<TestMsg>> = Extension::new(1, CARRIER);
1639        let c = Carrier::default();
1640        assert!(c.extension(&E).is_none());
1641    }
1642
1643    #[test]
1644    fn group_wrong_wire_type_is_none() {
1645        // A LengthDelimited record at the same number does NOT match GroupCodec
1646        // — decode skips it (would merge if MessageCodec were used).
1647        const E: Extension<GroupCodec<TestMsg>> = Extension::new(1, CARRIER);
1648        let mut c = Carrier::default();
1649        c.unknown.push(ld(1, vec![0x08, 0x05]));
1650        assert!(c.extension(&E).is_none());
1651    }
1652
1653    #[test]
1654    fn group_set_get_roundtrip() {
1655        const E: Extension<GroupCodec<TestMsg>> = Extension::new(1, CARRIER);
1656        let mut c = Carrier::default();
1657        c.set_extension(
1658            &E,
1659            TestMsg {
1660                a: 3,
1661                b: -1,
1662                unknown: UnknownFields::new(),
1663            },
1664        );
1665        // Verify the encoded data is a Group variant.
1666        match &c.unknown.iter().next().unwrap().data {
1667            UnknownFieldData::Group(_) => {}
1668            other => panic!("expected Group, got {other:?}"),
1669        }
1670        let got = c.extension(&E).expect("decoded");
1671        assert_eq!(got.a, 3);
1672        assert_eq!(got.b, -1);
1673    }
1674
1675    #[test]
1676    fn group_set_empty_message() {
1677        // An empty message encodes to zero bytes → empty Group inner.
1678        // Still counts as present (explicit-presence semantics).
1679        const E: Extension<GroupCodec<TestMsg>> = Extension::new(1, CARRIER);
1680        let mut c = Carrier::default();
1681        c.set_extension(&E, TestMsg::default());
1682        assert!(c.has_extension(&E));
1683        let got = c.extension(&E).expect("decoded");
1684        assert_eq!(got, TestMsg::default());
1685    }
1686
1687    #[test]
1688    fn repeated_group() {
1689        const E: Extension<Repeated<GroupCodec<TestMsg>>> = Extension::new(1, CARRIER);
1690        let mut c = Carrier::default();
1691        c.unknown.push(group(1, inner_a(1)));
1692        c.unknown.push(group(1, inner_a(2)));
1693        let got = c.extension(&E);
1694        assert_eq!(got.len(), 2);
1695        assert_eq!(got[0].a, 1);
1696        assert_eq!(got[1].a, 2);
1697    }
1698
1699    #[test]
1700    fn repeated_group_set_get_roundtrip() {
1701        const E: Extension<Repeated<GroupCodec<TestMsg>>> = Extension::new(1, CARRIER);
1702        let mut c = Carrier::default();
1703        let msgs = vec![
1704            TestMsg {
1705                a: 10,
1706                b: 0,
1707                unknown: UnknownFields::new(),
1708            },
1709            TestMsg {
1710                a: 0,
1711                b: 20,
1712                unknown: UnknownFields::new(),
1713            },
1714        ];
1715        c.set_extension(&E, msgs.clone());
1716        // Two separate Group records.
1717        assert_eq!(c.unknown.len(), 2);
1718        for f in c.unknown.iter() {
1719            assert!(matches!(f.data, UnknownFieldData::Group(_)));
1720        }
1721        assert_eq!(c.extension(&E), msgs);
1722    }
1723
1724    // ── All remaining scalar types get a spot-check roundtrip ───────────────
1725
1726    #[test]
1727    fn scalar_roundtrip_table() {
1728        macro_rules! rt {
1729            ($codec:ty, $v:expr) => {{
1730                const E: Extension<$codec> = Extension::new(1, CARRIER);
1731                let mut c = Carrier::default();
1732                c.set_extension(&E, $v);
1733                assert_eq!(c.extension(&E), Some($v), stringify!($codec));
1734            }};
1735        }
1736        rt!(Int64, -1_i64);
1737        rt!(Uint64, u64::MAX);
1738        rt!(Sint64, i64::MIN);
1739        rt!(Fixed32, u32::MAX);
1740        rt!(Fixed64, u64::MAX);
1741        rt!(Sfixed64, -1_i64);
1742        rt!(EnumI32, 42);
1743    }
1744
1745    #[test]
1746    fn fixed64_packed_decode_partial_tail_ignored() {
1747        // 8 bytes = one value; 3 trailing bytes are ignored (not enough for a second).
1748        const E: Extension<Repeated<Fixed64>> = Extension::new(1, CARRIER);
1749        let mut c = Carrier::default();
1750        let mut payload = 42_u64.to_le_bytes().to_vec();
1751        payload.extend_from_slice(&[0x01, 0x02, 0x03]);
1752        c.unknown.push(ld(1, payload));
1753        assert_eq!(c.extension(&E), vec![42_u64]);
1754    }
1755
1756    #[test]
1757    fn varint_packed_decode_malformed_tail_stops() {
1758        // Good varint 1, then truncated varint (high bit, no continuation).
1759        const E: Extension<Repeated<Int32>> = Extension::new(1, CARRIER);
1760        let mut c = Carrier::default();
1761        c.unknown.push(ld(1, vec![0x01, 0x80]));
1762        assert_eq!(c.extension(&E), vec![1]);
1763    }
1764
1765    // Verify unused helper silenced by one use here.
1766    #[test]
1767    fn fixed64_wrong_wire_type() {
1768        const E: Extension<Fixed64> = Extension::new(1, CARRIER);
1769        let mut c = Carrier::default();
1770        c.unknown.push(fixed64(1, 0xDEADBEEF));
1771        assert_eq!(c.extension(&E), Some(0xDEADBEEF_u64));
1772        let mut c = Carrier::default();
1773        c.unknown.push(fixed32(1, 0)); // wrong wire type
1774        assert_eq!(c.extension(&E), None);
1775    }
1776}