Skip to main content

bilrost/encoding/
unpacked.rs

1use crate::buf::ReverseBuf;
2use crate::encoding::value_traits::{
3    Collection, DistinguishedCollection, EmptyState, ForOverwrite,
4};
5use crate::encoding::{
6    check_wire_type, decoding_modes, encoding_uses_base_empty_state, peek_repeated_field,
7    BorrowDecoder, Capped, DecodeContext, Decoder, DistinguishedBorrowDecoder,
8    DistinguishedDecoder, DistinguishedValueBorrowDecoder, DistinguishedValueDecoder, Encoder,
9    FieldEncoder, GeneralPacked, Packed, RestrictedDecodeContext, TagMeasurer, TagRevWriter,
10    TagWriter, ValueBorrowDecoder, ValueDecoder, ValueEncoder, WireType, Wiretyped,
11};
12use crate::DecodeErrorKind::InvalidValue;
13use crate::{Canonicity, DecodeError};
14use bytes::BufMut;
15
16pub struct Unpacked<E = GeneralPacked>(E);
17
18encoding_uses_base_empty_state!(Unpacked<E>, with generics (E));
19
20macro_rules! define_decoders {
21    (
22        mode: $mode:ident,
23        relaxed: $relaxed:ident::$relaxed_method:ident,
24        relaxed_value: $relaxed_value:ident::$relaxed_value_method:ident,
25        relaxed_field: $relaxed_field:ident::$relaxed_field_method:ident,
26        distinguished: $distinguished:ident::$distinguished_method:ident,
27        distinguished_value: $distinguished_value:ident::$distinguished_value_method:ident,
28        distinguished_field: $distinguished_field:ident::$distinguished_field_method:ident,
29        buf_ty: $buf_ty:ty,
30        impl_buf_ty: $impl_buf_ty:ty,
31        $(buf_generic: ($($buf_generic:tt)*),)?
32        $(lifetime: $lifetime:lifetime,)?
33    ) => {
34        /// Decodes a collection value from the unpacked representation. This greedily consumes
35        /// consecutive fields as long as they have the same tag.
36        #[inline]
37        pub(crate) fn decode<$($lifetime,)? T, E>(
38            wire_type: WireType,
39            collection: &mut T,
40            mut buf: Capped<$impl_buf_ty>,
41            ctx: DecodeContext,
42        ) -> Result<(), DecodeError>
43        where
44            T: Collection,
45            (): EmptyState<(), T>
46                + ForOverwrite<E, T::Item>
47                + $relaxed_value <$($lifetime,)? E, T::Item>,
48        {
49            check_wire_type(<() as Wiretyped<E, T::Item>>::WIRE_TYPE, wire_type)?;
50            loop {
51                // Decode one item
52                let mut new_item = <() as ForOverwrite<E, T::Item>>::for_overwrite();
53                <() as $relaxed_value<E, _>>::$relaxed_value_method(&mut new_item, buf.lend(), ctx.clone())?;
54                collection.insert(new_item)?;
55
56                if let Some(next_wire_type) = peek_repeated_field(&mut buf) {
57                    check_wire_type(<() as Wiretyped<E, T::Item>>::WIRE_TYPE, next_wire_type)?;
58                } else {
59                    break;
60                }
61            }
62            Ok(())
63        }
64
65        /// Decodes an array value from either unpacked or packed representation. If there are not
66        /// exactly the expected number of fields the value is considered to be invalid.
67        #[inline]
68        pub(super) fn decode_array_either_repr<$($lifetime,)? T, const N: usize, E>(
69            wire_type: WireType,
70            arr: &mut [T; N],
71            buf: Capped<$impl_buf_ty>,
72            ctx: DecodeContext,
73        ) -> Result<(), DecodeError>
74        where
75            (): $relaxed_value <$($lifetime,)? E, T>,
76        {
77            if wire_type == WireType::LengthDelimited
78                && <() as Wiretyped<E, T>>::WIRE_TYPE != WireType::LengthDelimited
79            {
80                // We've encountered a length-delimited field when we aren't expecting one; try
81                // decoding it in packed format instead.
82                <() as $relaxed_value<Packed<E>, _>>::$relaxed_value_method(arr, buf, ctx)
83            } else {
84                // Otherwise, decode in unpacked mode.
85                decode_array_unpacked_only(wire_type, arr, buf, ctx)
86            }
87        }
88
89        /// Decodes an array value in only the unpacked representation. If there are not exactly the
90        /// expected number of fields the value is considered to be invalid.
91        #[inline]
92        pub(crate) fn decode_array_unpacked_only<$($lifetime,)? T, const N: usize, E>(
93            wire_type: WireType,
94            arr: &mut [T; N],
95            mut buf: Capped<$impl_buf_ty>,
96            ctx: DecodeContext,
97        ) -> Result<(), DecodeError>
98        where
99            (): $relaxed_value <$($lifetime,)? E, T>,
100        {
101            check_wire_type(<() as Wiretyped<E, T>>::WIRE_TYPE, wire_type)?;
102            for (i, dest) in arr.iter_mut().enumerate() {
103                // The initial field key is consumed, but we must read the repeated field key for
104                // each one after that.
105                if i > 0 {
106                    if let Some(next_wire_type) = peek_repeated_field(&mut buf) {
107                        check_wire_type(<() as Wiretyped<E, T>>::WIRE_TYPE, next_wire_type)?;
108                    } else {
109                        // Not enough value fields
110                        return Err(DecodeError::new(InvalidValue));
111                    }
112                }
113                // Decode one item
114                <() as $relaxed_value<E, _>>::$relaxed_value_method(dest, buf.lend(), ctx.clone())?;
115            }
116            if peek_repeated_field(&mut buf).is_some() {
117                // Too many value fields
118                Err(DecodeError::new(InvalidValue))
119            } else {
120                Ok(())
121            }
122        }
123
124        /// Decodes a collection value from the unpacked representation in distinguished mode. This
125        /// greedily consumes consecutive fields as long as they have the same tag.
126        #[inline]
127        pub(crate) fn decode_distinguished<$($lifetime,)? T, E>(
128            wire_type: WireType,
129            collection: &mut T,
130            mut buf: Capped<$impl_buf_ty>,
131            ctx: RestrictedDecodeContext,
132        ) -> Result<Canonicity, DecodeError>
133        where
134            T: DistinguishedCollection,
135            T::Item: Eq,
136            (): EmptyState<(), T>
137                + ForOverwrite<E, T::Item>
138                + $distinguished_value <$($lifetime,)? E, T::Item>,
139        {
140            check_wire_type(<() as Wiretyped<E, T::Item>>::WIRE_TYPE, wire_type)?;
141            let mut canon = Canonicity::Canonical;
142            loop {
143                // Decode one item
144                let mut new_item = <() as ForOverwrite<E, T::Item>>::for_overwrite();
145                // Decoded field values are nested within the collection; empty values are OK
146                canon.update(
147                    <() as $distinguished_value<E, _>>::$distinguished_value_method::<true>(
148                        &mut new_item,
149                        buf.lend(),
150                        ctx.clone(),
151                    )?,
152                );
153                canon.update(ctx.check(collection.insert_distinguished(new_item)?)?);
154
155                if let Some(next_wire_type) = peek_repeated_field(&mut buf) {
156                    check_wire_type(<() as Wiretyped<E, T::Item>>::WIRE_TYPE, next_wire_type)?;
157                } else {
158                    break;
159                }
160            }
161            Ok(canon)
162        }
163
164        /// Decodes an array value from either packed or unpacked in distinguished mode. If there
165        /// are not exactly the expected number of fields the value is considered to be invalid.
166        #[inline]
167        pub(super) fn decode_distinguished_array_either_repr<$($lifetime,)? T, const N: usize, E>(
168            wire_type: WireType,
169            arr: &mut [T; N],
170            buf: Capped<$impl_buf_ty>,
171            ctx: RestrictedDecodeContext,
172        ) -> Result<Canonicity, DecodeError>
173        where
174            T: Eq,
175            (): $relaxed_value <$($lifetime,)? E, T>
176                + $distinguished_value <$($lifetime,)? E, T>,
177        {
178            if wire_type == WireType::LengthDelimited
179                && <() as Wiretyped<E, T>>::WIRE_TYPE != WireType::LengthDelimited
180            {
181                // We've encountered a length-delimited field when we aren't expecting one; try
182                // decoding it in packed format instead.
183                // The data is already known to be non-canonical; use relaxed decoding
184                _ = ctx.check(Canonicity::NotCanonical)?;
185                <() as $relaxed_value<Packed<E>, _>>::$relaxed_value_method(
186                    arr, buf, ctx.into_inner(),
187                )?;
188                Ok(Canonicity::NotCanonical)
189            } else {
190                // Otherwise, decode in unpacked mode.
191                decode_distinguished_array_unpacked_only(wire_type, arr, buf, ctx)
192            }
193        }
194
195        /// Decodes an array value from the unpacked representation in distinguished mode. If there
196        /// are not exactly the expected number of fields the value is considered to be invalid.
197        #[inline]
198        fn decode_distinguished_array_unpacked_only<$($lifetime,)? T, const N: usize, E>(
199            wire_type: WireType,
200            arr: &mut [T; N],
201            mut buf: Capped<$impl_buf_ty>,
202            ctx: RestrictedDecodeContext,
203        ) -> Result<Canonicity, DecodeError>
204        where
205            T: Eq,
206            (): $distinguished_value <$($lifetime,)? E, T>,
207        {
208            check_wire_type(<() as Wiretyped<E, T>>::WIRE_TYPE, wire_type)?;
209            let mut canon = Canonicity::Canonical;
210            for (i, dest) in arr.iter_mut().enumerate() {
211                // The initial field key is consumed, but we must read the repeated field key for
212                // each one after that.
213                if i > 0 {
214                    if let Some(next_wire_type) = peek_repeated_field(&mut buf) {
215                        check_wire_type(<() as Wiretyped<E, T>>::WIRE_TYPE, next_wire_type)?;
216                    } else {
217                        // Not enough value fields
218                        return Err(DecodeError::new(InvalidValue));
219                    }
220                }
221                // Decode one item. Empty values are allowed
222                canon.update(
223                    <() as $distinguished_value<E, _>>::$distinguished_value_method::<true>(
224                        dest,
225                        buf.lend(),
226                        ctx.clone(),
227                    )?,
228                );
229            }
230            if peek_repeated_field(&mut buf).is_some() {
231                // Too many value fields
232                Err(DecodeError::new(InvalidValue))
233            } else {
234                Ok(canon)
235            }
236        }
237    };
238}
239
240pub(crate) mod owned {
241    use super::*;
242    decoding_modes::__invoke!(define_decoders, owned);
243}
244
245pub(crate) mod borrowed {
246    use super::*;
247    decoding_modes::__invoke!(define_decoders, borrowed);
248}
249
250/// Unpacked encodes vecs as repeated fields and in relaxed decoding mode will accept both packed
251/// and un-packed encodings.
252impl<C, T, E> Encoder<Unpacked<E>, C> for ()
253where
254    C: Collection<Item = T>,
255    (): EmptyState<(), C> + ForOverwrite<E, T> + ValueEncoder<E, T>,
256{
257    #[inline]
258    fn encode<B: BufMut + ?Sized>(tag: u32, value: &C, buf: &mut B, tw: &mut TagWriter) {
259        for val in value.iter() {
260            <() as FieldEncoder<E, T>>::encode_field(tag, val, buf, tw);
261        }
262    }
263
264    #[inline]
265    fn prepend_encode<B: ReverseBuf + ?Sized>(
266        tag: u32,
267        value: &C,
268        buf: &mut B,
269        tw: &mut TagRevWriter,
270    ) {
271        for val in value.reversed() {
272            <() as FieldEncoder<E, T>>::prepend_field(tag, val, buf, tw);
273        }
274    }
275
276    #[inline]
277    fn encoded_len(tag: u32, value: &C, tm: &mut impl TagMeasurer) -> usize {
278        if value.len() > 0 {
279            // Each *additional* field encoded after the first needs only 1 byte for the field key.
280            tm.key_len(tag)
281                + <() as ValueEncoder<E, _>>::many_values_encoded_len(value.iter())
282                + value.len()
283                - 1
284        } else {
285            0
286        }
287    }
288}
289
290/// Unpacked encodes arrays as repeated fields if any of the values are non-empty, and in relaxed
291/// decoding mode will accept both packed and un-packed encodings.
292impl<T, const N: usize, E> Encoder<Unpacked<E>, [T; N]> for ()
293where
294    (): ValueEncoder<E, T> + EmptyState<E, [T; N]>,
295{
296    #[inline]
297    fn encode<B: BufMut + ?Sized>(tag: u32, value: &[T; N], buf: &mut B, tw: &mut TagWriter) {
298        if !<() as EmptyState<E, _>>::is_empty(value) {
299            <() as Encoder<Unpacked<E>, [T]>>::encode(tag, value, buf, tw);
300        }
301    }
302
303    #[inline]
304    fn prepend_encode<B: ReverseBuf + ?Sized>(
305        tag: u32,
306        value: &[T; N],
307        buf: &mut B,
308        tw: &mut TagRevWriter,
309    ) {
310        if !<() as EmptyState<E, _>>::is_empty(value) {
311            <() as Encoder<Unpacked<E>, [T]>>::prepend_encode(tag, value, buf, tw);
312        }
313    }
314
315    #[inline]
316    fn encoded_len(tag: u32, value: &[T; N], tm: &mut impl TagMeasurer) -> usize {
317        if !<() as EmptyState<E, _>>::is_empty(value) {
318            <() as Encoder<Unpacked<E>, [T]>>::encoded_len(tag, value, tm)
319        } else {
320            0
321        }
322    }
323}
324
325/// Unpacked encodes slices the same way as arrays. This implementation always uses the natural
326/// emptiness and item iteration of the slice, since implementing `EmptyState` for the unsized `[T]`
327/// isn't practical.
328impl<T, E> Encoder<Unpacked<E>, [T]> for ()
329where
330    (): ValueEncoder<E, T>,
331{
332    #[inline]
333    fn encode<B: BufMut + ?Sized>(tag: u32, value: &[T], buf: &mut B, tw: &mut TagWriter) {
334        for val in value.iter() {
335            <() as FieldEncoder<E, T>>::encode_field(tag, val, buf, tw);
336        }
337    }
338
339    #[inline]
340    fn prepend_encode<B: ReverseBuf + ?Sized>(
341        tag: u32,
342        value: &[T],
343        buf: &mut B,
344        tw: &mut TagRevWriter,
345    ) {
346        for val in value.iter().rev() {
347            <() as FieldEncoder<E, T>>::prepend_field(tag, val, buf, tw);
348        }
349    }
350
351    #[inline]
352    fn encoded_len(tag: u32, value: &[T], tm: &mut impl TagMeasurer) -> usize {
353        if !value.is_empty() {
354            // Each *additional* field encoded after the first needs only 1 byte for the field key.
355            tm.key_len(tag)
356                + <() as ValueEncoder<E, T>>::many_values_encoded_len(value.iter())
357                + value.len()
358                - 1
359        } else {
360            0
361        }
362    }
363}
364
365/// Unpacked encodes arrays as repeated fields if any of the values are non-empty.
366impl<T, const N: usize, E> Encoder<Unpacked<E>, Option<[T; N]>> for ()
367where
368    (): ValueEncoder<E, T> + ForOverwrite<E, [T; N]>,
369{
370    #[inline]
371    fn encode<B: BufMut + ?Sized>(
372        tag: u32,
373        value: &Option<[T; N]>,
374        buf: &mut B,
375        tw: &mut TagWriter,
376    ) {
377        if let Some(values) = value.as_ref() {
378            for val in values {
379                <() as FieldEncoder<E, T>>::encode_field(tag, val, buf, tw);
380            }
381        }
382    }
383
384    #[inline]
385    fn prepend_encode<B: ReverseBuf + ?Sized>(
386        tag: u32,
387        value: &Option<[T; N]>,
388        buf: &mut B,
389        tw: &mut TagRevWriter,
390    ) {
391        if let Some(values) = value.as_ref() {
392            for val in values.iter().rev() {
393                <() as FieldEncoder<E, T>>::prepend_field(tag, val, buf, tw);
394            }
395        }
396    }
397
398    #[inline]
399    fn encoded_len(tag: u32, value: &Option<[T; N]>, tm: &mut impl TagMeasurer) -> usize {
400        if let Some(values) = value.as_ref() {
401            // Each *additional* field encoded after the first needs only 1 byte for the field key.
402            tm.key_len(tag) + <() as ValueEncoder<E, T>>::many_values_encoded_len(values.iter()) + N
403                - 1
404        } else {
405            0
406        }
407    }
408}
409
410macro_rules! impl_decoders {
411    (
412        mode: $mode:ident,
413        relaxed: $relaxed:ident::$relaxed_method:ident,
414        relaxed_value: $relaxed_value:ident::$relaxed_value_method:ident,
415        relaxed_field: $relaxed_field:ident::$relaxed_field_method:ident,
416        distinguished: $distinguished:ident::$distinguished_method:ident,
417        distinguished_value: $distinguished_value:ident::$distinguished_value_method:ident,
418        distinguished_field: $distinguished_field:ident::$distinguished_field_method:ident,
419        buf_ty: $buf_ty:ty,
420        impl_buf_ty: $impl_buf_ty:ty,
421        $(buf_generic: ($($buf_generic:tt)*),)?
422        $(lifetime: $lifetime:lifetime,)?
423    ) => {
424        impl<$($lifetime,)? C, T, E> $relaxed <$($lifetime,)? Unpacked<E>, C> for ()
425        where
426            C: Collection<Item = T>,
427            (): EmptyState<(), C> + ForOverwrite<E, T> + $relaxed_value <$($lifetime,)? E, T>,
428        {
429            #[inline]
430            fn $relaxed_method $($($buf_generic)*)? (
431                wire_type: WireType,
432                value: &mut C,
433                buf: Capped<$buf_ty>,
434                ctx: DecodeContext,
435            ) -> Result<(), DecodeError> {
436                if wire_type == WireType::LengthDelimited
437                    && <() as Wiretyped<E, C::Item>>::WIRE_TYPE != WireType::LengthDelimited
438                {
439                    // We've encountered a length-delimited field when we aren't expecting one; try decoding
440                    // it in packed format instead.
441                    <() as $relaxed_value<Packed<E>, _>>::$relaxed_value_method(value, buf, ctx)
442                } else {
443                    // Otherwise, decode in unpacked mode.
444                    $mode::decode::<C, E>(wire_type, value, buf, ctx)
445                }
446            }
447        }
448
449        /// Distinguished encoding enforces only the repeated field representation is allowed.
450        impl<$($lifetime,)? C, T, E> $distinguished <$($lifetime,)? Unpacked<E>, C> for ()
451        where
452            C: DistinguishedCollection<Item = T>,
453            T: Eq,
454            (): EmptyState<(), C>
455                + ForOverwrite<E, T>
456                + $distinguished_value <$($lifetime,)? E, T>
457                + $relaxed_value <$($lifetime,)? Packed<E>, C>
458                + $relaxed <$($lifetime,)? Unpacked<E>, C>,
459        {
460            #[inline]
461            fn $distinguished_method $($($buf_generic)*)? (
462                wire_type: WireType,
463                value: &mut C,
464                buf: Capped<$buf_ty>,
465                ctx: RestrictedDecodeContext,
466            ) -> Result<Canonicity, DecodeError> {
467                if wire_type == WireType::LengthDelimited
468                    && <() as Wiretyped<E, T>>::WIRE_TYPE != WireType::LengthDelimited
469                {
470                    // We've encountered a length-delimited field when we aren't expecting one; try decoding
471                    // it in packed format instead.
472                    // The data is already known to be non-canonical; use relaxed decoding
473                    _ = ctx.check(Canonicity::NotCanonical)?;
474                    <() as $relaxed_value<Packed<E>, _>>::$relaxed_value_method(
475                        value,
476                        buf,
477                        ctx.into_inner(),
478                    )?;
479                    Ok(Canonicity::NotCanonical)
480                } else {
481                    // Otherwise, decode in unpacked mode.
482                    $mode::decode_distinguished::<C, E>(wire_type, value, buf, ctx)
483                }
484            }
485        }
486
487        impl<$($lifetime,)? T, const N: usize, E>
488        $relaxed <$($lifetime,)? Unpacked<E>, [T; N]> for ()
489        where
490            (): $relaxed_value <$($lifetime,)? E, T> + EmptyState<E, [T; N]>,
491        {
492            #[inline]
493            fn $relaxed_method $($($buf_generic)*)? (
494                wire_type: WireType,
495                value: &mut [T; N],
496                buf: Capped<$buf_ty>,
497                ctx: DecodeContext,
498            ) -> Result<(), DecodeError> {
499                $mode::decode_array_either_repr(wire_type, value, buf, ctx)
500            }
501        }
502
503        /// Distinguished encoding considers only the repeated field representation to be canonical.
504        impl<$($lifetime,)? T, const N: usize, E>
505        $distinguished <$($lifetime,)? Unpacked<E>, [T; N]> for ()
506        where
507            T: Eq,
508            (): EmptyState<E, [T; N]>
509                + $distinguished_value <$($lifetime,)? E, T>
510                + $relaxed_value <$($lifetime,)? E, T>,
511        {
512            #[inline]
513            fn $distinguished_method $($($buf_generic)*)? (
514                wire_type: WireType,
515                value: &mut [T; N],
516                buf: Capped<$buf_ty>,
517                ctx: RestrictedDecodeContext,
518            ) -> Result<Canonicity, DecodeError> {
519                let canon = $mode::decode_distinguished_array_either_repr(
520                    wire_type,
521                    value,
522                    buf,
523                    ctx.clone(),
524                )?;
525                if <() as EmptyState::<E, _>>::is_empty(value) {
526                    ctx.check(Canonicity::NotCanonical)
527                } else {
528                    Ok(canon)
529                }
530            }
531        }
532
533        impl<$($lifetime,)? T, const N: usize, E>
534        $relaxed <$($lifetime,)? Unpacked<E>, Option<[T; N]>> for ()
535        where
536            (): $relaxed_value <$($lifetime,)? E, T> + ForOverwrite<E, [T; N]>,
537        {
538            #[inline]
539            fn $relaxed_method $($($buf_generic)*)? (
540                wire_type: WireType,
541                value: &mut Option<[T; N]>,
542                buf: Capped<$buf_ty>,
543                ctx: DecodeContext,
544            ) -> Result<(), DecodeError> {
545                $mode::decode_array_either_repr(
546                    wire_type,
547                    value.get_or_insert_with(<() as ForOverwrite::<E, _>>::for_overwrite),
548                    buf,
549                    ctx,
550                )
551            }
552        }
553
554        /// Distinguished encoding enforces only the repeated field representation is considered to be
555        /// canonical.
556        impl<$($lifetime,)? T, const N: usize, E>
557        $distinguished <$($lifetime,)? Unpacked<E>, Option<[T; N]>> for ()
558        where
559            T: Eq,
560            (): ForOverwrite<E, [T; N]>
561                + $distinguished_value<$($lifetime,)? E, T>
562                + $relaxed_value<$($lifetime,)? E, T>,
563        {
564            #[inline]
565            fn $distinguished_method $($($buf_generic)*)? (
566                wire_type: WireType,
567                value: &mut Option<[T; N]>,
568                buf: Capped<$buf_ty>,
569                ctx: RestrictedDecodeContext,
570            ) -> Result<Canonicity, DecodeError> {
571                $mode::decode_distinguished_array_either_repr(
572                    wire_type,
573                    value.get_or_insert_with(<() as ForOverwrite::<E, _>>::for_overwrite),
574                    buf,
575                    ctx,
576                )
577            }
578        }
579    };
580}
581
582decoding_modes::__invoke!(impl_decoders, owned);
583decoding_modes::__invoke!(impl_decoders, borrowed);
584
585#[cfg(test)]
586mod test {
587    use alloc::string::String;
588    use alloc::vec::Vec;
589
590    use proptest::proptest;
591
592    use crate::encoding::test::{distinguished, relaxed};
593    use crate::encoding::{Fixed, Unpacked, WireType};
594
595    proptest! {
596        #[test]
597        fn varint(value: Vec<u64>, tag: u32) {
598            relaxed::check_type_unpacked::<Vec<u64>, Unpacked>(
599                value.clone(),
600                tag,
601                WireType::Varint,
602            )?;
603            distinguished::check_type_unpacked::<Vec<u64>, Unpacked>(value, tag, WireType::Varint)?;
604        }
605
606        #[test]
607        fn length_delimited(value: Vec<String>, tag: u32) {
608            relaxed::check_type_unpacked::<Vec<String>, Unpacked>(
609                value.clone(),
610                tag,
611                WireType::LengthDelimited,
612            )?;
613            distinguished::check_type_unpacked::<Vec<String>, Unpacked>(
614                value,
615                tag,
616                WireType::LengthDelimited,
617            )?;
618        }
619
620        #[test]
621        fn fixed32(value: Vec<u32>, tag: u32) {
622            relaxed::check_type_unpacked::<Vec<u32>, Unpacked<Fixed>>(
623                value.clone(),
624                tag,
625                WireType::ThirtyTwoBit,
626            )?;
627            distinguished::check_type_unpacked::<Vec<u32>, Unpacked<Fixed>>(
628                value,
629                tag,
630                WireType::ThirtyTwoBit,
631            )?;
632        }
633
634        #[test]
635        fn fixed64(value: Vec<u64>, tag: u32) {
636            relaxed::check_type_unpacked::<Vec<u64>, Unpacked<Fixed>>(
637                value.clone(),
638                tag,
639                WireType::SixtyFourBit,
640            )?;
641            distinguished::check_type_unpacked::<Vec<u64>, Unpacked<Fixed>>(
642                value,
643                tag,
644                WireType::SixtyFourBit,
645            )?;
646        }
647
648        #[test]
649        fn varint_array(value: [u64; 2], tag: u32) {
650            relaxed::check_type_unpacked::<[u64; 2], Unpacked>(
651                value,
652                tag,
653                WireType::Varint,
654            )?;
655            distinguished::check_type_unpacked::<[u64; 2], Unpacked>(value, tag, WireType::Varint)?;
656        }
657
658        #[test]
659        fn length_delimited_array(value: [String; 2], tag: u32) {
660            relaxed::check_type_unpacked::<[String; 2], Unpacked>(
661                value.clone(),
662                tag,
663                WireType::LengthDelimited,
664            )?;
665            distinguished::check_type_unpacked::<[String; 2], Unpacked>(
666                value,
667                tag,
668                WireType::LengthDelimited,
669            )?;
670        }
671
672        #[test]
673        fn fixed32_array(value: [u32; 2], tag: u32) {
674            relaxed::check_type_unpacked::<[u32; 2], Unpacked<Fixed>>(
675                value,
676                tag,
677                WireType::ThirtyTwoBit,
678            )?;
679            distinguished::check_type_unpacked::<[u32; 2], Unpacked<Fixed>>(
680                value,
681                tag,
682                WireType::ThirtyTwoBit,
683            )?;
684        }
685
686        #[test]
687        fn fixed64_array(value: [u64; 2], tag: u32) {
688            relaxed::check_type_unpacked::<[u64; 2], Unpacked<Fixed>>(
689                value,
690                tag,
691                WireType::SixtyFourBit,
692            )?;
693            distinguished::check_type_unpacked::<[u64; 2], Unpacked<Fixed>>(
694                value,
695                tag,
696                WireType::SixtyFourBit,
697            )?;
698        }
699    }
700}