{"id":17604547,"url":"https://github.com/6d7a/asnr","last_synced_at":"2025-03-29T22:26:28.446Z","repository":{"id":166849602,"uuid":"639874521","full_name":"6d7a/asnr","owner":"6d7a","description":"ASN1 Compiler for Rust","archived":false,"fork":false,"pushed_at":"2023-11-14T07:27:49.000Z","size":738,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-02-04T23:57:34.173Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/6d7a.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"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}},"created_at":"2023-05-12T12:27:15.000Z","updated_at":"2023-05-18T12:46:15.000Z","dependencies_parsed_at":"2023-11-14T08:31:09.624Z","dependency_job_id":"956e103b-866b-4bfd-9be9-69c1610743d5","html_url":"https://github.com/6d7a/asnr","commit_stats":null,"previous_names":["6d7a/asnr"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/6d7a%2Fasnr","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/6d7a%2Fasnr/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/6d7a%2Fasnr/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/6d7a%2Fasnr/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/6d7a","download_url":"https://codeload.github.com/6d7a/asnr/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246251899,"owners_count":20747646,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":[],"created_at":"2024-10-22T14:09:59.329Z","updated_at":"2025-03-29T22:26:28.415Z","avatar_url":"https://github.com/6d7a.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# ASNR\r\nASNR - an ASN1 compiler for Rust that makes your skin tingle.\r\n\r\n### Motivation\r\n\r\nI've been using the excellent [asn1c](https://github.com/vlm/asn1c) with [a thin Rust wrapper](https://sjames.github.io/articles/2020-04-26-rust-ffi-asn1-codec/) parser in various situations. Unfortunately, on WebAssembly targets, this set-up becomes close to impossible to handle. Since there is not much out there in terms of ASN1 compilers for Rust and because I always enjoy a good read of [John Larmouth's beloved classic](https://www.oss.com/asn1/resources/books-whitepapers-pubs/larmouth-asn1-book.pdf), I started this project.\r\n\r\n# ASNR Compiler\r\nThe ASNR compiler is a parser combinator that parses ASN1 specifications and outputs encoding-rule-agnotic rust representations of the ASN1 data elements. ASNR heavily relies on the great library [nom](https://docs.rs/nom/latest/nom/) for its basic parsers. It is designed to be \r\nencoding-rule-agnostic, so that its output can be used regardless whether the actual encoding follows\r\nBER, DER, CER, PER, XER, or whatever exotic *ERs still out there.\r\n\r\n## Example\r\nIn order to compile ASN1 in your build process, invoke the ASNR compiler in your [`build.rs` build script](https://doc.rust-lang.org/cargo/reference/build-scripts.html).\r\n```rust\r\n// build.rs build script\r\nuse std::path::PathBuf;\r\nuse asnr_compiler::Asnr;\r\n\r\nfn main() {\r\n  // Initialize the compiler\r\n  match Asnr::new()\r\n    // add a single ASN1 source file\r\n    .add_asn_by_path(PathBuf::from(\"spec_1.asn\"))\r\n    // add several ASN1 source files\r\n    .add_asn_sources_by_path(vec![\r\n        PathBuf::from(\"spec_2.asn\"),\r\n        PathBuf::from(\"spec_3.asn\"),\r\n    ].iter())\r\n    // set an output path for the generated rust code\r\n    .set_output_path(PathBuf::from(\"./asn/generated.rs\"))\r\n    // you may also compile literal ASN1 snippets\r\n    .add_asn_literal(\"My-test-integer ::= INTEGER (1..128)\")\r\n    // optionally choose to support `no_std`\r\n    .no_std(true)\r\n    .compile() {\r\n    Ok(warnings /* Vec\u003cBox\u003cdyn Error\u003e\u003e */) =\u003e { /* handle compilation warnings */ }\r\n    Err(error /* Box\u003cdyn Error\u003e */) =\u003e { /* handle unrecoverable compilation error */ }\r\n  }\r\n}\r\n```\r\n\r\nSee also the `asnr-compiler-derive` crate, that provides shorthand macros for inline ASN1 support.\r\n```rust\r\nuse asnr_compiler_derive::asn1;\r\n\r\nasn1! { \r\n  r#\"\r\n    HashAlgorithm ::= ENUMERATED { \r\n      sha256,\r\n      ...,\r\n      sha384\r\n    }\r\n  \"#\r\n}\r\n```\r\n\r\n# ASNR Transcoder\r\nThe transcoder crate handles the actual encoding and decoding of data at runtime.\r\nIt aims to be suitable for `no_std` environments and `wasm-unknown` targets.\r\nFor a start, the asnr transcoder will provide support for UPER encoding rules, \r\nbut transcoding can be easily customized by implementing the crate's `Encoder` and `Decoder` traits.\r\n\r\nThe ASNR transcoder de- and encodes messages by composing functions that handle the\r\nde-/encoding of generic ASN1 types like SEQUENCEs or INTEGERs. In the current implementation,\r\nthat choice has led to a lot of boxing and unboxing, but I hope to find a more efficient solution\r\nin the future. The advantage of this design is that authors of custom encoders and decoders have\r\npretty much all of the information concerning the data element as it's specified in an \r\nASN1 specification, including constraints, even comments up to a certain degree. \r\n\r\n## Usage\r\nLet's consider the following ASN1 Sequence:\r\n```asn1\r\nExampleSequence ::= SEQUENCE {\r\n  member-1 IA5String (SIZE (1..24)),\r\n  member-2 INTEGER (0..15),\r\n  ...,\r\n  extension BOOLEAN OPTIONAL\r\n}\r\n```\r\n\r\n```rust\r\nuse asnr_transcoder::uper::Uper;\r\n/// import your generated ASN1 representations\r\nuse my_asn_spec::*;\r\n\r\nfn decode_example_sequence(binary: \u0026[u8]) -\u003e ExampleSequence {\r\n  Uper::decode(binary).unwrap()\r\n}\r\n\r\nfn encode_example_sequence() -\u003e Vec\u003cu8\u003e {\r\n  let example_sequence = ExampleSequence {\r\n    // ASN1-built-in types are represented as new types within SEQUENCEs\r\n    member_1: InnerExampleSequenceMember1(\"Hello, World!\".into()),\r\n    member_2: InnerExampleSequenceMember2(8),\r\n    extension: None\r\n  };\r\n  Uper::encode(example_sequence).unwrap()\r\n}\r\n```","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2F6d7a%2Fasnr","html_url":"https://awesome.ecosyste.ms/projects/github.com%2F6d7a%2Fasnr","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2F6d7a%2Fasnr/lists"}