rasn/
uper.rs

1//! # Unaligned Packed Encoding Rules
2//!
3//! Codec functions for UPER, rasn provides a "basic" decoder, and canonical encoder.
4//! This means that users are able decode any valid UPER value, and that rasn's
5//! encoding will always produce the same output for the same value.
6
7use crate::types::Constraints;
8
9pub use super::per::*;
10
11/// Attempts to decode `T` from `input` using UPER-BASIC.
12pub fn decode<T: crate::Decode>(input: &[u8]) -> Result<T, crate::error::DecodeError> {
13    crate::per::decode(de::DecoderOptions::unaligned(), input)
14}
15
16/// Attempts to encode `value` to UPER-CANONICAL.
17pub fn encode<T: crate::Encode>(
18    value: &T,
19) -> Result<alloc::vec::Vec<u8>, crate::error::EncodeError> {
20    crate::per::encode(enc::EncoderOptions::unaligned(), value)
21}
22
23/// Attempts to decode `T` from `input` using UPER-BASIC.
24pub fn decode_with_constraints<T: crate::Decode>(
25    constraints: Constraints,
26    input: &[u8],
27) -> Result<T, crate::error::DecodeError> {
28    crate::per::decode_with_constraints(de::DecoderOptions::unaligned(), constraints, input)
29}
30
31/// Attempts to encode `value` to UPER-CANONICAL.
32pub fn encode_with_constraints<T: crate::Encode>(
33    constraints: Constraints,
34    value: &T,
35) -> Result<alloc::vec::Vec<u8>, crate::error::EncodeError> {
36    crate::per::encode_with_constraints(enc::EncoderOptions::unaligned(), constraints, value)
37}
38
39#[cfg(test)]
40mod tests {
41    use crate::{
42        prelude::*,
43        types::{constraints::*, *},
44    };
45    #[test]
46    fn bool() {
47        round_trip!(uper, bool, true, &[0x80]);
48        round_trip!(uper, bool, false, &[0]);
49    }
50
51    #[test]
52    fn integer() {
53        round_trip!(uper, Integer, 32768.into(), &[0x03, 0x00, 0x80, 0x00]);
54        round_trip!(uper, Integer, 32767.into(), &[0x02, 0x7f, 0xff]);
55        round_trip!(uper, Integer, 256.into(), &[0x02, 0x01, 0x00]);
56        round_trip!(uper, Integer, 255.into(), &[0x02, 0x00, 0xff]);
57        round_trip!(uper, Integer, 128.into(), &[0x02, 0x00, 0x80]);
58        round_trip!(uper, Integer, 127.into(), &[0x01, 0x7f]);
59        round_trip!(uper, Integer, 1.into(), &[0x01, 0x01]);
60        round_trip!(uper, Integer, 0.into(), &[0x01, 0x00]);
61        round_trip!(uper, Integer, (-1).into(), &[0x01, 0xff]);
62        round_trip!(uper, Integer, (-128).into(), &[0x01, 0x80]);
63        round_trip!(uper, Integer, (-129).into(), &[0x02, 0xff, 0x7f]);
64        round_trip!(uper, Integer, (-256).into(), &[0x02, 0xff, 0x00]);
65        round_trip!(uper, Integer, (-32768).into(), &[0x02, 0x80, 0x00]);
66        round_trip!(uper, Integer, (-32769).into(), &[0x03, 0xff, 0x7f, 0xff]);
67
68        type B = ConstrainedInteger<5, 99>;
69        type C = ConstrainedInteger<-10, 10>;
70        //type D = ExtensibleConstrainedInteger<5, 99>;
71        type E = ConstrainedInteger<1000, 1000>;
72
73        round_trip!(uper, B, 5.into(), &[0x00]);
74        round_trip!(uper, B, 6.into(), &[0x02]);
75        round_trip!(uper, B, 99.into(), &[0xbc]);
76        round_trip!(uper, C, (-10).into(), &[0x00]);
77        round_trip!(uper, C, (-1).into(), &[0x48]);
78        round_trip!(uper, C, 0.into(), &[0x50]);
79        round_trip!(uper, C, 1.into(), &[0x58]);
80        round_trip!(uper, C, 10.into(), &[0xa0]);
81        // round_trip!(uper, D, 99, &[0x5e]);
82        round_trip!(uper, E, Integer::from(1000).into(), &[]);
83    }
84
85    #[test]
86    fn sequence_of() {
87        round_trip!(uper, Vec<u8>, vec![1; 5], &[0b00000101, 1, 1, 1, 1, 1]);
88        round_trip!(aper, Vec<u8>, vec![1; 5], &[0b00000101, 1, 1, 1, 1, 1]);
89    }
90
91    #[test]
92    fn numeric_string() {
93        round_trip!(
94            uper,
95            NumericString,
96            " 0123456789".try_into().unwrap(),
97            &[0x0b, 0x01, 0x23, 0x45, 0x67, 0x89, 0xa0]
98        );
99        round_trip_with_constraints!(
100            uper,
101            NumericString,
102            Constraints::new(&[Constraint::Size(Size::new(Bounded::Single(5)).into())]),
103            "1 9 5".try_into().unwrap(),
104            &[0x20, 0xa0, 0x60]
105        );
106
107        round_trip_with_constraints!(
108            uper,
109            NumericString,
110            Constraints::new(&[Constraint::Size(
111                Size::new(Bounded::Range {
112                    start: 19.into(),
113                    end: 134.into()
114                })
115                .into()
116            )]),
117            "0123456789 9876543210".try_into().unwrap(),
118            &[0x04, 0x24, 0x68, 0xac, 0xf1, 0x34, 0x15, 0x30, 0xec, 0xa8, 0x64, 0x20]
119        );
120
121        round_trip_with_constraints!(
122            uper,
123            NumericString,
124            Constraints::new(&[Constraint::PermittedAlphabet(
125                PermittedAlphabet::new(&[
126                    b'0' as u32,
127                    b'1' as u32,
128                    b'2' as u32,
129                    b'3' as u32,
130                    b'4' as u32,
131                    b'5' as u32
132                ])
133                .into()
134            )]),
135            "5".try_into().unwrap(),
136            &[0x01, 0xa0]
137        );
138    }
139
140    #[test]
141    fn visible_string() {
142        round_trip_with_constraints!(
143            uper,
144            VisibleString,
145            Constraints::new(&[Constraint::Size(
146                Size::new(Bounded::Range {
147                    start: 19.into(),
148                    end: 133.into()
149                })
150                .into()
151            )]),
152            "HejHoppHappHippAbcde".try_into().unwrap(),
153            &[
154                0x03, 0x23, 0x2e, 0xa9, 0x1b, 0xf8, 0x70, 0x91, 0x87, 0x87, 0x09, 0x1a, 0x78, 0x70,
155                0x83, 0x8b, 0x1e, 0x4c, 0xa0
156            ]
157        );
158
159        round_trip_with_constraints!(
160            uper,
161            VisibleString,
162            Constraints::new(&[Constraint::Size(Size::new(Bounded::Single(5)).into())]),
163            "Hejaa".try_into().unwrap(),
164            &[0x91, 0x97, 0x56, 0x1c, 0x20]
165        );
166
167        const ALPHABET: &[u32] = &{
168            let mut array = [0; 26];
169            let mut i = 0;
170            let mut start = 'a' as u32;
171            let end = 'z' as u32;
172            loop {
173                array[i] = start;
174                start += 1;
175                i += 1;
176
177                if start > end {
178                    break;
179                }
180            }
181
182            array
183        };
184
185        round_trip_with_constraints!(
186            uper,
187            VisibleString,
188            Constraints::new(&[
189                Constraint::Size(
190                    Size::new(Bounded::Range {
191                        start: 1.into(),
192                        end: 255.into()
193                    })
194                    .into()
195                ),
196                Constraint::PermittedAlphabet(PermittedAlphabet::new(ALPHABET).into()),
197            ]),
198            "hej".try_into().unwrap(),
199            &[0x02, 0x39, 0x12]
200        );
201    }
202    #[test]
203    fn printable_string() {
204        round_trip_with_constraints!(
205            uper,
206            PrintableString,
207            Constraints::new(&[Constraint::Size(Size::new(Bounded::Single(16)).into())]),
208            PrintableString::from_bytes("0123456789abcdef".as_bytes()).unwrap(),
209            &[0x60, 0xc5, 0x93, 0x36, 0x8d, 0x5b, 0x37, 0x70, 0xe7, 0x0e, 0x2c, 0x79, 0x32, 0xe6]
210        );
211        round_trip_with_constraints!(
212            uper,
213            PrintableString,
214            Constraints::new(&[Constraint::Size(
215                Size::new(Bounded::Range {
216                    start: 0.into(),
217                    end: 31.into()
218                })
219                .into()
220            )]),
221            "".try_into().unwrap(),
222            &[0x00]
223        );
224        round_trip_with_constraints!(
225            uper,
226            PrintableString,
227            Constraints::new(&[Constraint::Size(
228                Size::new(Bounded::Range {
229                    start: 0.into(),
230                    end: 31.into()
231                })
232                .into()
233            )]),
234            "2".try_into().unwrap(),
235            &[0x0b, 0x20]
236        );
237
238        #[derive(AsnType, Clone, Debug, Decode, Encode, PartialEq)]
239        #[rasn(crate_root = "crate")]
240        struct PrintStruct {
241            a: bool,
242            #[rasn(size("36"))]
243            b: PrintableString,
244            c: bool,
245        }
246        round_trip!(
247            uper,
248            PrintStruct,
249            PrintStruct {
250                a: true,
251                b: "123123123123123123123123123123123123".try_into().unwrap(),
252                c: true
253            },
254            &[
255                0xb1, 0x64, 0xcd, 0x8b, 0x26, 0x6c, 0x59, 0x33, 0x62, 0xc9, 0x9b, 0x16, 0x4c, 0xd8,
256                0xb2, 0x66, 0xc5, 0x93, 0x36, 0x2c, 0x99, 0xb1, 0x64, 0xcd, 0x8b, 0x26, 0x6c, 0x59,
257                0x33, 0x62, 0xc9, 0x9c
258            ]
259        );
260    }
261
262    #[test]
263    fn choice() {
264        use crate as rasn;
265        #[derive(AsnType, Decode, Debug, Encode, PartialEq)]
266        #[rasn(choice, automatic_tags)]
267        #[non_exhaustive]
268        enum Choice {
269            Normal,
270            High,
271            #[rasn(extension_addition)]
272            Medium,
273        }
274
275        round_trip!(uper, Choice, Choice::Normal, &[0]);
276        round_trip!(uper, Choice, Choice::Medium, &[0x80, 1, 0]);
277        round_trip!(aper, Choice, Choice::Medium, &[0x80, 1, 0]);
278    }
279
280    #[test]
281    fn enumerated() {
282        #[derive(AsnType, Clone, Copy, Debug, Decode, Encode, PartialEq)]
283        #[rasn(enumerated, crate_root = "crate")]
284        enum Enum1 {
285            Green,
286            Red,
287            Blue,
288        }
289
290        round_trip!(uper, Enum1, Enum1::Green, &[0]);
291        round_trip!(uper, Enum1, Enum1::Red, &[0x40]);
292        round_trip!(uper, Enum1, Enum1::Blue, &[0x80]);
293
294        #[derive(AsnType, Clone, Copy, Debug, Decode, Encode, PartialEq)]
295        #[rasn(enumerated, crate_root = "crate")]
296        #[non_exhaustive]
297        enum Enum2 {
298            Red,
299            Blue,
300            Green,
301            #[rasn(extension_addition)]
302            Yellow,
303            #[rasn(extension_addition)]
304            Purple,
305        }
306
307        round_trip!(uper, Enum2, Enum2::Red, &[0]);
308        round_trip!(uper, Enum2, Enum2::Yellow, &[0x80]);
309        round_trip!(uper, Enum2, Enum2::Purple, &[0x81]);
310    }
311
312    #[test]
313    fn sequence() {
314        #[derive(AsnType, Clone, Debug, Decode, Encode, PartialEq)]
315        #[rasn(crate_root = "crate")]
316        struct B {
317            #[rasn(default)]
318            a: Integer,
319        }
320
321        fn true_identity() -> bool {
322            true
323        }
324
325        #[derive(AsnType, Clone, Debug, Decode, Encode, PartialEq)]
326        #[rasn(crate_root = "crate")]
327        #[non_exhaustive]
328        struct C {
329            a: bool,
330        }
331
332        #[derive(AsnType, Clone, Debug, Decode, Encode, PartialEq)]
333        #[rasn(crate_root = "crate")]
334        #[non_exhaustive]
335        struct D {
336            a: bool,
337            #[rasn(extension_addition_group)]
338            b: Option<DE>,
339        }
340
341        #[derive(AsnType, Clone, Debug, Decode, Encode, PartialEq)]
342        #[rasn(crate_root = "crate")]
343        struct DE {
344            a: bool,
345        }
346
347        #[derive(AsnType, Clone, Debug, Decode, Encode, PartialEq)]
348        #[rasn(crate_root = "crate")]
349        #[non_exhaustive]
350        struct F {
351            a: bool,
352            #[rasn(extension_addition_group)]
353            b: Option<FE>,
354            #[rasn(extension_addition)]
355            c: Option<bool>,
356        }
357
358        #[derive(AsnType, Clone, Debug, Decode, Encode, PartialEq)]
359        #[rasn(crate_root = "crate")]
360        struct FE {
361            a: bool,
362        }
363
364        #[derive(AsnType, Clone, Debug, Decode, Encode, PartialEq)]
365        #[rasn(crate_root = "crate", automatic_tags)]
366        #[non_exhaustive]
367        struct G {
368            a: bool,
369            d: bool,
370            #[rasn(extension_addition_group)]
371            b: Option<GE>,
372            #[rasn(extension_addition_group)]
373            c: Option<GE>,
374        }
375
376        #[derive(AsnType, Clone, Debug, Decode, Encode, PartialEq)]
377        #[rasn(crate_root = "crate")]
378        struct GE {
379            a: bool,
380        }
381
382        #[derive(AsnType, Clone, Debug, Decode, Encode, PartialEq)]
383        #[rasn(crate_root = "crate", automatic_tags)]
384        #[non_exhaustive]
385        struct I {
386            a: bool,
387            #[rasn(extension_addition)]
388            b: Option<bool>,
389        }
390
391        #[derive(AsnType, Clone, Debug, Decode, Encode, PartialEq)]
392        #[rasn(crate_root = "crate", automatic_tags)]
393        #[non_exhaustive]
394        struct J {
395            a: bool,
396            #[rasn(extension_addition)]
397            b: Option<bool>,
398        }
399
400        #[derive(AsnType, Clone, Debug, Decode, Encode, PartialEq)]
401        #[rasn(crate_root = "crate", automatic_tags)]
402        #[non_exhaustive]
403        struct K {
404            a: bool,
405            #[rasn(extension_addition)]
406            b: Option<bool>,
407            #[rasn(extension_addition)]
408            c: Option<bool>,
409        }
410
411        #[derive(AsnType, Clone, Debug, Decode, Encode, PartialEq)]
412        #[rasn(crate_root = "crate")]
413        #[non_exhaustive]
414        struct L {
415            a: bool,
416            #[rasn(extension_addition_group)]
417            b: Option<LE>,
418        }
419
420        #[derive(AsnType, Clone, Debug, Decode, Encode, PartialEq)]
421        #[rasn(crate_root = "crate")]
422        struct LE {
423            a: bool,
424            b: bool,
425        }
426
427        #[derive(AsnType, Clone, Debug, Decode, Encode, PartialEq)]
428        #[rasn(crate_root = "crate")]
429        #[non_exhaustive]
430        struct M {
431            a: bool,
432            #[rasn(extension_addition_group)]
433            b: Option<ME>,
434        }
435
436        #[derive(AsnType, Clone, Debug, Decode, Encode, PartialEq)]
437        #[rasn(crate_root = "crate")]
438        struct ME {
439            a: Option<MESeq>,
440            b: bool,
441        }
442
443        #[derive(AsnType, Clone, Debug, Decode, Encode, PartialEq)]
444        #[rasn(crate_root = "crate")]
445        struct MESeq {
446            a: Integer,
447        }
448
449        #[derive(AsnType, Clone, Debug, Decode, Encode, PartialEq)]
450        #[rasn(crate_root = "crate")]
451        struct N {
452            #[rasn(default = "true_identity")]
453            a: bool,
454        }
455
456        #[derive(AsnType, Clone, Debug, Decode, Encode, PartialEq)]
457        #[rasn(crate_root = "crate")]
458        struct O {
459            #[rasn(extension_addition, default = "true_identity")]
460            a: bool,
461        }
462
463        #[derive(AsnType, Clone, Debug, Decode, Encode, PartialEq)]
464        #[rasn(crate_root = "crate")]
465        #[non_exhaustive]
466        struct P {
467            #[rasn(extension_addition_group)]
468            a: Option<PE>,
469        }
470
471        #[derive(AsnType, Clone, Debug, Decode, Encode, PartialEq)]
472        #[rasn(crate_root = "crate")]
473        struct PE {
474            a: bool,
475            #[rasn(default = "true_identity")]
476            b: bool,
477        }
478
479        #[derive(AsnType, Clone, Debug, Decode, Encode, PartialEq)]
480        #[rasn(crate_root = "crate")]
481        struct Q {
482            a: C,
483            b: Integer,
484        }
485
486        #[derive(AsnType, Clone, Debug, Decode, Encode, PartialEq)]
487        #[rasn(crate_root = "crate")]
488        struct R {
489            a: D,
490            b: Integer,
491        }
492
493        #[derive(AsnType, Clone, Debug, Decode, Encode, PartialEq)]
494        #[rasn(crate_root = "crate")]
495        #[non_exhaustive]
496        struct S {
497            a: bool,
498            #[rasn(extension_addition)]
499            b: Option<SSeq>,
500        }
501
502        #[derive(AsnType, Clone, Debug, Decode, Encode, PartialEq)]
503        #[rasn(crate_root = "crate")]
504        #[non_exhaustive]
505        struct SSeq {
506            a: bool,
507            b: Option<bool>,
508        }
509
510        #[derive(AsnType, Clone, Debug, Decode, Default, Encode, PartialEq)]
511        #[rasn(crate_root = "crate")]
512        struct T {
513            a: Option<SequenceOf<T>>,
514        }
515
516        #[derive(AsnType, Clone, Debug, Decode, Encode, PartialEq)]
517        #[rasn(crate_root = "crate")]
518        #[non_exhaustive]
519        struct U {
520            #[rasn(extension_addition)]
521            a: USeq,
522        }
523
524        #[derive(AsnType, Clone, Debug, Decode, Encode, PartialEq)]
525        #[rasn(crate_root = "crate")]
526        struct USeq {
527            a: Integer,
528        }
529
530        #[derive(AsnType, Clone, Debug, Default, Decode, Encode, PartialEq)]
531        #[rasn(crate_root = "crate", automatic_tags)]
532        #[non_exhaustive]
533        struct V {
534            #[rasn(extension_addition)]
535            a: Option<bool>,
536            #[rasn(extension_addition)]
537            b: Option<bool>,
538            #[rasn(extension_addition)]
539            c: Option<bool>,
540        }
541
542        #[derive(AsnType, Clone, Debug, Default, Decode, Encode, PartialEq)]
543        #[rasn(crate_root = "crate", automatic_tags)]
544        #[non_exhaustive]
545        struct W {
546            #[rasn(extension_addition)]
547            a1: Option<bool>,
548            #[rasn(extension_addition)]
549            a2: Option<bool>,
550            #[rasn(extension_addition)]
551            a3: Option<bool>,
552            #[rasn(extension_addition)]
553            a4: Option<bool>,
554            #[rasn(extension_addition)]
555            a5: Option<bool>,
556            #[rasn(extension_addition)]
557            a6: Option<bool>,
558            #[rasn(extension_addition)]
559            a7: Option<bool>,
560            #[rasn(extension_addition)]
561            a8: Option<bool>,
562            #[rasn(extension_addition)]
563            a9: Option<bool>,
564            #[rasn(extension_addition)]
565            a10: Option<bool>,
566            #[rasn(extension_addition)]
567            a11: Option<bool>,
568            #[rasn(extension_addition)]
569            a12: Option<bool>,
570            #[rasn(extension_addition)]
571            a13: Option<bool>,
572            #[rasn(extension_addition)]
573            a14: Option<bool>,
574            #[rasn(extension_addition)]
575            a15: Option<bool>,
576            #[rasn(extension_addition)]
577            a16: Option<bool>,
578            #[rasn(extension_addition)]
579            a17: Option<bool>,
580            #[rasn(extension_addition)]
581            a18: Option<bool>,
582            #[rasn(extension_addition)]
583            a19: Option<bool>,
584            #[rasn(extension_addition)]
585            a20: Option<bool>,
586            #[rasn(extension_addition)]
587            a21: Option<bool>,
588            #[rasn(extension_addition)]
589            a22: Option<bool>,
590            #[rasn(extension_addition)]
591            a23: Option<bool>,
592            #[rasn(extension_addition)]
593            a24: Option<bool>,
594            #[rasn(extension_addition)]
595            a25: Option<bool>,
596            #[rasn(extension_addition)]
597            a26: Option<bool>,
598            #[rasn(extension_addition)]
599            a27: Option<bool>,
600            #[rasn(extension_addition)]
601            a28: Option<bool>,
602            #[rasn(extension_addition)]
603            a29: Option<bool>,
604            #[rasn(extension_addition)]
605            a30: Option<bool>,
606            #[rasn(extension_addition)]
607            a31: Option<bool>,
608            #[rasn(extension_addition)]
609            a32: Option<bool>,
610            #[rasn(extension_addition)]
611            a33: Option<bool>,
612            #[rasn(extension_addition)]
613            a34: Option<bool>,
614            #[rasn(extension_addition)]
615            a35: Option<bool>,
616            #[rasn(extension_addition)]
617            a36: Option<bool>,
618            #[rasn(extension_addition)]
619            a37: Option<bool>,
620            #[rasn(extension_addition)]
621            a38: Option<bool>,
622            #[rasn(extension_addition)]
623            a39: Option<bool>,
624            #[rasn(extension_addition)]
625            a40: Option<bool>,
626            #[rasn(extension_addition)]
627            a41: Option<bool>,
628            #[rasn(extension_addition)]
629            a42: Option<bool>,
630            #[rasn(extension_addition)]
631            a43: Option<bool>,
632            #[rasn(extension_addition)]
633            a44: Option<bool>,
634            #[rasn(extension_addition)]
635            a45: Option<bool>,
636            #[rasn(extension_addition)]
637            a46: Option<bool>,
638            #[rasn(extension_addition)]
639            a47: Option<bool>,
640            #[rasn(extension_addition)]
641            a48: Option<bool>,
642            #[rasn(extension_addition)]
643            a49: Option<bool>,
644            #[rasn(extension_addition)]
645            a50: Option<bool>,
646            #[rasn(extension_addition)]
647            a51: Option<bool>,
648            #[rasn(extension_addition)]
649            a52: Option<bool>,
650            #[rasn(extension_addition)]
651            a53: Option<bool>,
652            #[rasn(extension_addition)]
653            a54: Option<bool>,
654            #[rasn(extension_addition)]
655            a55: Option<bool>,
656            #[rasn(extension_addition)]
657            a56: Option<bool>,
658            #[rasn(extension_addition)]
659            a57: Option<bool>,
660            #[rasn(extension_addition)]
661            a58: Option<bool>,
662            #[rasn(extension_addition)]
663            a59: Option<bool>,
664            #[rasn(extension_addition)]
665            a60: Option<bool>,
666            #[rasn(extension_addition)]
667            a61: Option<bool>,
668            #[rasn(extension_addition)]
669            a62: Option<bool>,
670            #[rasn(extension_addition)]
671            a63: Option<bool>,
672            #[rasn(extension_addition)]
673            a64: Option<bool>,
674            #[rasn(extension_addition)]
675            a65: Option<bool>,
676        }
677
678        // round_trip!(uper, B, B { a: 0.into() }, &[0]);
679        // round_trip!(uper, B, B { a: 1.into() }, &[0x80, 0x80, 0x80]);
680        // round_trip!(uper, C, C {a: true}, &[0x40]);
681        round_trip!(uper, D, D { a: true, b: None }, &[0x40]);
682        round_trip!(uper, I, I { a: true, b: None }, &[0x40]);
683        round_trip!(uper, J, J { a: true, b: None }, &[0x40]);
684        round_trip!(
685            uper,
686            K,
687            K {
688                a: true,
689                b: None,
690                c: None
691            },
692            &[0x40]
693        );
694        round_trip!(uper, L, L { a: true, b: None }, &[0x40]);
695        round_trip!(uper, M, M { a: true, b: None }, &[0x40]);
696        round_trip!(uper, N, N { a: true }, &[0x00]);
697        round_trip!(uper, N, N { a: false }, &[0x80]);
698        round_trip!(uper, P, P { a: None }, &[0x00]);
699        round_trip!(
700            uper,
701            G,
702            G {
703                a: true,
704                b: Some(GE { a: true }),
705                c: Some(GE { a: true }),
706                d: true
707            },
708            &[0xe0, 0x70, 0x18, 0x00, 0x18, 0x00]
709        );
710        round_trip!(
711            uper,
712            M,
713            M {
714                a: true,
715                b: Some(ME {
716                    a: Some(MESeq { a: 5.into() }),
717                    b: true
718                })
719            },
720            &[0xc0, 0x40, 0xe0, 0x20, 0xb0, 0x00]
721        );
722        round_trip!(
723            uper,
724            Q,
725            Q {
726                a: C { a: true },
727                b: 100.into()
728            },
729            &[0x40, 0x59, 0x00]
730        );
731        round_trip!(
732            uper,
733            R,
734            R {
735                a: D {
736                    a: true,
737                    b: Some(DE { a: true })
738                },
739                b: 100.into()
740            },
741            &[0xc0, 0x40, 0x60, 0x00, 0x59, 0x00]
742        );
743        round_trip!(
744            uper,
745            S,
746            S {
747                a: true,
748                b: Some(SSeq {
749                    a: true,
750                    b: Some(true)
751                })
752            },
753            &[0xc0, 0x40, 0x5c, 0x00]
754        );
755        round_trip!(
756            uper,
757            T,
758            T {
759                a: Some(vec![<_>::default()])
760            },
761            &[0x80, 0x80]
762        );
763        round_trip!(
764            uper,
765            T,
766            T {
767                a: Some(vec![T { a: Some(vec![]) }])
768            },
769            &[0x80, 0xc0, 0x00]
770        );
771        round_trip!(
772            uper,
773            V,
774            V {
775                a: Some(false),
776                ..<_>::default()
777            },
778            &[0x82, 0x80, 0x20, 0x00]
779        );
780        round_trip!(
781            uper,
782            V,
783            V {
784                b: Some(false),
785                ..<_>::default()
786            },
787            &[0x82, 0x40, 0x20, 0x00]
788        );
789        round_trip!(
790            uper,
791            V,
792            V {
793                c: Some(false),
794                ..<_>::default()
795            },
796            &[0x82, 0x20, 0x20, 0x00]
797        );
798        // round_trip!(uper, W, W { a1: Some(true), ..<_>::default() }, &[0xd0, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00]);
799    }
800
801    #[test]
802    fn extension_additions() {
803        #[derive(AsnType, Clone, Copy, Debug, Decode, Default, Encode, PartialEq)]
804        #[rasn(enumerated, crate_root = "crate")]
805        enum Urgency {
806            #[default]
807            Normal,
808            High,
809        }
810
811        #[derive(AsnType, Clone, Debug, Decode, Encode, PartialEq)]
812        #[rasn(crate_root = "crate")]
813        struct MySequenceValExtension {
814            #[rasn(value("0..254"))]
815            alternate_item_code: u8,
816            #[rasn(size("3..10"))]
817            alternate_item_name: Option<Ia5String>,
818        }
819
820        #[derive(AsnType, Clone, Debug, Decode, Encode, PartialEq)]
821        #[rasn(crate_root = "crate")]
822        #[non_exhaustive]
823        struct MySequenceVal {
824            #[rasn(value("0..254"))]
825            item_code: u8,
826            #[rasn(size("3..10"))]
827            item_name: Option<Ia5String>,
828            #[rasn(extension_addition, default)]
829            urgency: Urgency,
830            #[rasn(extension_addition_group)]
831            v2: Option<MySequenceValExtension>,
832        }
833
834        let value = MySequenceVal {
835            item_code: 29,
836            item_name: Some(Ia5String::try_from("SHERRY").unwrap()),
837            urgency: Urgency::High,
838            v2: Some(MySequenceValExtension {
839                alternate_item_code: 45,
840                alternate_item_name: Some(Ia5String::try_from("PORT").unwrap()),
841            }),
842        };
843
844        round_trip!(
845            uper,
846            MySequenceVal,
847            value,
848            &[
849                0xc7, 0x5d, 0x39, 0x11, 0x69, 0x52, 0xb2, 0x07, 0x01, 0x80, 0x05, 0x96, 0x9a, 0x13,
850                0xe9, 0x54
851            ]
852        );
853    }
854
855    #[test]
856    fn constrained_extension_addition() {
857        #[derive(AsnType, Debug, Clone, Decode, Encode, PartialEq)]
858        #[rasn(crate_root = "crate")]
859        #[non_exhaustive]
860        struct TestSequence {
861            #[rasn(size("0..=8"))]
862            hello: OctetString,
863            #[rasn(
864                extension_addition,
865                value("0..=9"),
866                default = "test_sequence_world_default"
867            )]
868            world: u8,
869        }
870
871        fn test_sequence_world_default() -> u8 {
872            8
873        }
874
875        let ext_value = TestSequence {
876            hello: bytes::Bytes::from(vec![1, 2, 3, 4]),
877            world: 4,
878        };
879
880        round_trip!(
881            uper,
882            TestSequence,
883            ext_value,
884            &[0xA0, 0x08, 0x10, 0x18, 0x20, 0x08, 0x0A, 0x00]
885        );
886    }
887
888    #[test]
889    fn recursive_types() {
890        #[derive(AsnType, Debug, Clone, Decode, Encode, PartialEq)]
891        #[rasn(crate_root = "crate")]
892        #[rasn(choice, automatic_tags)]
893        #[non_exhaustive]
894        enum TestChoice {
895            Number1(()),
896            Number2(bool),
897            Number3(Box<TopLevel>),
898        }
899
900        #[derive(AsnType, Debug, Clone, Decode, Encode, PartialEq)]
901        #[rasn(crate_root = "crate")]
902        #[rasn(automatic_tags)]
903        struct TopLevel {
904            #[rasn(value("1..=8"))]
905            pub test: u8,
906            pub choice: TestChoice,
907        }
908
909        impl TopLevel {
910            pub fn new(test: u8, choice: TestChoice) -> Self {
911                Self { test, choice }
912            }
913        }
914
915        let test_value = TopLevel::new(
916            1,
917            TestChoice::Number3(Box::new(TopLevel {
918                test: 2,
919                choice: TestChoice::Number1(()),
920            })),
921        );
922        round_trip!(uper, TopLevel, test_value, &[8, 128]);
923    }
924    #[test]
925    fn deeply_nested_choice() {
926        use crate as rasn;
927        #[derive(AsnType, Decode, Debug, Encode, PartialEq)]
928        #[rasn(choice, automatic_tags)]
929        enum Choice {
930            Normal(Integer),
931            High(Integer),
932            Medium(Integer),
933        }
934        round_trip!(
935            uper,
936            Choice,
937            Choice::Medium(333.into()),
938            &[128, 128, 83, 64]
939        );
940        #[derive(AsnType, Decode, Debug, Encode, PartialEq)]
941        #[rasn(choice, automatic_tags)]
942        enum BoolChoice {
943            A(bool),
944            B(bool),
945            C(Choice),
946        }
947        round_trip!(
948            uper,
949            BoolChoice,
950            BoolChoice::C(Choice::Normal(333.into())),
951            &[128, 32, 20, 208]
952        );
953
954        #[derive(AsnType, Decode, Debug, Encode, PartialEq)]
955        #[rasn(choice, automatic_tags)]
956        enum TripleChoice {
957            A(bool),
958            B(BoolChoice),
959        }
960        #[derive(AsnType, Decode, Debug, Encode, PartialEq)]
961        #[rasn(choice, automatic_tags)]
962        enum FourthChoice {
963            A(TripleChoice),
964            B(bool),
965        }
966        round_trip!(
967            uper,
968            TripleChoice,
969            TripleChoice::B(BoolChoice::C(Choice::Normal(333.into()))),
970            &[192, 16, 10, 104]
971        );
972        round_trip!(
973            uper,
974            FourthChoice,
975            FourthChoice::A(TripleChoice::B(BoolChoice::C(Choice::Normal(333.into())))),
976            &[96, 8, 5, 52]
977        );
978    }
979    #[test]
980    fn test_object_identifier() {
981        round_trip!(
982            uper,
983            ObjectIdentifier,
984            ObjectIdentifier::new(vec![1, 2]).unwrap(),
985            &[0x01u8, 0x2a]
986        );
987        round_trip!(
988            uper,
989            ObjectIdentifier,
990            ObjectIdentifier::new(vec![1, 2, 3321]).unwrap(),
991            &[0x03u8, 0x2a, 0x99, 0x79]
992        );
993        #[derive(AsnType, Debug, Decode, Encode, PartialEq)]
994        #[rasn(crate_root = "crate")]
995        struct B {
996            a: bool,
997            b: ObjectIdentifier,
998        }
999        round_trip!(
1000            uper,
1001            B,
1002            B {
1003                a: true,
1004                b: ObjectIdentifier::new(vec![1, 2]).unwrap()
1005            },
1006            &[0x80, 0x95, 0x00]
1007        );
1008    }
1009}