asn1rs - ASN.1 Compiler for Rust
This crate generates Rust Code and optionally compatible Protobuf and SQL schema files from ASN.1 definitions.
Basic support for serde integration is provided.
The crate can be used as standalone CLI binary or used as library through its API
(for example inside the build.rs script).
Support Table
| Feature | Parses | UPER | Protobuf | PSQL | Async PSQL | UPER Legacy |
|---|---|---|---|---|---|---|
SEQUENCE |
✔️ yes | ✔️ yes | ✔️ yes | ✔️ yes | ✔️ yes | ✔️ yes |
| ...extensible | ✔️ yes | ✔️ yes | 🆗 ignored | 🆗 ignored | 🆗 ignored | 🔶 not serialized |
SEQUENCE OF |
✔️ yes | ✔️ yes | ✔️ yes | ✔️ yes | ✔️ yes | ✔️ yes |
...SIZE(A..B) |
✔️ yes | ✔️ yes | 🆗 ignored | 🆗 ignored | 🆗 ignored | ⚠️ ignored️ |
...SIZE(A..B,...) |
✔️ yes | ✔️ yes | 🆗 ignored | 🆗 ignored | 🆗 ignored | ⚠️ ignored️ |
ENUMERATED |
✔️ yes | ✔️ yes | ✔️ yes | ✔️ yes | ✔️ yes | ✔️ yes |
| ...extensible | ✔️ yes | ✔️ yes | 🆗 ignored | 🆗 ignored | 🆗 ignored | 🔶 not serialized |
CHOICE |
✔️ yes | ✔️ yes | ✔️ yes | ✔️ yes | ✔️ yes | ✔️ yes |
| ...extensible | ✔️ yes | ✔️ yes | 🆗 ignored | 🆗 ignored | 🆗 ignored | 🔶 not serialized |
BIT STRING |
✔️ yes | ✔️ yes | ✔️ yes(1) | ✔️ yes(1) | ✔️ yes(1) | ✔️ yes |
...SIZE(A..B) |
✔️ yes | ✔️ yes | 🆗 ignored | 🆗 ignored | 🆗 ignored | ⚠️ ignored |
...SIZE(A..B,...) |
✔️ yes | ✔️ yes | 🆗 ignored | 🆗 ignored | 🆗 ignored | ⚠️ ignored |
OCTET STRING |
✔️ yes | ✔️ yes | ✔️ yes | ✔️ yes | ✔️ yes | ✔️ yes |
...SIZE(A..B) |
✔️ yes | ✔️ yes | 🆗 ignored | 🆗 ignored | 🆗 ignored | ⚠️ ignored |
...SIZE(A..B,...) |
✔️ yes | ✔️ yes | 🆗 ignored | 🆗 ignored | 🆗 ignored | ⚠️ ignored |
UTF8String |
✔️ yes | ✔️ yes | ✔️ yes | ✔️ yes | ✔️ yes | ✔️ yes |
...SIZE(A..B) |
✔️ yes | ✔️ yes | 🆗 ignored | 🆗 ignored | 🆗 ignored | ⚠️ ignored |
...SIZE(A..B,...) |
✔️ yes | ✔️ yes | 🆗 ignored | 🆗 ignored | 🆗 ignored | ⚠️ ignored |
IA5String |
✔️ yes | ✔️ yes | ✔️ yes(1) | ✔️ yes(1) | ✔️ yes(1) | ❌ ub |
...SIZE(A..B) |
✔️ yes | ✔️ yes | 🆗 ignored | 🆗 ignored | 🆗 ignored | ❌ ub |
...SIZE(A..B,...) |
✔️ yes | ✔️ yes | 🆗 ignored | 🆗 ignored | 🆗 ignored | ❌ ub |
INTEGER |
✔️ yes | ✔️ yes | ✔️ yes | ✔️ yes | ✔️ yes | ✔️ yes |
...A..B |
✔️ yes | ✔️ yes | ✔️ yes(2) | ✔️ yes(2) | ✔️ yes(2) | ✔️ yes |
...A..B,... |
✔️ yes | ✔️ yes | ✔️ yes(2) | ✔️ yes(2) | ✔️ yes(2) | ⚠️ ignored |
BOOLEAN |
✔️ yes | ✔️ yes | ✔️ yes | ✔️ yes | ✔️ yes | ✔️ yes |
OPTIONAL |
✔️ yes | ✔️ yes | ✔️ yes | ✔️ yes | ✔️ yes | ✔️ yes |
IMPORTS..FROM..; |
✔️ yes | |||||
ObjectIdentifiers |
✔️ yes |
- ✔️ yes: according to specification
- ✔️ yes(1): different representation
- ✔️ yes(2): as close as possible to the original specification (sometimes yes, sometimes yes(1))
- 🔶 not serialized: values are not serialized or deserialized in this case, might break compatibility
- ⚠️ ignored️: constraint is ignored, this most likely breaks compatibility
- 🆗 ignored: constraint is ignored but it does not break compatibility
- ❌ ub: undefined behavior - whatever seems reasonable to prevent compiler errors and somehow transmit the value
- 🟥 error: fails to compile / translate
Supported standards
itu-t(0) identified-organization(4) etsi(0) itsDomain(5) wg1(1) ts(102894) cdd(2) version(1)(ITS-Container)itu-t(0) identified-organization(4) etsi(0) itsDomain(5) wg1(1) en(302637) cam(2) version(1)(CAM-PDU-Descriptions)
CLI usage
It is always helpful to check asn1rs --help in advance.
The basic usage can be seen blow:
asn1rs -t rust directory/for/rust/files some.asn1 messages.asn1
asn1rs -t proto directory/for/protobuf/files some.asn1 messages.asn1
asn1rs -t sql directory/for/sql/schema/files some.asn1 messages.asn1
API usage
The following example generates Rust, Protobuf and SQL files for all .asn1-files in the asn/ directory of the project.
While the generated Rust code is written to the src/ directory, the Protobuf files are written to proto/ and the SQL files are written to sql/ .
Additionally, in this example each generated Rust-Type also receives Serialize and Deserialize derive directives (#[derive(Serialize, Deserialize)]) for automatic serde integration.
File build.rs:
extern crate asn1rs;
use fs;
use convert_to_proto;
use convert_to_rust;
use convert_to_sql;
use RustCodeGenerator;
Inlining ASN.1 with procedural macros
Useful for tests or very small definitions. See tests/ for more examples.
use BitBuffer;
use asn_to_rust;
asn_to_rust!;
Example ASN.1-Definition to Rust, Protobuf and SQL
Input input.asn1
MyMessages DEFINITIONS AUTOMATIC TAGS ::=
BEGIN
Header ::= SEQUENCE {
timestamp INTEGER (0..1209600000)
}
END
Output my_messages.rs:
use *;
// Serialize and deserialize functions for ASN.1 UPER
// Serialize and deserialize functions for protobuf
// Insert and query functions for PostgreSQL
Output my_messages.proto:
syntax = 'proto3';
package my.messages;
message Header {
uint32 timestamp = 1;
}
Output my_messages.sql:
IF EXISTS Header CASCADE;
(
id SERIAL PRIMARY KEY,
timestamp INTEGER NOT NULL
);
Example usage of async postgres
NOTE: This requires the async-psql feature.
Using async postgres allows the message - or the batched messages - to take advantage of pipelining automatically.
This can provide a speedup (personal experience: at around 26%) compared to the synchronous/blocking postgres implementation.
use *;
use NoTls;
async
Good to know
The module asn1rs::io exposes (de-)serializers and helpers for direct usage without ASN.1 definitons:
use *;
use BitBuffer;
let mut buffer = default;
buffer.write_bit.unwrap;
buffer.write_utf8_string.unwrap;
send_to_another_host:
use *;
let mut buffer = Vecdefault;
buffer.write_varint.unwrap;
buffer.write_string.unwrap;
send_to_another_host:
TODO
Things to do at some point in time (PRs are welcome)
- generate a proper module hierarchy from the modules' object-identifier
- remove legacy rust+uper code generator (probably in 0.3)
- support
#![no_std] - refactor / clean-up (rust) code-generators