1use crate::types::Constraints;
8
9pub use super::per::*;
10
11pub fn decode<T: crate::Decode>(input: &[u8]) -> Result<T, crate::error::DecodeError> {
13 crate::per::decode(de::DecoderOptions::unaligned(), input)
14}
15
16pub 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
23pub 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
31pub 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 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, 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, 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 }
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}