Skip to main content

bilrost/encoding/
packed.rs

1use crate::buf::ReverseBuf;
2use crate::encoding::value_traits::{
3    Collection, DistinguishedCollection, EmptyState, ForOverwrite,
4};
5use crate::encoding::{
6    decoding_modes, encode_varint, encoded_len_varint, encoding_uses_base_empty_state,
7    prepend_varint, unpacked, BorrowDecoder, Canonicity, Capped, DecodeContext, DecodeError,
8    Decoder, DistinguishedBorrowDecoder, DistinguishedDecoder, DistinguishedValueBorrowDecoder,
9    DistinguishedValueDecoder, Encoder, FieldEncoder, GeneralPacked, RestrictedDecodeContext,
10    TagMeasurer, TagRevWriter, TagWriter, ValueBorrowDecoder, ValueDecoder, ValueEncoder, WireType,
11    Wiretyped,
12};
13use crate::DecodeErrorKind::{InvalidValue, Truncated};
14use bytes::{Buf, BufMut};
15
16pub struct Packed<E = GeneralPacked>(E);
17
18encoding_uses_base_empty_state!(Packed<E>, with generics (E));
19
20/// Packed encodings always prefer to encode length delimited.
21impl<E, T: ?Sized> Wiretyped<Packed<E>, T> for () {
22    const WIRE_TYPE: WireType = WireType::LengthDelimited;
23}
24
25impl<C, T, E> ValueEncoder<Packed<E>, C> for ()
26where
27    C: Collection<Item = T>,
28    (): EmptyState<(), C> + ForOverwrite<E, T> + ValueEncoder<E, T>,
29{
30    #[inline]
31    fn encode_value<B: BufMut + ?Sized>(value: &C, buf: &mut B) {
32        encode_varint(
33            <() as ValueEncoder<E, _>>::many_values_encoded_len(value.iter()) as u64,
34            buf,
35        );
36        for val in value.iter() {
37            <() as ValueEncoder<E, _>>::encode_value(val, buf);
38        }
39    }
40
41    #[inline]
42    fn prepend_value<B: ReverseBuf + ?Sized>(value: &C, buf: &mut B) {
43        let end = buf.remaining();
44        for val in value.reversed() {
45            <() as ValueEncoder<E, _>>::prepend_value(val, buf);
46        }
47        prepend_varint((buf.remaining() - end) as u64, buf);
48    }
49
50    #[inline]
51    fn value_encoded_len(value: &C) -> usize {
52        let inner_len = <() as ValueEncoder<E, _>>::many_values_encoded_len(value.iter());
53        encoded_len_varint(inner_len as u64)
54            .checked_add(inner_len)
55            .unwrap()
56    }
57}
58
59/// ValueEncoder for packed repeated encodings lets this value type nest.
60impl<C, T, E> Encoder<Packed<E>, C> for ()
61where
62    C: Collection<Item = T>,
63    (): EmptyState<(), C> + ForOverwrite<E, T> + ValueEncoder<E, T> + ValueEncoder<Packed<E>, C>,
64{
65    #[inline]
66    fn encode<B: BufMut + ?Sized>(tag: u32, value: &C, buf: &mut B, tw: &mut TagWriter) {
67        if !<() as EmptyState<(), _>>::is_empty(value) {
68            Self::encode_field(tag, value, buf, tw);
69        }
70    }
71
72    #[inline]
73    fn prepend_encode<B: ReverseBuf + ?Sized>(
74        tag: u32,
75        value: &C,
76        buf: &mut B,
77        tw: &mut TagRevWriter,
78    ) {
79        if !<() as EmptyState<(), _>>::is_empty(value) {
80            Self::prepend_field(tag, value, buf, tw);
81        }
82    }
83
84    #[inline]
85    fn encoded_len(tag: u32, value: &C, tm: &mut impl TagMeasurer) -> usize {
86        if !<() as EmptyState<(), _>>::is_empty(value) {
87            Self::field_encoded_len(tag, value, tm)
88        } else {
89            0
90        }
91    }
92}
93
94impl<T, const N: usize, E> ValueEncoder<Packed<E>, [T; N]> for ()
95where
96    (): ValueEncoder<E, T>,
97{
98    #[inline]
99    fn encode_value<B: BufMut + ?Sized>(value: &[T; N], buf: &mut B) {
100        <() as ValueEncoder<Packed<E>, [T]>>::encode_value(value, buf)
101    }
102
103    #[inline]
104    fn prepend_value<B: ReverseBuf + ?Sized>(value: &[T; N], buf: &mut B) {
105        <() as ValueEncoder<Packed<E>, [T]>>::prepend_value(value, buf)
106    }
107
108    #[inline]
109    fn value_encoded_len(value: &[T; N]) -> usize {
110        <() as ValueEncoder<Packed<E>, [T]>>::value_encoded_len(value)
111    }
112}
113
114impl<T, const N: usize, E> Encoder<Packed<E>, [T; N]> for ()
115where
116    (): ValueEncoder<E, T> + EmptyState<E, [T; N]>,
117{
118    #[inline]
119    fn encode<B: BufMut + ?Sized>(tag: u32, value: &[T; N], buf: &mut B, tw: &mut TagWriter) {
120        if !<() as EmptyState<E, _>>::is_empty(value) {
121            <() as FieldEncoder<Packed<E>, [T]>>::encode_field(tag, value, buf, tw);
122        }
123    }
124
125    #[inline]
126    fn prepend_encode<B: ReverseBuf + ?Sized>(
127        tag: u32,
128        value: &[T; N],
129        buf: &mut B,
130        tw: &mut TagRevWriter,
131    ) {
132        if !<() as EmptyState<E, _>>::is_empty(value) {
133            <() as FieldEncoder<Packed<E>, [T]>>::prepend_field(tag, value, buf, tw);
134        }
135    }
136
137    #[inline]
138    fn encoded_len(tag: u32, value: &[T; N], tm: &mut impl TagMeasurer) -> usize {
139        if !<() as EmptyState<E, _>>::is_empty(value) {
140            <() as FieldEncoder<Packed<E>, [T]>>::field_encoded_len(tag, value, tm)
141        } else {
142            0
143        }
144    }
145}
146
147/// Packed encodes slices the same way as arrays. This implementation always uses the natural
148/// emptiness and item iteration of the slice, since implementing `EmptyState` for the unsized `[T]`
149/// isn't practical.
150impl<T, E> ValueEncoder<Packed<E>, [T]> for ()
151where
152    (): ValueEncoder<E, T>,
153{
154    #[inline]
155    fn encode_value<B: BufMut + ?Sized>(value: &[T], buf: &mut B) {
156        encode_varint(
157            <() as ValueEncoder<E, _>>::many_values_encoded_len(value.iter()) as u64,
158            buf,
159        );
160        for val in value.iter() {
161            <() as ValueEncoder<E, _>>::encode_value(val, buf);
162        }
163    }
164
165    #[inline]
166    fn prepend_value<B: ReverseBuf + ?Sized>(value: &[T], buf: &mut B) {
167        let end = buf.remaining();
168        for val in value.iter().rev() {
169            <() as ValueEncoder<E, _>>::prepend_value(val, buf);
170        }
171        prepend_varint((buf.remaining() - end) as u64, buf);
172    }
173
174    #[inline]
175    fn value_encoded_len(value: &[T]) -> usize {
176        let inner_len = <() as ValueEncoder<E, _>>::many_values_encoded_len(value.iter());
177        encoded_len_varint(inner_len as u64)
178            .checked_add(inner_len)
179            .unwrap()
180    }
181}
182
183impl<T, E> Encoder<Packed<E>, [T]> for ()
184where
185    (): ValueEncoder<E, T>,
186{
187    #[inline]
188    fn encode<B: BufMut + ?Sized>(tag: u32, value: &[T], buf: &mut B, tw: &mut TagWriter) {
189        if !value.is_empty() {
190            <() as FieldEncoder<Packed<E>, [T]>>::encode_field(tag, value, buf, tw);
191        }
192    }
193
194    #[inline]
195    fn prepend_encode<B: ReverseBuf + ?Sized>(
196        tag: u32,
197        value: &[T],
198        buf: &mut B,
199        tw: &mut TagRevWriter,
200    ) {
201        if !value.is_empty() {
202            <() as FieldEncoder<Packed<E>, [T]>>::prepend_field(tag, value, buf, tw);
203        }
204    }
205
206    #[inline]
207    fn encoded_len(tag: u32, value: &[T], tm: &mut impl TagMeasurer) -> usize {
208        if !value.is_empty() {
209            <() as FieldEncoder<Packed<E>, [T]>>::field_encoded_len(tag, value, tm)
210        } else {
211            0
212        }
213    }
214}
215
216macro_rules! impl_decoders {
217    (
218        mode: $mode:ident,
219        relaxed: $relaxed:ident::$relaxed_method:ident,
220        relaxed_value: $relaxed_value:ident::$relaxed_value_method:ident,
221        relaxed_field: $relaxed_field:ident::$relaxed_field_method:ident,
222        distinguished: $distinguished:ident::$distinguished_method:ident,
223        distinguished_value: $distinguished_value:ident::$distinguished_value_method:ident,
224        distinguished_field: $distinguished_field:ident::$distinguished_field_method:ident,
225        buf_ty: $buf_ty:ty,
226        impl_buf_ty: $impl_buf_ty:ty,
227        $(buf_generic: ($($buf_generic:tt)*),)?
228        $(lifetime: $lifetime:lifetime,)?
229    ) => {
230        impl<$($lifetime,)? C, T, E> $relaxed_value <$($lifetime,)? Packed<E>, C> for ()
231        where
232            C: Collection<Item = T>,
233            (): EmptyState<(), C>
234                + ForOverwrite<E, T>
235                + $relaxed_value<$($lifetime,)? E, T>,
236        {
237            #[inline]
238            fn $relaxed_value_method $($($buf_generic)*)? (
239                value: &mut C,
240                mut buf: Capped<$buf_ty>,
241                ctx: DecodeContext,
242            ) -> Result<(), DecodeError> {
243                let mut capped = buf.take_length_delimited()?;
244                // MSRV: this could be .is_some_and(..)
245                if matches!(
246                    <() as Wiretyped<E, T>>::WIRE_TYPE.fixed_size(),
247                    Some(fixed_size) if capped.remaining_before_cap() % fixed_size != 0
248                ) {
249                    // No number of fixed-sized values can pack evenly into this size.
250                    return Err(DecodeError::new(Truncated));
251                }
252                while capped.has_remaining()? {
253                    let mut new_val = <() as ForOverwrite<E, T>>::for_overwrite();
254                    <() as $relaxed_value<E, _>>::$relaxed_value_method(
255                        &mut new_val,
256                        capped.lend(),
257                        ctx.clone(),
258                    )?;
259                    value.insert(new_val)?;
260                }
261                Ok(())
262            }
263        }
264
265        impl<$($lifetime,)? C, T, E> $distinguished_value<$($lifetime,)? Packed<E>, C> for ()
266        where
267            C: DistinguishedCollection<Item = T> + Eq,
268            T: Eq,
269            (): EmptyState<(), C>
270                + ForOverwrite<E, T>
271                + $distinguished_value<$($lifetime,)? E, T>,
272        {
273            const CHECKS_EMPTY: bool = false;
274
275            #[inline]
276            fn $distinguished_value_method <const ALLOW_EMPTY: bool>(
277                value: &mut C,
278                mut buf: Capped<$impl_buf_ty>,
279                ctx: RestrictedDecodeContext,
280            ) -> Result<Canonicity, DecodeError> {
281                let mut capped = buf.take_length_delimited()?;
282                // MSRV: this could be .is_some_and(..)
283                if matches!(
284                    <() as Wiretyped<E, T>>::WIRE_TYPE.fixed_size(),
285                    Some(fixed_size) if capped.remaining_before_cap() % fixed_size != 0
286                ) {
287                    // No number of fixed-sized values can pack evenly into this size.
288                    return Err(DecodeError::new(Truncated));
289                }
290                let mut canon = Canonicity::Canonical;
291                while capped.has_remaining()? {
292                    let mut new_val = <() as ForOverwrite<E, T>>::for_overwrite();
293                    canon.update(
294                        <() as $distinguished_value<E, _>>::$distinguished_value_method::<true>(
295                            &mut new_val,
296                            capped.lend(),
297                            ctx.clone(),
298                        )?,
299                    );
300                    canon.update(ctx.check(value.insert_distinguished(new_val)?)?);
301                }
302                Ok(canon)
303            }
304        }
305
306        impl<$($lifetime,)? C, T, E> $relaxed <$($lifetime,)? Packed<E>, C> for ()
307        where
308            C: Collection<Item = T>,
309            (): EmptyState<(), C>
310                + ForOverwrite<E, T>
311                + $relaxed_value <$($lifetime,)? E, T>
312                + $relaxed_value <$($lifetime,)? Packed<E>, C>,
313        {
314            #[inline]
315            fn $relaxed_method $($($buf_generic)*)? (
316                wire_type: WireType,
317                value: &mut C,
318                buf: Capped<$buf_ty>,
319                ctx: DecodeContext,
320            ) -> Result<(), DecodeError> {
321                if wire_type == WireType::LengthDelimited {
322                    // We've encountered the expected length-delimited type: decode it in packed
323                    // format.
324                    <() as $relaxed_value<Packed<E>, C>>::$relaxed_value_method(value, buf, ctx)
325                } else {
326                    // Otherwise, try decoding it in the unpacked representation
327                    unpacked::$mode::decode::<C, E>(wire_type, value, buf, ctx)
328                }
329            }
330        }
331
332        impl<$($lifetime,)? C, T, E> $distinguished <$($lifetime,)? Packed<E>, C> for ()
333        where
334            C: DistinguishedCollection<Item = T>,
335            T: Eq,
336            (): EmptyState<(), C>
337                + ForOverwrite<E, T>
338                + $relaxed_value <$($lifetime,)? E, T>
339                + $distinguished_value <$($lifetime,)? Packed<E>, C>,
340        {
341            #[inline]
342            fn $distinguished_method $($($buf_generic)*)? (
343                wire_type: WireType,
344                value: &mut C,
345                buf: Capped<$buf_ty>,
346                ctx: RestrictedDecodeContext,
347            ) -> Result<Canonicity, DecodeError> {
348                if wire_type == WireType::LengthDelimited {
349                    // We've encountered the expected length-delimited type: decode it in packed
350                    // format. Set ALLOW_EMPTY to false: empty collections are not canonical
351                    let canon = <() as $distinguished_value<Packed<E>, _>>::
352                        $distinguished_value_method::<false>
353                    (
354                        value,
355                        buf,
356                        ctx.clone(),
357                    )?;
358                    if !<() as $distinguished_value<Packed<E>, C>>::CHECKS_EMPTY
359                        && <() as EmptyState<(), C>>::is_empty(value)
360                    {
361                        ctx.check(Canonicity::NotCanonical)
362                    } else {
363                        Ok(canon)
364                    }
365                } else {
366                    // Otherwise, try decoding it in the unpacked representation
367                    _ = ctx.check(Canonicity::NotCanonical)?;
368                    unpacked::$mode::decode::<C, E>(
369                        wire_type,
370                        value,
371                        buf,
372                        ctx.into_inner(),
373                    )?;
374                    Ok(Canonicity::NotCanonical)
375                }
376            }
377        }
378
379        impl<$($lifetime,)? T, const N: usize, E>
380        $relaxed_value <$($lifetime,)? Packed<E>, [T; N]> for ()
381        where
382            (): $relaxed_value <$($lifetime,)? E, T>,
383        {
384            #[inline]
385            fn $relaxed_value_method $($($buf_generic)*)? (
386                value: &mut [T; N],
387                mut buf: Capped<$buf_ty>,
388                ctx: DecodeContext,
389            ) -> Result<(), DecodeError> {
390                let mut capped = buf.take_length_delimited()?;
391                // MSRV: this could be .is_some_and(..)
392                if matches!(
393                    <() as Wiretyped<E, T>>::WIRE_TYPE.fixed_size(),
394                    Some(fixed_size) if capped.remaining_before_cap() != fixed_size * N
395                ) {
396                    // We know the exact size of a valid value and this isn't it.
397                    return Err(DecodeError::new(InvalidValue));
398                }
399
400                for dest in value {
401                    // If the value's size was already checked, we don't need to check again
402                    if <() as Wiretyped<E, T>>::WIRE_TYPE.fixed_size().is_none()
403                        && !capped.has_remaining()?
404                    {
405                        // Not enough values
406                        return Err(DecodeError::new(InvalidValue));
407                    }
408                    <() as $relaxed_value<E, _>>::$relaxed_value_method(
409                        dest, capped.lend(), ctx.clone())?;
410                }
411
412                // If the value's size was already checked, we don't need to check again
413                if <() as Wiretyped<E, T>>::WIRE_TYPE.fixed_size().is_none()
414                    && capped.has_remaining()?
415                {
416                    // Too many values or trailing data
417                    Err(DecodeError::new(InvalidValue))
418                } else {
419                    Ok(())
420                }
421            }
422        }
423
424        impl<$($lifetime,)? T, const N: usize, E>
425        $distinguished_value <$($lifetime,)? Packed<E>, [T; N]> for ()
426        where
427            (): $distinguished_value <$($lifetime,)? E, T>,
428        {
429            const CHECKS_EMPTY: bool = false;
430
431            #[inline]
432            fn $distinguished_value_method <const ALLOW_EMPTY: bool>(
433                value: &mut [T; N],
434                mut buf: Capped<$impl_buf_ty>,
435                ctx: RestrictedDecodeContext,
436            ) -> Result<Canonicity, DecodeError> {
437                let mut capped = buf.take_length_delimited()?;
438                // MSRV: this could be .is_some_and(..)
439                if matches!(
440                    <() as Wiretyped<E, T>>::WIRE_TYPE.fixed_size(),
441                    Some(fixed_size) if capped.remaining_before_cap() != fixed_size * N
442                ) {
443                    // We know the exact size of a valid value and this isn't it.
444                    return Err(DecodeError::new(InvalidValue));
445                }
446
447                let mut canon = Canonicity::Canonical;
448                for dest in value.iter_mut() {
449                    // If the value's size was already checked, we don't need to check again
450                    if <() as Wiretyped<E, T>>::WIRE_TYPE.fixed_size().is_none()
451                        && !capped.has_remaining()?
452                    {
453                        // Not enough values
454                        return Err(DecodeError::new(InvalidValue));
455                    }
456                    canon.update(
457                        // Empty values are allowed because they are nested
458                        <() as $distinguished_value<E, _>>::$distinguished_value_method::<true>(
459                            dest,
460                            capped.lend(),
461                            ctx.clone(),
462                        )?,
463                    );
464                }
465
466                // If the value's size was already checked, we don't need to check again
467                if <() as Wiretyped<E, T>>::WIRE_TYPE.fixed_size().is_none()
468                    && capped.has_remaining()?
469                {
470                    // Too many values or trailing data
471                    Err(DecodeError::new(InvalidValue))
472                } else {
473                    Ok(canon)
474                }
475            }
476        }
477
478        impl<$($lifetime,)? T, const N: usize, E>
479        $relaxed <$($lifetime,)? Packed<E>, [T; N]> for ()
480        where
481            (): $relaxed_value <$($lifetime,)? E, T> + EmptyState<E, [T; N]>,
482        {
483            #[inline]
484            fn $relaxed_method $($($buf_generic)*)? (
485                wire_type: WireType,
486                value: &mut [T; N],
487                buf: Capped<$buf_ty>,
488                ctx: DecodeContext,
489            ) -> Result<(), DecodeError> {
490                if wire_type == WireType::LengthDelimited {
491                    // We've encountered the expected length-delimited type: decode it in packed
492                    // format.
493                    <() as $relaxed_value<Packed<E>, [T; N]>>::
494                        $relaxed_value_method(value, buf, ctx)
495                } else {
496                    // Otherwise, try decoding it in the unpacked representation
497                    unpacked::$mode::decode_array_unpacked_only::<T, N, E>(
498                        wire_type,
499                        value,
500                        buf,
501                        ctx,
502                    )
503                }
504            }
505        }
506
507        impl<$($lifetime,)? T, const N: usize, E>
508        $distinguished <$($lifetime,)? Packed<E>, [T; N]> for ()
509        where
510            T: Eq,
511            (): $distinguished_value <$($lifetime,)? E, T>
512                + $relaxed_value <$($lifetime,)? E, T>
513                + EmptyState<E, [T; N]>,
514        {
515            #[inline]
516            fn $distinguished_method $($($buf_generic)*)? (
517                wire_type: WireType,
518                value: &mut [T; N],
519                buf: Capped<$buf_ty>,
520                ctx: RestrictedDecodeContext,
521            ) -> Result<Canonicity, DecodeError> {
522                if wire_type == WireType::LengthDelimited {
523                    // We've encountered the expected length-delimited type: decode it in packed
524                    // format.
525                    // Set ALLOW_EMPTY to false: empty collections are not canonical
526                    let canon = <() as $distinguished_value<Packed<E>, _>>::
527                        $distinguished_value_method::<false>
528                    (
529                        value,
530                        buf,
531                        ctx.clone(),
532                    )?;
533
534                    if
535                    /* !<[T; N]>::CHECKS_EMPTY && /* it never checks */ */
536                    <() as EmptyState<E, [T; N]>>::is_empty(value) {
537                        ctx.check(Canonicity::NotCanonical)
538                    } else {
539                        Ok(canon)
540                    }
541                } else {
542                    // Otherwise, try decoding it in the unpacked representation
543                    _ = ctx.check(Canonicity::NotCanonical)?;
544                    unpacked::$mode::decode_array_unpacked_only::<T, N, E>(
545                        wire_type,
546                        value,
547                        buf,
548                        ctx.into_inner(),
549                    )?;
550                    Ok(Canonicity::NotCanonical)
551                }
552            }
553        }
554    };
555}
556
557decoding_modes::__invoke!(impl_decoders, owned);
558decoding_modes::__invoke!(impl_decoders, borrowed);