Skip to main content

bilrost/encoding/
tuple.rs

1//! Every tuple type starting at arity 1 and up to arity 12 implements ValueEncoder for the encoding
2//! (E1, ... EN) where its elements are encoded with the corresponding sub-encoding. The
3//! representation on the wire is exactly the same as if it were a message type that had fields with
4//! tags 0 through arity-minus-1.
5//!
6//! Note again that these tags start at zero, not at 1 as they do by default when deriving `Message`
7//! for a struct. This is for similar reasons; struct fields "feel" more natural when numbered
8//! ordinally, but tuple types in rust are *indexed* starting at zero so we prefer to maintain
9//! parity with that.
10//!
11//! The arity-zero unit tuple encodes the same way, but it does so independently of this file.
12//! Because it has no fields, it has a privileged lack of ambiguity regarding *how* it will encode,
13//! where every other tuple type might appear differently when included in a message depending on
14//! which encodings are chosen for each member. For this reason, it is the only tuple type that
15//! implements `Message` itself, and it stands as the prototype for a message with no defined
16//! fields.
17
18use bytes::{Buf, BufMut};
19
20use crate::buf::ReverseBuf;
21use crate::encoding::{
22    delegate_value_encoding, encode_varint, encoded_len_varint,
23    encoding_implemented_via_value_encoding, implement_core_empty_state_rules, prepend_varint,
24    skip_field, BorrowDecoder, Canonicity, Capped, DecodeContext, Decoder,
25    DistinguishedBorrowDecoder, DistinguishedDecoder, DistinguishedValueBorrowDecoder,
26    DistinguishedValueDecoder, EmptyState, Encoder, ForOverwrite, General, GeneralGeneric,
27    RestrictedDecodeContext, TagReader, TagRevWriter, TagWriter, TrivialTagMeasurer,
28    ValueBorrowDecoder, ValueDecoder, ValueEncoder, WireType, Wiretyped,
29};
30use crate::DecodeError;
31use crate::DecodeErrorKind::UnexpectedlyRepeated;
32
33macro_rules! impl_tuple {
34    (
35        $arity:expr,
36        $name:expr,
37        $test_mod_name:ident,
38        ($($numbers:tt),*),
39        ($($numbers_desc:tt),*),
40        ($($letters:ident),*),
41        ($($letters_desc:ident),*),
42        ($($encodings:ident),*),
43        ($($encodings_desc:ident),*),
44        ($($tees:ident),*),
45    ) => {
46        implement_core_empty_state_rules!(($($encodings,)*), with generics ($($encodings),*));
47
48        // All tuple types encode as nested messages, so all of them implement ValueEncoder and
49        // should therefore implement Encoder in terms of that.
50        encoding_implemented_via_value_encoding!(
51            ($($encodings,)*),
52            with generics ($($encodings),*)
53        );
54
55        impl<$($letters,)* $($encodings,)*> ForOverwrite<($($encodings,)*), ($($letters,)*)> for ()
56        where
57            $((): ForOverwrite<$encodings, $letters>,)*
58        {
59            #[inline]
60            fn for_overwrite() -> ($($letters,)*) {
61                ($(<() as ForOverwrite<$encodings, $letters>>::for_overwrite(),)*)
62            }
63        }
64
65        impl<$($letters,)* $($encodings,)*> EmptyState<($($encodings,)*), ($($letters,)*)> for ()
66        where
67            $((): EmptyState<$encodings, $letters>,)*
68        {
69            #[inline]
70            fn empty() -> ($($letters,)*) {
71                ($(<() as EmptyState<$encodings, $letters>>::empty(),)*)
72            }
73
74            #[inline]
75            fn is_empty(val: &($($letters,)*)) -> bool {
76                true $(&& <() as EmptyState<$encodings, $letters>>::is_empty(&val.$numbers))*
77            }
78
79            #[inline]
80            fn clear(val: &mut ($($letters,)*)) {
81                $(<() as EmptyState<$encodings, $letters>>::clear(&mut val.$numbers);)*
82            }
83        }
84
85        impl<$($letters,)* $($encodings,)*> Wiretyped<($($encodings,)*), ($($letters,)*)> for () {
86            const WIRE_TYPE: WireType = WireType::LengthDelimited;
87        }
88
89        impl<$($letters,)* $($encodings,)*> ValueEncoder<($($encodings,)*), ($($letters,)*)> for ()
90        where
91            $((): EmptyState<$encodings, $letters> + Encoder<$encodings, $letters>,)*
92        {
93            #[inline]
94            fn encode_value<__B: BufMut + ?Sized>(value: &($($letters,)*), buf: &mut __B) {
95                // Because we do not implement tuples with more than arity 32, we can always use
96                // the trivial tag measurer implementation.
97                let tm = &mut TrivialTagMeasurer::new();
98                let message_len = 0usize $(+ <() as Encoder<$encodings, _>>::encoded_len(
99                    $numbers,
100                    &value.$numbers,
101                    tm,
102                ))*;
103                encode_varint(message_len as u64, buf);
104                let tw = &mut TagWriter::new();
105                $(<() as Encoder<$encodings, _>>::encode($numbers, &value.$numbers, buf, tw);)*
106            }
107
108            #[inline]
109            fn prepend_value<__B: ReverseBuf + ?Sized>(
110                value: &($($letters,)*),
111                buf: &mut __B,
112            ) {
113                let end = buf.remaining();
114                let tw = &mut TagRevWriter::new();
115                $(<() as Encoder<$encodings_desc, _>>::prepend_encode(
116                    $numbers_desc,
117                    &value.$numbers_desc,
118                    buf,
119                    tw,
120                );)*
121                tw.finalize(buf);
122                prepend_varint((buf.remaining() - end) as u64, buf);
123            }
124
125            #[inline]
126            fn value_encoded_len(value: &($($letters,)*)) -> usize {
127                // Because we do not implement tuples with more than arity 32, we can always use
128                // the trivial tag measurer implementation.
129                let tm = &mut TrivialTagMeasurer::new();
130                let message_len = 0usize $(+ <() as Encoder<$encodings, _>>::encoded_len(
131                    $numbers,
132                    &value.$numbers,
133                    tm,
134                ))*;
135                encoded_len_varint(message_len as u64) + message_len
136            }
137        }
138
139        impl<$($letters,)* $($encodings,)*> ValueDecoder<($($encodings,)*), ($($letters,)*)> for ()
140        where
141            $((): EmptyState<$encodings, $letters> + Decoder<$encodings, $letters>,)*
142        {
143            #[inline]
144            fn decode_value<__B: Buf + ?Sized>(
145                value: &mut ($($letters,)*),
146                mut buf: Capped<__B>,
147                ctx: DecodeContext,
148            ) -> Result<(), DecodeError> {
149                let mut buf = buf.take_length_delimited()?;
150                ctx.limit_reached()?;
151                let ctx = ctx.enter_recursion();
152                let tr = &mut TagReader::new();
153                let mut last_tag = None::<u32>;
154                while buf.has_remaining()? {
155                    let (tag, wire_type) = tr.decode_key(buf.lend())?;
156                    let duplicated = last_tag == Some(tag);
157                    last_tag = Some(tag);
158                    // Decode the field. Each tuple field has a tag corresponding to its index.
159                    match tag {
160                        $($numbers => {
161                            if duplicated {
162                                Err(DecodeError::new(UnexpectedlyRepeated))
163                            } else {
164                                <() as Decoder<$encodings, _>>::decode(
165                                    wire_type,
166                                    &mut value.$numbers,
167                                    buf.lend(),
168                                    ctx.clone(),
169                                )
170                            }
171                            .map_err(|mut error| {
172                                error.push($name, stringify!($numbers));
173                                error
174                            })?
175                        })*
176                        _ => skip_field(wire_type, buf.lend())?,
177                    }
178                }
179                Ok(())
180            }
181        }
182
183        impl<$($letters,)* $($encodings,)*>
184        DistinguishedValueDecoder<($($encodings,)*), ($($letters,)*)> for ()
185        where
186            ($($letters,)*): Eq,
187            $(
188                $letters: Eq,
189                (): EmptyState<$encodings, $letters>
190                    + DistinguishedDecoder<$encodings, $letters>,
191            )*
192        {
193            const CHECKS_EMPTY: bool = true; // Message types are always zero-length when empty
194
195            #[inline]
196            fn decode_value_distinguished<const ALLOW_EMPTY: bool>(
197                value: &mut ($($letters,)*),
198                mut buf: Capped<impl Buf + ?Sized>,
199                ctx: RestrictedDecodeContext,
200            ) -> Result<Canonicity, DecodeError>
201            where
202                ($($letters,)*): Sized,
203            {
204                let mut buf = buf.take_length_delimited()?;
205                // Since tuples emulate messages, empty values always encode and decode from zero
206                // bytes. It is far cheaper to check here than to check after the value has been
207                // decoded and checking the value's `is_empty()`.
208                if !ALLOW_EMPTY && buf.remaining_before_cap() == 0 {
209                    return ctx.check(Canonicity::NotCanonical);
210                }
211                ctx.limit_reached()?;
212                let mut canon = Canonicity::Canonical;
213                let ctx = ctx.enter_recursion();
214                let tr = &mut TagReader::new();
215                let mut last_tag = None::<u32>;
216                while buf.has_remaining()? {
217                    let (tag, wire_type) = tr.decode_key(buf.lend())?;
218                    let duplicated = last_tag == Some(tag);
219                    last_tag = Some(tag);
220                    // Decode the field. Each tuple field has a tag corresponding to its index.
221                    match tag {
222                        $($numbers => {
223                            canon.update(
224                                if duplicated {
225                                    Err(DecodeError::new(UnexpectedlyRepeated))
226                                } else {
227                                    <() as DistinguishedDecoder<$encodings, _>>
228                                        ::decode_distinguished(
229                                            wire_type,
230                                            &mut value.$numbers,
231                                            buf.lend(),
232                                            ctx.clone(),
233                                        )
234                                }
235                                .map_err(|mut error| {
236                                    error.push($name, stringify!($numbers));
237                                    error
238                                })?
239                            );
240                        })*
241                        _ => {
242                            canon.update(ctx.check(Canonicity::HasExtensions)?);
243                            skip_field(wire_type, buf.lend())?;
244                        },
245                    }
246                }
247                Ok(canon)
248            }
249        }
250
251        // We'd like to implement the borrowed decoders here with decoding_modes::__invoke!, but it
252        // seems the optional lifetime and the repeating elements in the tuple won't nest in
253        // macro_rules!.
254
255        impl<'a, $($letters,)* $($encodings,)*>
256        ValueBorrowDecoder<'a, ($($encodings,)*), ($($letters,)*)> for ()
257        where
258            $((): EmptyState<$encodings, $letters> + BorrowDecoder<'a, $encodings, $letters>,)*
259        {
260            #[inline]
261            fn borrow_decode_value(
262                value: &mut ($($letters,)*),
263                mut buf: Capped<&'a [u8]>,
264                ctx: DecodeContext,
265            ) -> Result<(), DecodeError> {
266                let mut buf = buf.take_length_delimited()?;
267                ctx.limit_reached()?;
268                let ctx = ctx.enter_recursion();
269                let tr = &mut TagReader::new();
270                let mut last_tag = None::<u32>;
271                while buf.has_remaining()? {
272                    let (tag, wire_type) = tr.decode_key(buf.lend())?;
273                    let duplicated = last_tag == Some(tag);
274                    last_tag = Some(tag);
275                    // Decode the field. Each tuple field has a tag corresponding to its index.
276                    match tag {
277                        $($numbers => {
278                            if duplicated {
279                                Err(DecodeError::new(UnexpectedlyRepeated))
280                            } else {
281                                <() as BorrowDecoder<$encodings, _>>::borrow_decode(
282                                    wire_type,
283                                    &mut value.$numbers,
284                                    buf.lend(),
285                                    ctx.clone(),
286                                )
287                            }
288                            .map_err(|mut error| {
289                                error.push($name, stringify!($numbers));
290                                error
291                            })?
292                        })*
293                        _ => skip_field(wire_type, buf.lend())?,
294                    }
295                }
296                Ok(())
297            }
298        }
299
300        impl<'a, $($letters,)* $($encodings,)*>
301        DistinguishedValueBorrowDecoder<'a, ($($encodings,)*), ($($letters,)*)> for ()
302        where
303            ($($letters,)*): Eq,
304            $(
305                $letters: Eq,
306                (): EmptyState<$encodings, $letters>
307                    + DistinguishedBorrowDecoder<'a, $encodings, $letters>,
308            )*
309        {
310            const CHECKS_EMPTY: bool = true; // Message types are always zero-length when empty
311
312            #[inline]
313            fn borrow_decode_value_distinguished<const ALLOW_EMPTY: bool>(
314                value: &mut ($($letters,)*),
315                mut buf: Capped<&'a [u8]>,
316                ctx: RestrictedDecodeContext,
317            ) -> Result<Canonicity, DecodeError>
318            where
319                ($($letters,)*): Sized,
320            {
321                let mut buf = buf.take_length_delimited()?;
322                // Since tuples emulate messages, empty values always encode and decode from zero
323                // bytes. It is far cheaper to check here than to check after the value has been
324                // decoded and checking the value's `is_empty()`.
325                if !ALLOW_EMPTY && buf.remaining_before_cap() == 0 {
326                    return ctx.check(Canonicity::NotCanonical);
327                }
328                ctx.limit_reached()?;
329                let mut canon = Canonicity::Canonical;
330                let ctx = ctx.enter_recursion();
331                let tr = &mut TagReader::new();
332                let mut last_tag = None::<u32>;
333                while buf.has_remaining()? {
334                    let (tag, wire_type) = tr.decode_key(buf.lend())?;
335                    let duplicated = last_tag == Some(tag);
336                    last_tag = Some(tag);
337                    // Decode the field. Each tuple field has a tag corresponding to its index.
338                    match tag {
339                        $($numbers => {
340                            canon.update(
341                                if duplicated {
342                                    Err(DecodeError::new(UnexpectedlyRepeated))
343                                } else {
344                                    <() as DistinguishedBorrowDecoder<$encodings, _>>
345                                        ::borrow_decode_distinguished(
346                                            wire_type,
347                                            &mut value.$numbers,
348                                            buf.lend(),
349                                            ctx.clone(),
350                                        )
351                                }
352                                .map_err(|mut error| {
353                                    error.push($name, stringify!($numbers));
354                                    error
355                                })?
356                            );
357                        })*
358                        _ => {
359                            canon.update(ctx.check(Canonicity::HasExtensions)?);
360                            skip_field(wire_type, buf.lend())?;
361                        },
362                    }
363                }
364                Ok(canon)
365            }
366        }
367
368        #[cfg(test)]
369        mod $test_mod_name {
370            // MSRV: impl From<[T; N]> for (T, ...{N}) is new in rust 1.71
371            fn array_to_tuple<T: Clone>(arr: [T; $arity]) -> ($($tees,)*) {
372                ($(arr[$numbers].clone(),)*)
373            }
374
375            mod delegated_bools {
376                use crate::encoding::General;
377                use crate::encoding::test::check_type_test;
378                type T = bool;
379
380                check_type_test!(
381                    General,
382                    relaxed,
383                    from [T; $arity],
384                    into ($($tees,)*),
385                    converter(value) { super::super::array_to_tuple(value) },
386                    WireType::LengthDelimited
387                );
388                check_type_test!(
389                    General,
390                    distinguished,
391                    from [T; $arity],
392                    into ($($tees,)*),
393                    converter(value) { super::super::array_to_tuple(value) },
394                    WireType::LengthDelimited
395                );
396            }
397            mod varint_bools {
398                use crate::encoding::test::check_type_test;
399                type T = bool;
400                $(type $encodings = crate::encoding::Varint;)*
401
402                check_type_test!(
403                    ($($encodings,)*),
404                    relaxed,
405                    from [T; $arity],
406                    into ($($tees,)*),
407                    converter(value) { super::super::array_to_tuple(value) },
408                    WireType::LengthDelimited
409                );
410                check_type_test!(
411                    ($($encodings,)*),
412                    distinguished,
413                    from [T; $arity],
414                    into ($($tees,)*),
415                    converter(value) { super::super::array_to_tuple(value) },
416                    WireType::LengthDelimited
417                );
418            }
419            mod fixed_floats {
420                use crate::encoding::test::check_type_test;
421                type T = f32;
422                $(type $encodings = crate::encoding::Fixed;)*
423
424                check_type_test!(
425                    ($($encodings,)*),
426                    relaxed,
427                    from [T; $arity],
428                    into ($($tees,)*),
429                    converter(value) { super::super::array_to_tuple(value) },
430                    WireType::LengthDelimited
431                );
432            }
433            mod small_arrays {
434                use crate::encoding::test::check_type_test;
435                type T = [u8; 1];
436                $(type $encodings = crate::encoding::PlainBytes;)*
437
438                check_type_test!(
439                    ($($encodings,)*),
440                    relaxed,
441                    from [T; $arity],
442                    into ($($tees,)*),
443                    converter(value) { super::super::array_to_tuple(value) },
444                    WireType::LengthDelimited
445                );
446                check_type_test!(
447                    ($($encodings,)*),
448                    distinguished,
449                    from [T; $arity],
450                    into ($($tees,)*),
451                    converter(value) { super::super::array_to_tuple(value) },
452                    WireType::LengthDelimited
453                );
454            }
455        }
456    }
457}
458
459impl_tuple!(
460    1,             //
461    "(1-tuple)",   //
462    tuple_arity_1, //
463    (0),           //
464    (0),           //
465    (A),           //
466    (A),           //
467    (Ae),          //
468    (Ae),          //
469    (T),           //
470);
471impl_tuple!(
472    2,             //
473    "(2-tuple)",   //
474    tuple_arity_2, //
475    (0, 1),        //
476    (1, 0),        //
477    (A, B),        //
478    (B, A),        //
479    (Ae, Be),      //
480    (Be, Ae),      //
481    (T, T),        //
482);
483impl_tuple!(
484    3,             //
485    "(3-tuple)",   //
486    tuple_arity_3, //
487    (0, 1, 2),     //
488    (2, 1, 0),     //
489    (A, B, C),     //
490    (C, B, A),     //
491    (Ae, Be, Ce),  //
492    (Ce, Be, Ae),  //
493    (T, T, T),     //
494);
495impl_tuple!(
496    4,                //
497    "(4-tuple)",      //
498    tuple_arity_4,    //
499    (0, 1, 2, 3),     //
500    (3, 2, 1, 0),     //
501    (A, B, C, D),     //
502    (D, C, B, A),     //
503    (Ae, Be, Ce, De), //
504    (De, Ce, Be, Ae), //
505    (T, T, T, T),     //
506);
507impl_tuple!(
508    5,                    //
509    "(5-tuple)",          //
510    tuple_arity_5,        //
511    (0, 1, 2, 3, 4),      //
512    (4, 3, 2, 1, 0),      //
513    (A, B, C, D, E),      //
514    (E, D, C, B, A),      //
515    (Ae, Be, Ce, De, Ee), //
516    (Ee, De, Ce, Be, Ae), //
517    (T, T, T, T, T),      //
518);
519impl_tuple!(
520    6,                        //
521    "(6-tuple)",              //
522    tuple_arity_6,            //
523    (0, 1, 2, 3, 4, 5),       //
524    (5, 4, 3, 2, 1, 0),       //
525    (A, B, C, D, E, F),       //
526    (F, E, D, C, B, A),       //
527    (Ae, Be, Ce, De, Ee, Fe), //
528    (Fe, Ee, De, Ce, Be, Ae), //
529    (T, T, T, T, T, T),       //
530);
531impl_tuple!(
532    7,                            //
533    "(7-tuple)",                  //
534    tuple_arity_7,                //
535    (0, 1, 2, 3, 4, 5, 6),        //
536    (6, 5, 4, 3, 2, 1, 0),        //
537    (A, B, C, D, E, F, G),        //
538    (G, F, E, D, C, B, A),        //
539    (Ae, Be, Ce, De, Ee, Fe, Ge), //
540    (Ge, Fe, Ee, De, Ce, Be, Ae), //
541    (T, T, T, T, T, T, T),        //
542);
543impl_tuple!(
544    8,                                //
545    "(8-tuple)",                      //
546    tuple_arity_8,                    //
547    (0, 1, 2, 3, 4, 5, 6, 7),         //
548    (7, 6, 5, 4, 3, 2, 1, 0),         //
549    (A, B, C, D, E, F, G, H),         //
550    (H, G, F, E, D, C, B, A),         //
551    (Ae, Be, Ce, De, Ee, Fe, Ge, He), //
552    (He, Ge, Fe, Ee, De, Ce, Be, Ae), //
553    (T, T, T, T, T, T, T, T),         //
554);
555impl_tuple!(
556    9,                                    //
557    "(9-tuple)",                          //
558    tuple_arity_9,                        //
559    (0, 1, 2, 3, 4, 5, 6, 7, 8),          //
560    (8, 7, 6, 5, 4, 3, 2, 1, 0),          //
561    (A, B, C, D, E, F, G, H, I),          //
562    (I, H, G, F, E, D, C, B, A),          //
563    (Ae, Be, Ce, De, Ee, Fe, Ge, He, Ie), //
564    (Ie, He, Ge, Fe, Ee, De, Ce, Be, Ae), //
565    (T, T, T, T, T, T, T, T, T),          //
566);
567impl_tuple!(
568    10,                                       //
569    "(10-tuple)",                             //
570    tuple_arity_10,                           //
571    (0, 1, 2, 3, 4, 5, 6, 7, 8, 9),           //
572    (9, 8, 7, 6, 5, 4, 3, 2, 1, 0),           //
573    (A, B, C, D, E, F, G, H, I, J),           //
574    (J, I, H, G, F, E, D, C, B, A),           //
575    (Ae, Be, Ce, De, Ee, Fe, Ge, He, Ie, Je), //
576    (Je, Ie, He, Ge, Fe, Ee, De, Ce, Be, Ae), //
577    (T, T, T, T, T, T, T, T, T, T),           //
578);
579impl_tuple!(
580    11,                                           //
581    "(11-tuple)",                                 //
582    tuple_arity_11,                               //
583    (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10),           //
584    (10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0),           //
585    (A, B, C, D, E, F, G, H, I, J, K),            //
586    (K, J, I, H, G, F, E, D, C, B, A),            //
587    (Ae, Be, Ce, De, Ee, Fe, Ge, He, Ie, Je, Ke), //
588    (Ke, Je, Ie, He, Ge, Fe, Ee, De, Ce, Be, Ae), //
589    (T, T, T, T, T, T, T, T, T, T, T),            //
590);
591impl_tuple!(
592    12,                                               //
593    "(12-tuple)",                                     //
594    tuple_arity_12,                                   //
595    (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11),           //
596    (11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0),           //
597    (A, B, C, D, E, F, G, H, I, J, K, L),             //
598    (L, K, J, I, H, G, F, E, D, C, B, A),             //
599    (Ae, Be, Ce, De, Ee, Fe, Ge, He, Ie, Je, Ke, Le), //
600    (Le, Ke, Je, Ie, He, Ge, Fe, Ee, De, Ce, Be, Ae), //
601    (T, T, T, T, T, T, T, T, T, T, T, T),             //
602);
603
604delegate_value_encoding!(
605    delegate from (GeneralGeneric<P>) to ((General,))
606    for type ((A,)) including distinguished
607    with generics (const P: u8, A)
608);
609delegate_value_encoding!(
610    delegate from (GeneralGeneric<P>) to ((General, General))
611    for type ((A, B)) including distinguished
612    with generics (const P: u8, A, B)
613);
614delegate_value_encoding!(
615    delegate from (GeneralGeneric<P>) to ((General, General, General))
616    for type ((A, B, C)) including distinguished
617    with generics (const P: u8, A, B, C)
618);
619delegate_value_encoding!(
620    delegate from (GeneralGeneric<P>) to ((General, General, General, General))
621    for type ((A, B, C, D)) including distinguished
622    with generics (const P: u8, A, B, C, D)
623);
624delegate_value_encoding!(
625    delegate from (GeneralGeneric<P>) to ((General, General, General, General, General))
626    for type ((A, B, C, D, E)) including distinguished
627    with generics (const P: u8, A, B, C, D, E)
628);
629delegate_value_encoding!(
630    delegate from (GeneralGeneric<P>) to ((General, General, General, General, General, General))
631    for type ((A, B, C, D, E, F)) including distinguished
632    with generics (const P: u8, A, B, C, D, E, F)
633);
634delegate_value_encoding!(
635    delegate from (GeneralGeneric<P>) to ((General, General, General, General, General, General,
636                                           General))
637    for type ((A, B, C, D, E, F, G)) including distinguished
638    with generics (const P: u8, A, B, C, D, E, F, G)
639);
640delegate_value_encoding!(
641    delegate from (GeneralGeneric<P>) to ((General, General, General, General, General, General,
642                                           General, General))
643    for type ((A, B, C, D, E, F, G, H)) including distinguished
644    with generics (const P: u8, A, B, C, D, E, F, G, H)
645);
646delegate_value_encoding!(
647    delegate from (GeneralGeneric<P>) to ((General, General, General, General, General, General,
648                                           General, General, General))
649    for type ((A, B, C, D, E, F, G, H, I)) including distinguished
650    with generics (const P: u8, A, B, C, D, E, F, G, H, I)
651);
652delegate_value_encoding!(
653    delegate from (GeneralGeneric<P>) to ((General, General, General, General, General, General,
654                                           General, General, General, General))
655    for type ((A, B, C, D, E, F, G, H, I, J)) including distinguished
656    with generics (const P: u8, A, B, C, D, E, F, G, H, I, J)
657);
658delegate_value_encoding!(
659    delegate from (GeneralGeneric<P>) to ((General, General, General, General, General, General,
660                                           General, General, General, General, General))
661    for type ((A, B, C, D, E, F, G, H, I, J, K)) including distinguished
662    with generics (const P: u8, A, B, C, D, E, F, G, H, I, J, K)
663);
664delegate_value_encoding!(
665    delegate from (GeneralGeneric<P>) to ((General, General, General, General, General, General,
666                                           General, General, General, General, General, General))
667    for type ((A, B, C, D, E, F, G, H, I, J, K, L)) including distinguished
668    with generics (const P: u8, A, B, C, D, E, F, G, H, I, J, K, L)
669);