{"id":17604289,"url":"https://github.com/librasn/rasn","last_synced_at":"2026-04-15T11:04:14.917Z","repository":{"id":37963779,"uuid":"292537885","full_name":"librasn/rasn","owner":"librasn","description":"A Safe #[no_std] ASN.1 Codec Framework","archived":false,"fork":false,"pushed_at":"2026-03-10T18:43:19.000Z","size":2603,"stargazers_count":353,"open_issues_count":41,"forks_count":74,"subscribers_count":6,"default_branch":"main","last_synced_at":"2026-03-11T00:21:48.613Z","etag":null,"topics":["aper","asn","asn1","ber","cer","codec","coer","der","encoding-formats","encoding-rules","jer","oer","parser","rust","uper"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/librasn.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":".github/FUNDING.yml","license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null},"funding":{"github":["XAMPPRocky"]}},"created_at":"2020-09-03T10:27:52.000Z","updated_at":"2026-03-10T18:41:11.000Z","dependencies_parsed_at":"2023-11-10T19:24:08.018Z","dependency_job_id":"869c8c0c-fa11-4482-9032-443e348d2c05","html_url":"https://github.com/librasn/rasn","commit_stats":{"total_commits":342,"total_committers":33,"mean_commits":"10.363636363636363","dds":0.4444444444444444,"last_synced_commit":"33d22a67479182c96228259a92789190e0ec5c6e"},"previous_names":["librasn/rasn","xampprocky/rasn"],"tags_count":1199,"template":false,"template_full_name":null,"purl":"pkg:github/librasn/rasn","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/librasn%2Frasn","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/librasn%2Frasn/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/librasn%2Frasn/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/librasn%2Frasn/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/librasn","download_url":"https://codeload.github.com/librasn/rasn/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/librasn%2Frasn/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30370267,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-10T21:41:54.280Z","status":"online","status_checked_at":"2026-03-11T02:00:07.027Z","response_time":84,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["aper","asn","asn1","ber","cer","codec","coer","der","encoding-formats","encoding-rules","jer","oer","parser","rust","uper"],"created_at":"2024-10-22T14:08:34.729Z","updated_at":"2026-03-11T10:01:23.195Z","avatar_url":"https://github.com/librasn.png","language":"Rust","readme":"# Rasn\n[![crates.io](https://img.shields.io/crates/d/rasn.svg)](https://crates.io/crates/rasn)\n[![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)\n[![Documentation](https://docs.rs/rasn/badge.svg)](https://docs.rs/rasn/)\n[![Benchmarks](https://img.shields.io/badge/bencher-benchmarks-orange?link=https%3A%2F%2Fbencher.dev%2Fconsole%2Fprojects%2Frasn%2Fperf)](https://bencher.dev/perf/rasn/plots)\n\nWelcome to `rasn` (pronounced \"raisin\"), a safe `#[no_std]` ASN.1 codec framework.\nThat 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.\n\nThe [`rasn` compiler][compiler] can be used to generate `rasn` bindings for ASN.1 modules.\n\n[ghs]: https://github.com/sponsors/XAMPPRocky\n[lenc]: https://letsencrypt.org/docs/a-warm-welcome-to-asn1-and-der/\n[compiler]: https://github.com/librasn/compiler\n\n## Features\n\n### Abstract Codec Data Model\nThere 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.\n\n### `#[no_std]` Support\nRasn is entirely `#[no_std]`, so you can share the same ASN.1 implementation on any Rust target platform that can support `alloc`.\n\n### Rich Data Types\nRasn 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.\n\n[mod:types]: https://docs.rs/rasn/latest/rasn/types/index.html\n\n### Safe  Codecs\nThe 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.\n\n#### Supported Codecs\n\n- Basic Encoding Rules (BER)\n- Canonical Encoding Rules (CER)\n- Distinguished Encoding Rules (DER)\n- Aligned Packed Encoding Rules (APER)\n- Unaligned Packed Encoding Rules (UPER)\n- JSON Encoding Rules (JER)\n- Octet Encoding Rules (OER)\n- Canonical Octet Encoding Rules (COER)\n- XML Encoding Rules (XER)\n\n[bun]: https://aflplus.plus\n\n### RFC implementations\nRasn also provides implementations for a number of IETF RFCs using the `rasn`\nframework for use out of the box. These crates provide strongly typed\ndefinitions for the necessary data types. Like `rasn` they are `#[no_std]`,\nas well as being transport layer and encoding rule agnostic.\n\n- [**CMS:** Cryptographic Message Syntax](https://docs.rs/rasn-cms)\n- [**Kerberos** Authentication Framework](https://docs.rs/rasn-kerberos)\n- [**LDAP:** Lightweight Directory Access Protocol](https://docs.rs/rasn-ldap)\n- [**MIB-II:** Management of Information Base](https://docs.rs/rasn-mib)\n- [**OCSP:** Online Certificate Status Protocol](https://docs.rs/rasn-ocsp)\n- [**PKIX:** Public Key Infrastructure](https://docs.rs/rasn-pkix)\n- [**SMI:** Structure of Management Information](https://docs.rs/rasn-smi)\n- [**SNMP:** Simple Network Management Protocol](https://docs.rs/rasn-snmp)\n- [**S/MIME:** Secure/Multipurpose Internet Mail Extensions](https://docs.rs/rasn-smime)\n\n\n#### C-ITS Standards\n\n- [**IEEE 1609.2:** IEEE Standard for Wireless Access in Vehicular Environments (WAVE) - Security Services for Application and Management Messages ](standards/its/src/ieee1609dot2/)\n- [**ETSI TS 103 097:** Intelligent Transport Systems (ITS) - Security header and certificate formats](standards/its/src/ts103097/)\n\n\n### Powerful Derive Macros\nEasily 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…\n\n## How It Works\nThe 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.\n\n```asn1\nPerson ::= SEQUENCE {\n  age INTEGER,\n  name UTF8String\n}\n```\n\nWhich we want to map to the following equivalent Rust code.\n\n```rust\nstruct Person {\n    age: rasn::types::Integer,\n    name: String, // or rasn::types::Utf8String\n}\n```\n\n\n### Implementing The Traits\nWhen 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.\n\n```rust\n# struct Person;\nuse rasn::{AsnType, types::Tag};\n\nimpl AsnType for Person {\n    // Default tag for sequences.\n    const TAG: Tag = Tag::SEQUENCE;\n}\n```\n\nNext 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.\n\n```rust\n# use rasn::{AsnType, types::{Constructed, fields::{Field, Fields}}};\n# struct Person { name: Utf8String, age: Integer }\n# impl AsnType for Person {\n#    const TAG: Tag = Tag::SEQUENCE;\n#    const IDENTIFIER: Identifier = Identifier(Some(\"Person\"));\n# }\n# impl Constructed\u003c2, 0\u003e for Person {\n#     const FIELDS: Fields\u003c2\u003e = Fields::from_static([\n#          Field::new_required(0, Utf8String::TAG, Utf8String::TAG_TREE, \"age\"),\n#          Field::new_required(1, Integer::TAG, Integer::TAG_TREE, \"name\"),\n#     ]);\n# }\nuse rasn::{prelude::*, types::{Integer, Utf8String}};\n\nimpl Decode for Person {\n    fn decode_with_tag_and_constraints\u003cD: Decoder\u003e(decoder: \u0026mut D, tag: Tag, constraints: Constraints) -\u003e Result\u003cSelf, D::Error\u003e {\n        // Accepts a closure that decodes the contents of the sequence.\n        decoder.decode_sequence(tag, None::\u003cfn () -\u003e Self\u003e, |decoder| {\n            let age = Integer::decode(decoder)?;\n            let name = Utf8String::decode(decoder)?;\n            Ok(Self { age, name })\n        })\n    }\n}\n\nimpl Encode for Person {\n    fn encode_with_tag_and_constraints\u003c'encoder, E: Encoder\u003c'encoder\u003e\u003e(\u0026self, encoder: \u0026mut E, tag: Tag, constraints: Constraints, identifier: Identifier) -\u003e Result\u003c(), E::Error\u003e {\n        // Accepts a closure that encodes the contents of the sequence.\n        encoder.encode_sequence::\u003c2, 0, Self, _\u003e(tag, |encoder| {\n            self.age.encode(encoder)?;\n            self.name.encode(encoder)?;\n            Ok(())\n        }, identifier)?;\n\n        Ok(())\n    }\n}\n```\n\nThat's it!  We've just created a new ASN.1 that can 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.\n\nWith 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 at our `Encode` implementation, what if we forgot to use the encoder we were given in `encode_sequence` and tried to use the parent instead?\n\n```text\nerror[E0501]: cannot borrow `*encoder` as mutable because previous closure requires unique access\n   --\u003e tests/derive.rs:122:9\n    |\n122 |           encoder.encode_sequence(tag, |sequence| {\n    |           ^       ---------------      ---------- closure construction occurs here\n    |           |       |\n    |  _________|       first borrow later used by call\n    | |\n123 | |             self.age.encode(encoder)?;\n    | |                             ------- first borrow occurs due to use of `encoder` in closure\n124 | |             self.name.encode(sequence)?;\n125 | |             Ok(())\n126 | |         })?;\n    | |__________^ second borrow occurs here\n\nerror[E0500]: closure requires unique access to `encoder` but it is already borrowed\n   --\u003e tests/derive.rs:122:38\n    |\n122 |         encoder.encode_sequence(tag, |sequence| {\n    |         ------- ---------------      ^^^^^^^^^^ closure construction occurs here\n    |         |       |\n    |         |       first borrow later used by call\n    |         borrow occurs here\n123 |             self.age.encode(encoder)?;\n    |                             ------- second borrow occurs due to use of `encoder` in closure\n\n```\n\nOur 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.\n\n### Compile-Safe ASN.1 With Macros\nSo 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 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 be checked manually, however as we'll see you generally won't need to do that.\n\nIncluded 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.\n\n```no_compile\n// Invalid\n#[derive(rasn::AsnType)]\nstruct Person {\n    age: Option\u003cString\u003e,\n    name: Option\u003cString\u003e,\n}\n```\n\nWe'll now get the following error trying to compile the above definition.\n\n```text\nerror[E0080]: evaluation of constant value failed\n   --\u003e tests/derive.rs:146:10\n    |\n146 | #[derive(rasn::AsnType)]\n    |          ^^^^^^^^^^^^^ 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\ns are correct.', tests/derive.rs:146:10\n    |\n    = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info)\n```\n\nValidating 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 will apply the same automatic tagging transformation you'd expect from an ASN.1 compiler.\n\n```rust\nuse rasn::AsnType;\n\n// Valid\n#[derive(AsnType)]\nstruct Person {\n    #[rasn(tag(context, 0))] // or just #[rasn(tag(0))]\n    age: Option\u003cString\u003e,\n    name: Option\u003cString\u003e,\n}\n\n// Also valid\n#[derive(AsnType)]\n#[rasn(automatic_tags)]\nstruct Person2 {\n    age: Option\u003cString\u003e,\n    name: Option\u003cString\u003e,\n}\n```\n\n## Reference\nThe following table provides a range of examples showing how to declare data types with `rasn`.\n\n\u003ctable\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003c/td\u003e \u003ctd\u003e ASN1 \u003c/td\u003e \u003ctd\u003e rasn \u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eType alias\u003c/td\u003e\n\u003ctd\u003e\n\n```asn\nTest-type-b ::= BOOLEAN\nTest-type-a ::= Test-type-b\n```\n\n\u003c/td\u003e\n\u003ctd\u003e\n\n```rust\n// either\nuse rasn::prelude::*;\n\ntype TestTypeB = bool;\n\ntype TestTypeA = TestTypeB;\n```\n```rust\n// or\nuse rasn::prelude::*;\n\n#[derive(AsnType, Decode, Encode)]\n#[rasn(delegate)]\nstruct TestTypeB(pub bool);\n\n/// or\n#[derive(AsnType, Decode, Encode)]\n#[rasn(delegate)]\nstruct TestTypeA(pub TestTypeB);\n```\n\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eBOOLEAN type\u003c/td\u003e\n\u003ctd\u003e\n\n```asn\nTest-type-a ::= BOOLEAN\n```\n\n\u003c/td\u003e\n\u003ctd\u003e\n\n```rust\n// either\nuse rasn::prelude::*;\n\n#[derive(AsnType, Decode, Encode)]\n#[rasn(delegate)]\nstruct TestTypeA(pub bool);\n```\n```rust\n// or\nuse rasn::prelude::*;\n\ntype TestTypeA = bool;\n```\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eNULL type\u003c/td\u003e\n\u003ctd\u003e\n\n```asn\nTest-type-a ::= NULL\n```\n\n\u003c/td\u003e\n\u003ctd\u003e\n\n```rust\n// either\nuse rasn::prelude::*;\n#[derive(AsnType, Decode, Encode)]\nstruct TestTypeA;\n```\n```rust\n// or\nuse rasn::prelude::*;\n#[derive(AsnType, Decode, Encode)]\n#[rasn(delegate)]\nstruct TestTypeA(());\n```\n```rust\n// or\nuse rasn::prelude::*;\n\ntype TestTypeA = ();\n```\n\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eINTEGER type\u003c/td\u003e\n\u003ctd\u003e\n\n```asn\nTest-type-a ::= INTEGER\n```\n\n\u003c/td\u003e\n\u003ctd\u003e\n\n```rust\nuse rasn::prelude::*;\n// either\n#[derive(AsnType, Decode, Encode)]\n#[rasn(delegate)]\nstruct TestTypeA(pub u8 /* or any other rust integer type */);\n```\n```rust\n// or\nuse rasn::prelude::*;\n#[derive(AsnType, Decode, Encode)]\n#[rasn(delegate)]\nstruct TestTypeA(pub Integer);\n```\n```rust\n// or\nuse rasn::prelude::*;\ntype TestTypeA = Integer;\n```\n```rust\n// or\nuse rasn::prelude::*;\ntype TestTypeA = u8; // or any other rust integer type\n```\n\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eSingle-value contraint\u003c/td\u003e\n\u003ctd\u003e\n\n```asn\nTest-type-a ::= INTEGER (8)\n```\n\n\u003c/td\u003e\n\u003ctd\u003e\n\n```rust\n// either\nuse rasn::prelude::*;\n#[derive(AsnType, Decode, Encode)]\n#[rasn(delegate, value(\"8\"))]\nstruct TestTypeA(pub u8);\n```\n```rust\n// or\nuse rasn::prelude::*;\n#[derive(AsnType, Decode, Encode)]\n#[rasn(delegate, value(\"8\"))]\nstruct TestTypeA(pub Integer);\n```\n\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eValue range constraint\u003c/td\u003e\n\u003ctd\u003e\n\n```asn\nTest-type-a ::= INTEGER (-8..360)\nTest-type-b ::= INTEGER (MIN..360)\nTest-type-c ::= INTEGER (42..MAX)\n```\n\n\u003c/td\u003e\n\u003ctd\u003e\n\n```rust\nuse rasn::prelude::*;\n/// of course a primitive rust integer would still work in these examples\n#[derive(AsnType, Decode, Encode)]\n#[rasn(delegate, value(\"-8..=360\"))]\nstruct TestTypeA(pub Integer);\n\n#[derive(AsnType, Decode, Encode)]\n#[rasn(delegate, value(\"..=360\"))]\nstruct TestTypeB(pub Integer);\n\n#[derive(AsnType, Decode, Encode)]\n#[rasn(delegate, value(\"42..=\"))]\nstruct TestTypeC(pub Integer);\n```\n\n\u003c/td\u003e\n\u003c/tr\u003e\n\n\u003ctr\u003e\n\u003ctd\u003eExtensible value constraint\u003c/td\u003e\n\u003ctd\u003e\n\n```asn\nTest-type-a ::= INTEGER (42,...)\nTest-type-b ::= INTEGER (1..360,...)\n```\n\n\u003c/td\u003e\n\u003ctd\u003e\n\n```rust\nuse rasn::prelude::*;\n/// of course a primitive rust integer would still work in these examples\n#[derive(AsnType, Decode, Encode)]\n#[rasn(delegate, value(\"42\", extensible))]\nstruct TestTypeA(pub Integer);\n\n#[derive(AsnType, Decode, Encode)]\n#[rasn(delegate, value(\"1..=360\", extensible))]\nstruct TestTypeB(pub Integer);\n```\n\n\u003c/td\u003e\n\u003c/tr\u003e\n\n\u003ctr\u003e\n\u003ctd\u003eENUMERATED type\u003c/td\u003e\n\u003ctd\u003e\n\n```asn\nTest-type-a ::= ENUMERATED { seed, grape, raisin }\n```\n\n\u003c/td\u003e\n\u003ctd\u003e\n\n```rust\nuse rasn::prelude::*;\n#[derive(AsnType, Decode, Encode, Copy, Clone, PartialEq, Debug)]\n#[rasn(enumerated, automatic_tags)] /// See below\nenum TestTypeA {\n    Seed,\n    Grape,\n    Raisin\n}\n```\n\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eExtensible ENUMERATED type\u003c/td\u003e\n\u003ctd\u003e\n\n```asn\nTest-type-a ::= ENUMERATED { seed, grape, ..., raisin }\n```\n\n\u003c/td\u003e\n\u003ctd\u003e\n\n```rust\nuse rasn::prelude::*;\n#[derive(AsnType, Decode, Encode, Copy, Clone, PartialEq, Debug)]\n#[rasn(enumerated, automatic_tags)] /// See below\n#[non_exhaustive]\nenum TestTypeA {\n    Seed,\n    Grape,\n    #[rasn(extension_addition)]\n    Raisin\n}\n```\n\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eAUTOMATIC TAGS environment\u003c/td\u003e\n\u003ctd\u003e\n\n```asn\nTestModule DEFINITIONS AUTOMATIC TAGS ::=\nBEGIN\nTest-type-a ::= ENUMERATED { seed, grape, raisin }\nTest-type-b ::= ENUMERATED { juice, wine, grappa }\nEND\n```\n\n\u003c/td\u003e\n\u003ctd\u003e\n\n```rust\nuse rasn::prelude::*;\n/// The tagging encironment has to be declared for every rasn-annotated struct or enum\n/// There is no implicit extensibility\n#[derive(AsnType, Decode, Encode, Copy, Clone, PartialEq, Debug)]\n#[rasn(enumerated, automatic_tags)]\nenum TestTypeB {\n    Juice,\n    Wine,\n    Grappa\n}\n\n#[derive(AsnType, Decode, Encode, Copy, Clone, PartialEq, Debug)]\n#[rasn(enumerated, automatic_tags)]\nenum TestTypeA {\n    Seed,\n    Grape,\n    Raisin\n}\n```\n\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eEXPLICIT TAGS environment\u003c/td\u003e\n\u003ctd\u003e\n\n```asn\nTestModule DEFINITIONS EXPLICIT TAGS ::=\nBEGIN\nTest-type-a ::= [APPLICATION 1] ENUMERATED { seed, grape, raisin }\nTest-type-b ::= [APPLICATION 2] ENUMERATED { juice, wine, grappa }\nEND\n```\n\n\u003c/td\u003e\n\u003ctd\u003e\n\n```rust\nuse rasn::prelude::*;\n/// The tagging encironment has to be declared for every rasn-annotated struct or enum\n/// There is no implicit extensibility\n#[derive(AsnType, Decode, Encode, Copy, Clone, PartialEq, Debug)]\n#[rasn(enumerated, tag(explicit(application, 1)))]\nenum TestTypeB {\n    #[rasn(tag(explicit(0)))]\n    Juice,\n    #[rasn(tag(explicit(1)))]\n    Wine,\n    #[rasn(tag(explicit(2)))]\n    Grappa\n}\n\n#[derive(AsnType, Decode, Encode, Copy, Clone, PartialEq, Debug)]\n#[rasn(enumerated, tag(explicit(application, 2)))]\nenum TestTypeA {\n    #[rasn(tag(explicit(0)))]\n    Seed,\n    #[rasn(tag(explicit(1)))]\n    Grape,\n    #[rasn(tag(explicit(2)))]\n    Raisin\n}\n```\n\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eIMPLICIT TAGS environment\u003c/td\u003e\n\u003ctd\u003e\n\n```asn\nTestModule DEFINITIONS IMPLICIT TAGS ::=\nBEGIN\nTest-type-a ::= [APPLICATION 1] ENUMERATED { seed, grape, raisin }\nTest-type-b ::= [APPLICATION 2] ENUMERATED { juice, wine, grappa }\nEND\n```\n\n\u003c/td\u003e\n\u003ctd\u003e\n\n```rust\nuse rasn::prelude::*;\n/// The tagging encironment has to be declared for every rasn-annotated struct or enum\n/// There is no implicit extensibility\n#[derive(AsnType, Decode, Encode, Copy, Clone, PartialEq, Debug)]\n#[rasn(enumerated, tag(application, 1))]\nenum TestTypeB {\n    Juice = 0,\n    Wine = 1,\n    Grappa = 2\n}\n\n#[derive(AsnType, Decode, Encode, Copy, Clone, PartialEq, Debug)]\n#[rasn(enumerated, tag(application, 2))]\nenum TestTypeA {\n    Seed = 0,\n    Grape = 1,\n    Raisin = 2\n}\n```\n\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eCHOICE type\u003c/td\u003e\n\u003ctd\u003e\n\n```asn\nTest-type-a ::= CHOICE {\n    seed BOOLEAN,\n    grape BIT STRING SIZE(1,...),\n    raisin OCTET STRING\n}\n\nTest-type-b ::= CHOICE {\n    juice INTEGER (0..3,...),\n    wine OCTET STRING,\n    ...,\n    grappa INTEGER\n}\n```\n\n\u003c/td\u003e\n\u003ctd\u003e\n\n```rust\nuse rasn::prelude::*;\n#[derive(AsnType, Decode, Encode)]\n#[rasn(choice, automatic_tags)]\nenum TestTypeA {\n    Seed(bool),\n    #[rasn(size(\"1\", extensible))]\n    Grape(BitString),\n    Raisin(OctetString)\n}\n\n#[derive(AsnType, Decode, Encode)]\n#[rasn(choice, automatic_tags)]\n#[non_exhaustive]\nenum TestTypeB {\n    #[rasn(value(\"0..3\", extensible))]\n    Juice(Integer),\n    Wine(OctetString),\n    #[rasn(extension_addition)]\n    Grappa(Integer)\n}\n\n```\n\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eSEQUENCE type\u003c/td\u003e\n\u003ctd\u003e\n\n```asn\nTest-type-a ::= SEQUENCE {\n    juice INTEGER (0..3,...),\n    wine OCTET STRING,\n    ...,\n    grappa INTEGER OPTIONAL,\n    water BIT STRING (SIZE(1)) OPTIONAL\n}\n```\n\n\u003c/td\u003e\n\u003ctd\u003e\n\n```rust\nuse rasn::prelude::*;\n#[derive(AsnType, Decode, Encode)]\n#[rasn(automatic_tags)]\n#[non_exhaustive]\nstruct TestTypeA {\n    #[rasn(value(\"0..3\", extensible))]\n    juice: Integer,\n    wine: OctetString,\n    #[rasn(extension_addition)]\n    grappa: Option\u003cInteger\u003e,\n    #[rasn(extension_addition, size(\"1\"))]\n    water: Option\u003cBitString\u003e\n}\n\n```\n\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eSET type\u003c/td\u003e\n\u003ctd\u003e\n\n```asn\nTest-type-a ::= SET {\n    seed NULL,\n    grape BOOLEAN,\n    raisin INTEGER\n}\n```\n\n\u003c/td\u003e\n\u003ctd\u003e\n\n```rust\nuse rasn::prelude::*;\n/// the SET declaration is basically identical to a SEQUENCE declaration,\n/// except for the `set` annotation\n#[derive(AsnType, Decode, Encode)]\n#[rasn(set, automatic_tags)]\nstruct TestTypeA {\n    seed: (),\n    grape: bool,\n    raisin: Integer\n}\n\n```\n\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eRenaming fields\u003c/td\u003e\n\u003ctd\u003e\n\n```asn\nTest-type-a ::= SEQUENCE {\n    notQuiteRustCase INTEGER\n}\n```\n\n\u003c/td\u003e\n\u003ctd\u003e\n\n```rust\nuse rasn::prelude::*;\n\n#[derive(AsnType, Decode, Encode)]\n#[rasn(automatic_tags, identifier = \"Test-type-a\")]\nstruct TestTypeA {\n    #[rasn(identifier = \"notQuiteRustCase\")]\n    rust_case_indeed: Integer\n}\n\n```\n\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eOPTIONAL and DEFAULT fields\u003c/td\u003e\n\u003ctd\u003e\n\n```asn\nTest-type-a ::= SEQUENCE {\n    seed BOOLEAN DEFAULT TRUE,\n    grape INTEGER OPTIONAL,\n    raisin INTEGER DEFAULT 1\n}\n```\n\n\u003c/td\u003e\n\u003ctd\u003e\n\n```rust\nuse rasn::prelude::*;\n/// DEFAULTs are provided via linked helper functions\n#[derive(AsnType, Decode, Encode)]\n#[rasn(automatic_tags)]\nstruct TestTypeA {\n    #[rasn(default = \"default_seed\")]\n    seed: bool,\n    grape: Option\u003cInteger\u003e,\n    #[rasn(default = \"default_raisin\")]\n    raisin: Integer\n}\n\nfn default_seed() -\u003e bool {\n    true\n}\n\nfn default_raisin() -\u003e Integer {\n    1.into()\n}\n```\n\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eSEQUENCE OF type\u003c/td\u003e\n\u003ctd\u003e\n\n```asn\nTest-type-a ::= SEQUENCE OF BOOLEAN\nTest-type-b ::= SEQUENCE OF INTEGER(1,...)\n```\n\n\u003c/td\u003e\n\u003ctd\u003e\n\n```rust\nuse rasn::prelude::*;\n#[derive(AsnType, Decode, Encode)]\n#[rasn(delegate)]\nstruct TestTypeA(pub SequenceOf\u003cbool\u003e);\n\n/// Constrained inner primitive types need to be wrapped in a helper newtype\n#[derive(AsnType, Decode, Encode)]\n#[rasn(delegate, value(\"1\", extensible))]\nstruct InnerTestTypeB(pub Integer);\n\n#[derive(AsnType, Decode, Encode)]\n#[rasn(delegate)]\nstruct TestTypeB(pub SequenceOf\u003cInnerTestTypeB\u003e);\n```\n\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eCharacter string types\u003c/td\u003e\n\u003ctd\u003e\n\n```asn\nTest-type-a ::= UTF8String\n```\n\n\u003c/td\u003e\n\u003ctd\u003e\n\n```rust\nuse rasn::prelude::*;\n/// the other charater types supported by rasn behave exactly the same:\n/// NumericString, VisibleString, Ia5String, TeletexString, GeneralString, BmpString, PrintableString\n/// (and also for BIT STRING and OCTET STRING)\n#[derive(AsnType, Decode, Encode)]\n#[rasn(delegate)]\nstruct TestTypeA(pub Utf8String);\n```\n\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eBIT STRING type\u003c/td\u003e\n\u003ctd\u003e\n\n```asn\nTest-type-a ::= BIT STRING\n```\n\n\u003c/td\u003e\n\u003ctd\u003e\n\n```rust\nuse rasn::prelude::*;\n#[derive(AsnType, Decode, Encode)]\n#[rasn(delegate)]\nstruct TestTypeA(pub BitString);\n```\n\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eOCTET STRING type\u003c/td\u003e\n\u003ctd\u003e\n\n```asn\nTest-type-a ::= OCTET STRING\n```\n\n\u003c/td\u003e\n\u003ctd\u003e\n\n```rust\nuse rasn::prelude::*;\n#[derive(AsnType, Decode, Encode)]\n#[rasn(delegate)]\nstruct TestTypeA(pub OctetString);\n```\n\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eSize contraint\u003c/td\u003e\n\u003ctd\u003e\n\n```asn\nTest-type-a ::= UTF8String (SIZE (42,...))\nTest-type-b ::= SEQUENCE (SIZE (1..8)) OF BOOLEAN\n```\n\n\u003c/td\u003e\n\u003ctd\u003e\n\n```rust\nuse rasn::prelude::*;\n/// The size constraint definition behaves similar to the value definition (see above)\n#[derive(AsnType, Decode, Encode)]\n#[rasn(delegate, size(\"42\", extensible))]\nstruct TestTypeA(pub Utf8String);\n\n#[derive(AsnType, Decode, Encode)]\n#[rasn(delegate, size(\"1..=8\"))]\nstruct TestTypeB(pub SequenceOf\u003cbool\u003e);\n```\n\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003ePermitted alphabet contraint\u003c/td\u003e\n\u003ctd\u003e\n\n```asn\nTest-type-a ::= UTF8String (FROM (\"A\"..\"Z\"))\n```\n\n\u003c/td\u003e\n\u003ctd\u003e\n\n```rust\nuse rasn::prelude::*;\n#[derive(AsnType, Decode, Encode)]\n#[rasn(delegate, from(\"\\u{0041}..\\u{005A}\"))]\nstruct TestTypeA(pub Utf8String);\n```\n\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/table\u003e\n\n## Sponsorship\nThis 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.\n\nOctet Encoding Rules (OER/COER) were added as part of the [RE-ROUTE project](https://reroute-project.eu/), which received funding from the European Union’s Horizon Europe Marie Skłodowska-Curie Actions (MSCA), Staff Exchanges under grant agreement No 101086343.\n\n## Disclaimer\nThe 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.\n","funding_links":["https://github.com/sponsors/XAMPPRocky"],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flibrasn%2Frasn","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flibrasn%2Frasn","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flibrasn%2Frasn/lists"}