rasn 0.14.0

A safe no_std ASN.1 codec framework.
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
# Rasn
[![crates.io](https://img.shields.io/crates/d/rasn.svg)](https://crates.io/crates/rasn)
[![Help Wanted](https://img.shields.io/github/issues/XAMPPRocky/rasn/help%20wanted?color=green)](https://github.com/XAMPPRocky/rasn/issues?q=is%3Aissue+is%3Aopen+label%3A%22help+wanted%22)
[![Lines Of Code](https://tokei.rs/b1/github/XAMPPRocky/rasn?category=code)](https://github.com/XAMPPRocky/tokei)
[![Documentation](https://docs.rs/rasn/badge.svg)](https://docs.rs/rasn/)

Welcome to `rasn` (pronounced "raisin"), a safe `#[no_std]` ASN.1 codec framework.
That enables you to safely create, share, and handle ASN.1 data types from and to different encoding rules. If you are unfamiliar with ASN.1 and encoding formats like BER/DER, I would recommend reading [*"A Warm Welcome to ASN.1 and DER"*][lenc] by Let's Encrypt as a quick introduction before continuing. In short it is an "Interface Description Language" (and data model) with a set of encoding formats (called rules) for that model. It was originally designed in the late 1980s and is used throughout the industry especially in telecommunications and cryptography.

[ghs]: https://github.com/sponsors/XAMPPRocky
[lenc]: https://letsencrypt.org/docs/a-warm-welcome-to-asn1-and-der/

## Features

### Abstract Codec Data Model
There are quite a few existing ASN.1 related Rust crates already, however they are currently specific to a single format or even a single standard, this makes it hard to share and re-use standards that are specified in ASN.1. Now with `rasn`'s abstract model you can build and share ASN.1 data types as crates that work with any encoder or decoder regardless of the underlying encoding rules, whether it's BER, CER, DER, or your own custom encoding.

### `#[no_std]` Support
Rasn is entirely `#[no_std]`, so you can share the same ASN.1 implementation on any Rust target platform that can support `alloc`.

### Rich Data Types
Rasn currently has support for nearly all of ASN.1's data types. `rasn` uses popular community libraries such as `bitvec`, `bytes`, and `chrono` for some of its data types as well as providing a couple of its own. Check out the [`types`][mod:types] module for what's currently available.

[mod:types]: http://docs.rs/rasn/0.4.1/rasn/types/index.html

### Safe  Codecs
The encoder and decoder have been written in 100% safe Rust and fuzzed with [American Fuzzy Lop Plus Plus][bun] to ensure that the decoder correctly handles random input, and if valid that the encoder can correctly re-encode that value.

#### Supported Codecs

- Basic Encoding Rules (BER)
- Canonical Encoding Rules (CER)
- Distinguished Encoding Rules (DER)
- Aligned Packed Encoding Rules (APER)
- Unaligned Packed Encoding Rules (UPER)
- JSON Encoding Rules (JER)

[bun]: https://aflplus.plus

### RFC implementations
Rasn also provides implementations for a number of IETF RFCs using the `rasn`
framework for use out of the box. These crates provide strongly typed
definitions for the necessary data types. Like `rasn` they are `#[no_std]`,
as well as being transport layer and encoding rule agnostic.

- [**CMS:** Cryptographic Message Syntax](https://docs.rs/rasn-cms)
- [**Kerberos** Authentication Framework](https://docs.rs/rasn-kerberos)
- [**LDAP:** Lightweight Directory Access Protocol](https://docs.rs/rasn-ldap)
- [**MIB-II:** Management of Information Base](https://docs.rs/rasn-mib)
- [**OCSP:** Online Certificate Status Protocol](https://docs.rs/rasn-ocsp)
- [**PKIX:** Public Key Infrastructure](https://docs.rs/rasn-pkix)
- [**SMI:** Structure of Management Information](https://docs.rs/rasn-smi)
- [**SNMP:** Simple Network Management Protocol](https://docs.rs/rasn-snmp)
- [**S/MIME:** Secure/Multipurpose Internet Mail Extensions](https://docs.rs/rasn-smime)


### Powerful Derive Macros
Easily model your structs and enums with derive equivalents of all of the traits. These macros provide a automatic implementation that ensures your model is a valid ASN.1 type at *compile-time*. To explain that though, first we have to explain…

## How It Works
The codec API has been designed for ease of use, safety, and being hard to *misuse*. The most common mistakes are around handling the length and ensuring it's correctly encoded and decoded. In `rasn` this is completely abstracted away letting you focus on the abstract model. Let's look at what decoding a simple custom `SEQUENCE` type looks like.

```asn1
Person ::= SEQUENCE {
  age INTEGER,
  name UTF8String
}
```

Which we want to map to the following equivalent Rust code.

```rust
struct Person {
    age: rasn::types::Integer,
    name: String, // or rasn::types::Utf8String
}
```


### Implementing The Traits
When modelling an ASN.1 data type, there are three traits we'll need to implement. `Decode` and `Encode` for converting to and from encoding rules, and the shared `AsnType` trait; which defines some associated data needed to be given to the encoder and decoder. Currently the only thing we have define is the tag to use to identify our type.

```rust
# struct Person;
use rasn::{AsnType, Tag};

impl AsnType for Person {
    // Default tag for sequences.
    const TAG: Tag = Tag::SEQUENCE;
}
```

Next is the `Decode` and `Encode` traits. These are mirrors of each other and both have one provided method (`decode`/`encode`) and one required method (`decode_with_tag`/`encode_with_tag`). Since in ASN.1 nearly every type can be implicitly tagged allowing anyone to override the tag associated with the type, having `*_with_tag` as a required method requires the implementer to correctly handle this case, and the provided methods simply calls `*_with_tag` with the type's associated `AsnType::TAG`. Let's look at what the codec implementation of `Person` looks like.

```rust
# use rasn::{AsnType, types::{Constructed, fields::{Field, Fields}}};
# struct Person { name: Utf8String, age: Integer }
# impl AsnType for Person { const TAG: Tag = Tag::SEQUENCE; }
# impl Constructed for Person {
#     const FIELDS: Fields = Fields::from_static(&[
#          Field::new_required(Utf8String::TAG, Utf8String::TAG_TREE, "age"),
#          Field::new_required(Integer::TAG, Integer::TAG_TREE, "name"),
#     ]);
# }
use rasn::{prelude::*, types::{Integer, Utf8String}};

impl Decode for Person {
    fn decode_with_tag_and_constraints<D: Decoder>(decoder: &mut D, tag: Tag, constraints: Constraints) -> Result<Self, D::Error> {
        // Accepts a closure that decodes the contents of the sequence.
        decoder.decode_sequence(tag, None::<fn () -> Self>, |decoder| {
            let age = Integer::decode(decoder)?;
            let name = Utf8String::decode(decoder)?;
            Ok(Self { age, name })
        })
    }
}

impl Encode for Person {
    fn encode_with_tag_and_constraints<E: Encoder>(&self, encoder: &mut E, tag: Tag, constraints: Constraints) -> Result<(), E::Error> {
        // Accepts a closure that encodes the contents of the sequence.
        encoder.encode_sequence::<Self, _>(tag, |encoder| {
            self.age.encode(encoder)?;
            self.name.encode(encoder)?;
            Ok(())
        })?;

        Ok(())
    }
}
```

That's it!  We've just created a new ASN.1 that be encoded and decoded to BER, CER, and DER; and nowhere did we have to check the tag, the length, or whether the string was primitive or constructed encoded. All those nasty encoding rules details are completely abstracted away so your type only has handle how to map to and from ASN.1's data model.

With all the actual conversion code isolated to the codec implementations you can know that your model is always safe to use. The API has also been designed to prevent you from making common logic errors that can lead to invalid encoding. For example; if we look back our `Encode` implementation, and what if we forgot to use the encoder we were given in `encode_sequence` and tired to use the parent instead?

```text
error[E0501]: cannot borrow `*encoder` as mutable because previous closure requires unique access
   --> tests/derive.rs:122:9
    |
122 |           encoder.encode_sequence(tag, |sequence| {
    |           ^       ---------------      ---------- closure construction occurs here
    |           |       |
    |  _________|       first borrow later used by call
    | |
123 | |             self.age.encode(encoder)?;
    | |                             ------- first borrow occurs due to use of `encoder` in closure
124 | |             self.name.encode(sequence)?;
125 | |             Ok(())
126 | |         })?;
    | |__________^ second borrow occurs here

error[E0500]: closure requires unique access to `encoder` but it is already borrowed
   --> tests/derive.rs:122:38
    |
122 |         encoder.encode_sequence(tag, |sequence| {
    |         ------- ---------------      ^^^^^^^^^^ closure construction occurs here
    |         |       |
    |         |       first borrow later used by call
    |         borrow occurs here
123 |             self.age.encode(encoder)?;
    |                             ------- second borrow occurs due to use of `encoder` in closure

```

Our code fails to compile! Which, in this case is great, there's no chance that our contents will accidentally be encoded in the wrong sequence because we forgot to change the name of a variable. These ownership semantics also mean that an `Encoder` can't accidentally encode the contents of a sequence multiple times in their implementation.  Let's see how we can try to take this even further.

### Compile-Safe ASN.1 With Macros
So far we've shown how rasn's API takes steps to be safe and protect from accidentally creating an invalid model. However, it's often hard to cover everything in an imperative API. Something that is important to understand about ASN.1 that isn't obvious in the above examples is that; in ASN.1, all types can be identified by a tag (essentially two numbers e.g. `INTEGER`'s tag is `0, 2`). Field and variant names are not transmitted in most encoding rules, so this tag is also used to identify fields or variants in a `SEQUENCE` or `CHOICE`. This means that every that in a ASN.1 struct or enum every field and variant  **must have** a distinct tag for the whole type to be considered valid. For example ; If we changed `age` in `Person` to be a `String` like below it would be invalid ASN.1 even though it compiles and runs correctly, we have to either use a different type or override `age`'s tag to be distinct from `name`'s. When implementing the `AsnType` trait yourself this requirement must checked by manually, however as we'll see you generally won't need to do that.

Included with rasn is a set of derive macros that enable you to have your ASN.1 model implementation implemented declaratively. The `Encode` and `Decode` macros will essentially auto-generate the implementations we showed earlier, but the real magic is the `AsnType` derive macro. Thanks to the `static-assertations` crate and recent developments in `const fn`; the `AsnType` derive will not only generate your `AsnType` implementation, it will also generate a check that asserts that every field or variant has a distinct tag at *compile-time*. This means now if for some reason we made a change to one of the types in person, we don't have re-check that our model is still valid, the compiler takes care of that for us.

```no_compile
// Invalid
#[derive(rasn::AsnType)]
struct Person {
    age: Option<String>,
    name: Option<String>,
}
```

We'll now get the following error trying to compile the above definition.

```text
error[E0080]: evaluation of constant value failed
   --> tests/derive.rs:146:10
    |
146 | #[derive(rasn::AsnType)]
    |          ^^^^^^^^^^^^^ the evaluated program panicked at 'Person's fields is not a valid order of ASN.1 tags, ensure that your field's tags and OPTIONAL
s are correct.', tests/derive.rs:146:10
    |
    = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info)
```

Validating your model at compile-time enables you to work on ASN.1 code without fear that you're unintentionally changing something in the background. I bet you're wondering now though, how we are supposed to have a struct with two strings for fields? The answer is thankfully pretty simple, you just add `#[rasn(tag)]` attribute to override the tags of one or more of the types. However we can actually go further, because in ASN.1 there's the concept of having `AUTOMATIC TAGS` which essentially tells your ASN.1 compiler to automatically generate distinct tags for your ASN.1 definition. Now with rasn you can do that in Rust! Applying `#[rasn(automatic_tags)]` to the container  automatically generate tags will apply the same automatic tagging transformation you'd expect from an ASN.1 compiler.

```rust
use rasn::AsnType;

// Valid
#[derive(AsnType)]
struct Person {
    #[rasn(tag(context, 0))] // or just #[rasn(tag(0))]
    age: Option<String>,
    name: Option<String>,
}

// Also valid
#[derive(AsnType)]
#[rasn(automatic_tags)]
struct Person2 {
    age: Option<String>,
    name: Option<String>,
}
```

## Reference
The following table provides a range of examples showing how to declare data types with `rasn`.

<table>
<tr>
<td></td> <td> ASN1 </td> <td> rasn </td>
</tr>
<tr>
<td>Type alias</td>
<td>

```asn
Test-type-b ::= BOOLEAN
Test-type-a ::= Test-type-b
```

</td>
<td>

```rust
// either
use rasn::prelude::*;

type TestTypeB = bool;

type TestTypeA = TestTypeB;
```
```rust
// or 
use rasn::prelude::*;

#[derive(AsnType, Decode, Encode)]
#[rasn(delegate)]
struct TestTypeB(pub bool);

/// or
#[derive(AsnType, Decode, Encode)]
#[rasn(delegate)]
struct TestTypeA(pub TestTypeB);
```

</td>
</tr>
<tr>
<td>BOOLEAN type</td>
<td>

```asn
Test-type-a ::= BOOLEAN
```

</td>
<td>

```rust
// either
use rasn::prelude::*;

#[derive(AsnType, Decode, Encode)]
#[rasn(delegate)]
struct TestTypeA(pub bool);
```
```rust
// or
use rasn::prelude::*;

type TestTypeA = bool;
```
</td>
</tr>
<tr>
<td>NULL type</td>
<td>

```asn
Test-type-a ::= NULL
```

</td>
<td>

```rust
// either
use rasn::prelude::*;
#[derive(AsnType, Decode, Encode)]
struct TestTypeA;
```
```rust
// or
use rasn::prelude::*;
#[derive(AsnType, Decode, Encode)]
#[rasn(delegate)]
struct TestTypeA(());
```
```rust
// or
use rasn::prelude::*;

type TestTypeA = ();
```

</td>
</tr>
<tr>
<td>INTEGER type</td>
<td>

```asn
Test-type-a ::= INTEGER
```

</td>
<td>

```rust
use rasn::prelude::*;
// either
#[derive(AsnType, Decode, Encode)]
#[rasn(delegate)]
struct TestTypeA(pub u8 /* or any other rust integer type */);
```
```rust
// or
use rasn::prelude::*;
#[derive(AsnType, Decode, Encode)]
#[rasn(delegate)]
struct TestTypeA(pub Integer);
```
```rust
// or
use rasn::prelude::*;
type TestTypeA = Integer;
```
```rust
// or
use rasn::prelude::*;
type TestTypeA = u8; // or any other rust integer type
```

</td>
</tr>
<tr>
<td>Single-value contraint</td>
<td>

```asn
Test-type-a ::= INTEGER (8)
```

</td>
<td>

```rust
// either
use rasn::prelude::*;
#[derive(AsnType, Decode, Encode)]
#[rasn(delegate, value("8"))]
struct TestTypeA(pub u8);
```
```rust
// or
use rasn::prelude::*;
#[derive(AsnType, Decode, Encode)]
#[rasn(delegate, value("8"))]
struct TestTypeA(pub Integer);
```

</td>
</tr>
<tr>
<td>Value range constraint</td>
<td>

```asn
Test-type-a ::= INTEGER (-8..360)
Test-type-b ::= INTEGER (MIN..360)
Test-type-c ::= INTEGER (42..MAX)
```

</td>
<td>

```rust
use rasn::prelude::*;
/// of course a primitive rust integer would still work in these examples
#[derive(AsnType, Decode, Encode)]
#[rasn(delegate, value("-8..=360"))]
struct TestTypeA(pub Integer);

#[derive(AsnType, Decode, Encode)]
#[rasn(delegate, value("..=360"))]
struct TestTypeB(pub Integer);

#[derive(AsnType, Decode, Encode)]
#[rasn(delegate, value("42..="))]
struct TestTypeC(pub Integer);
```

</td>
</tr>
<td>Extensible value constraint</td>
<td>

```asn
Test-type-a ::= INTEGER (42,...)
Test-type-b ::= INTEGER (1..360,...)
```

</td>
<td>

```rust
use rasn::prelude::*;
/// of course a primitive rust integer would still work in these examples
#[derive(AsnType, Decode, Encode)]
#[rasn(delegate, value("42", extensible))]
struct TestTypeA(pub Integer);

#[derive(AsnType, Decode, Encode)]
#[rasn(delegate, value("1..=360", extensible))]
struct TestTypeB(pub Integer);
```

</td>
</tr>
<tr>
<td>ENUMERATED type</td>
<td>

```asn
Test-type-a ::= ENUMERATED { seed, grape, raisin }
```

</td>
<td>

```rust
use rasn::prelude::*;
#[derive(AsnType, Decode, Encode, Copy, Clone, PartialEq, Debug)]
#[rasn(enumerated, automatic_tags)] /// See below
enum TestTypeA {
    Seed,
    Grape,
    Raisin
}
```

</td>
</tr>
<tr>
<td>Extensible ENUMERATED type</td>
<td>

```asn
Test-type-a ::= ENUMERATED { seed, grape, ..., raisin }
```

</td>
<td>

```rust
use rasn::prelude::*;
#[derive(AsnType, Decode, Encode, Copy, Clone, PartialEq, Debug)]
#[rasn(enumerated, automatic_tags)] /// See below
#[non_exhaustive]
enum TestTypeA {
    Seed,
    Grape,
    #[rasn(extension_addition)]
    Raisin
}
```

</td>
</tr>
<tr>
<td>AUTOMATIC TAGS environment</td>
<td>

```asn
TestModule DEFINITIONS AUTOMATIC TAGS ::=
BEGIN
Test-type-a ::= ENUMERATED { seed, grape, raisin }
Test-type-b ::= ENUMERATED { juice, wine, grappa }
END
```

</td>
<td>

```rust
use rasn::prelude::*;
/// The tagging encironment has to be declared for every rasn-annotated struct or enum
/// There is no implicit extensibility
#[derive(AsnType, Decode, Encode, Copy, Clone, PartialEq, Debug)]
#[rasn(enumerated, automatic_tags)]
enum TestTypeB {
    Juice,
    Wine,
    Grappa
}

#[derive(AsnType, Decode, Encode, Copy, Clone, PartialEq, Debug)]
#[rasn(enumerated, automatic_tags)]
enum TestTypeA {
    Seed,
    Grape,
    Raisin
}
```

</td>
</tr>
<tr>
<td>EXPLICIT TAGS environment</td>
<td>

```asn
TestModule DEFINITIONS EXPLICIT TAGS ::=
BEGIN
Test-type-a ::= [APPLICATION 1] ENUMERATED { seed, grape, raisin }
Test-type-b ::= [APPLICATION 2] ENUMERATED { juice, wine, grappa }
END
```

</td>
<td>

```rust
use rasn::prelude::*;
/// The tagging encironment has to be declared for every rasn-annotated struct or enum
/// There is no implicit extensibility
#[derive(AsnType, Decode, Encode, Copy, Clone, PartialEq, Debug)]
#[rasn(enumerated, tag(explicit(application, 1)))]
enum TestTypeB {
    #[rasn(tag(explicit(0)))]
    Juice,
    #[rasn(tag(explicit(1)))]
    Wine,
    #[rasn(tag(explicit(2)))]
    Grappa
}

#[derive(AsnType, Decode, Encode, Copy, Clone, PartialEq, Debug)]
#[rasn(enumerated, tag(explicit(application, 2)))]
enum TestTypeA {
    #[rasn(tag(explicit(0)))]
    Seed,
    #[rasn(tag(explicit(1)))]
    Grape,
    #[rasn(tag(explicit(2)))]
    Raisin
}
```

</td>
</tr>
<tr>
<td>IMPLICIT TAGS environment</td>
<td>

```asn
TestModule DEFINITIONS IMPLICIT TAGS ::=
BEGIN
Test-type-a ::= [APPLICATION 1] ENUMERATED { seed, grape, raisin }
Test-type-b ::= [APPLICATION 2] ENUMERATED { juice, wine, grappa }
END
```

</td>
<td>

```rust
use rasn::prelude::*;
/// The tagging encironment has to be declared for every rasn-annotated struct or enum
/// There is no implicit extensibility
#[derive(AsnType, Decode, Encode, Copy, Clone, PartialEq, Debug)]
#[rasn(enumerated, tag(application, 1))]
enum TestTypeB {
    Juice = 0,
    Wine = 1,
    Grappa = 2
}

#[derive(AsnType, Decode, Encode, Copy, Clone, PartialEq, Debug)]
#[rasn(enumerated, tag(application, 2))]
enum TestTypeA {
    Seed = 0,
    Grape = 1,
    Raisin = 2
}
```

</td>
</tr>
<tr>
<td>CHOICE type</td>
<td>

```asn
Test-type-a ::= CHOICE {
    seed BOOLEAN,
    grape BIT STRING SIZE(1,...),
    raisin OCTET STRING
}

Test-type-b ::= CHOICE { 
    juice INTEGER (0..3,...), 
    wine OCTET STRING,
    ...,
    grappa INTEGER 
}
```

</td>
<td>

```rust
use rasn::prelude::*;
#[derive(AsnType, Decode, Encode)]
#[rasn(choice, automatic_tags)]
enum TestTypeA {
    Seed(bool),
    #[rasn(size("1", extensible))]
    Grape(BitString),
    Raisin(OctetString)
}

#[derive(AsnType, Decode, Encode)]
#[rasn(choice, automatic_tags)]
#[non_exhaustive]
enum TestTypeB {
    #[rasn(value("0..3", extensible))]
    Juice(Integer),
    Wine(OctetString),
    #[rasn(extension_addition)]
    Grappa(Integer)
}

```

</td>
</tr>
<tr>
<td>SEQUENCE type</td>
<td>

```asn
Test-type-a ::= SEQUENCE { 
    juice INTEGER (0..3,...), 
    wine OCTET STRING,
    ...,
    grappa INTEGER OPTIONAL,
    water BIT STRING (SIZE(1)) OPTIONAL
}
```

</td>
<td>

```rust
use rasn::prelude::*;
#[derive(AsnType, Decode, Encode)]
#[rasn(automatic_tags)]
#[non_exhaustive]
struct TestTypeA {
    #[rasn(value("0..3", extensible))]
    juice: Integer,
    wine: OctetString,
    #[rasn(extension_addition)]
    grappa: Option<Integer>,
    #[rasn(extension_addition, size("1"))]
    water: Option<BitString>
}

```

</td>
</tr>
<tr>
<td>SET type</td>
<td>

```asn
Test-type-a ::= SET { 
    seed NULL,
    grape BOOLEAN,
    raisin INTEGER
}
```

</td>
<td>

```rust
use rasn::prelude::*;
/// the SET declaration is basically identical to a SEQUENCE declaration, 
/// except for the `set` annotation
#[derive(AsnType, Decode, Encode)]
#[rasn(set, automatic_tags)]
struct TestTypeA {
    seed: (),
    grape: bool,
    raisin: Integer
}

```

</td>
</tr>
<tr>
<td>Renaming fields</td>
<td>

```asn
Test-type-a ::= SEQUENCE { 
    notQuiteRustCase INTEGER
}
```

</td>
<td>

```rust
use rasn::prelude::*;

#[derive(AsnType, Decode, Encode)]
#[rasn(automatic_tags, identifier = "Test-type-a")]
struct TestTypeA {
    #[rasn(identifier = "notQuiteRustCase")]
    rust_case_indeed: Integer
}

```

</td>
</tr>
<tr>
<td>OPTIONAL and DEFAULT fields</td>
<td>

```asn
Test-type-a ::= SEQUENCE { 
    seed BOOLEAN DEFAULT TRUE,
    grape INTEGER OPTIONAL,
    raisin INTEGER DEFAULT 1
}
```

</td>
<td>

```rust
use rasn::prelude::*;
/// DEFAULTs are provided via linked helper functions
#[derive(AsnType, Decode, Encode)]
#[rasn(automatic_tags)]
struct TestTypeA {
    #[rasn(default = "default_seed")] 
    seed: bool,
    grape: Option<Integer>,
    #[rasn(default = "default_raisin")]
    raisin: Integer
}

fn default_seed() -> bool {
    true
}

fn default_raisin() -> Integer {
    1.into()
}
```

</td>
</tr>
<tr>
<td>SEQUENCE OF type</td>
<td>

```asn
Test-type-a ::= SEQUENCE OF BOOLEAN
Test-type-b ::= SEQUENCE OF INTEGER(1,...)
```

</td>
<td>

```rust
use rasn::prelude::*;
#[derive(AsnType, Decode, Encode)]
#[rasn(delegate)]
struct TestTypeA(pub SequenceOf<bool>);

/// Constrained inner primitive types need to be wrapped in a helper newtype
#[derive(AsnType, Decode, Encode)]
#[rasn(delegate, value("1", extensible))]
struct InnerTestTypeB(pub Integer);

#[derive(AsnType, Decode, Encode)]
#[rasn(delegate)]
struct TestTypeB(pub SequenceOf<InnerTestTypeB>);
```

</td>
</tr>
<tr>
<td>Character string types</td>
<td>

```asn
Test-type-a ::= UTF8String
```

</td>
<td>

```rust
use rasn::prelude::*;
/// the other charater types supported by rasn behave exactly the same:
/// NumericString, VisibleString, Ia5String, TeletexString, GeneralString, BmpString, PrintableString
/// (and also for BIT STRING and OCTET STRING)
#[derive(AsnType, Decode, Encode)]
#[rasn(delegate)]
struct TestTypeA(pub Utf8String);
```

</td>
</tr>
<tr>
<td>BIT STRING type</td>
<td>

```asn
Test-type-a ::= BIT STRING
```

</td>
<td>

```rust
use rasn::prelude::*;
#[derive(AsnType, Decode, Encode)]
#[rasn(delegate)]
struct TestTypeA(pub BitString);
```

</td>
</tr>
<tr>
<td>OCTET STRING type</td>
<td>

```asn
Test-type-a ::= OCTET STRING
```

</td>
<td>

```rust
use rasn::prelude::*;
#[derive(AsnType, Decode, Encode)]
#[rasn(delegate)]
struct TestTypeA(pub OctetString);
```

</td>
</tr>
<tr>
<td>Size contraint</td>
<td>

```asn
Test-type-a ::= UTF8String (SIZE (42,...))
Test-type-b ::= SEQUENCE (SIZE (1..8)) OF BOOLEAN
```

</td>
<td>

```rust
use rasn::prelude::*;
/// The size constraint definition behaves similar to the value definition (see above)
#[derive(AsnType, Decode, Encode)]
#[rasn(delegate, size("42", extensible))]
struct TestTypeA(pub Utf8String);

#[derive(AsnType, Decode, Encode)]
#[rasn(delegate, size("1..=8"))]
struct TestTypeB(pub SequenceOf<bool>);
```

</td>
</tr>
<tr>
<td>Permitted alphabet contraint</td>
<td>

```asn
Test-type-a ::= UTF8String (FROM ("A".."Z"))
```

</td>
<td>

```rust
use rasn::prelude::*;
#[derive(AsnType, Decode, Encode)]
#[rasn(delegate, from("\u{0041}..\u{005A}"))]
struct TestTypeA(pub Utf8String);
```

</td>
</tr>
</table>

## Sponsorship
This project was funded through the [NGI Assure Fund](https://nlnet.nl/project/RASN), a fund established by NLnet with financial support from the European Commission's Next Generation Internet programme, under the aegis of DG Communications Networks, Content and Technology under grant agreement No 957073.

## Disclaimer
The software is provided "as is" and the authors disclaim all warranties with regard to this software including all implied warranties of merchant-ability and fitness. In no event shall the authors be liable for any special, direct, indirect, or consequential damages or any damages whatsoever resulting from loss of use, data or profits, whether in an action of contract, negligence or other tortuous action, arising out of or in connection with the use or performance of this software.