synta-codegen
Table of Contents generated with DocToc
- Overview
- Features
- Quick Start
- Example
- Multi-File Projects
- Documentation
- Supported ASN.1 Constructs
- synta-codegen vs. Manual Implementation
- Real-World Support
- Development
- Contributing
- Current Limitations
- Optional Features
- See Also
- License
ASN.1 schema parser and Rust/C code generator for the synta library with full X.680 constraint support.
Overview
synta-codegen parses ASN.1 module definitions (.asn1 files) and generates type-safe, validated Rust code or C code using the synta library. It supports ITU-T X.680 constraints and generates validated newtypes with runtime checks, eliminating the need to manually write encoding/decoding implementations.
Target Languages
- Rust (default): Generates type-safe Rust code with derive macros and validation
- C: Generates C header files with struct definitions and encoder/decoder functions using the libcsynta C API
Features
Language & output targets
- Multi-Language Support - Generate Rust or C code from the same ASN.1 schema
- Owned or Zero-Copy String Types -
StringTypeMode::BorrowedemitsOctetStringRef<'a>,BitStringRef<'a>,Utf8StringRef<'a>, etc. for zero-allocation parse-only workloads (Rust) - Idiomatic Code - PascalCase types, snake_case fields, proper conventions
Type system & constraints
- X.680 Constraint Support - Full support for value ranges, size constraints, permitted alphabet, and more
- ANY Type Support - Support for legacy ANY and ANY DEFINED BY types
- Validated Newtypes - Generates type-safe wrappers with runtime validation (Rust)
- DEFAULT Values - Automatic Default trait implementation (Rust)
- Named Value Constants - Generate constants for INTEGER named values
- Subtype Definitions - Support for type references with additional constraints
- PATTERN Regex Validation - Optional regex validation with
regexfeature flag (Rust only) - CONTAINING Validation - Optional runtime validation of encoded types with
validate_containingfeature (Rust only)
Module system
- IMPORTS/EXPORTS - Full module dependency support with topological ordering
- Multi-File Projects - Automatic cross-module use statement generation (Rust) and multi-file output via
--output-dir - Circular Import Detection - Detects and reports import cycles before code generation (
--check-imports)
C build integration
- Build System Integration - Generate
CMakeLists.txt(--cmake) ormeson.build(--meson) for C projects - C Helper Functions -
_init,_validate, and_printhelpers for every C type (--with-helpers)
Implementation quality
- Zero Dependencies - No external crates required for code generation
See ../docs/asn1-support.md for the complete ASN.1 support matrix.
Quick Start
Installation
Or add to your Cargo.toml:
[]
= "0.1"
Basic Usage
Command Line (Rust):
Command Line (C):
# Single-file: generate header, then implementation
# With helper functions (_init, _validate, _print)
# Multi-file: headers and implementations together
# Generate CMake or Meson build files (single-file)
Library (owned types, default):
use ;
let schema = r#"
MyModule DEFINITIONS ::= BEGIN
Person ::= SEQUENCE {
name UTF8String,
age INTEGER (0..150)
}
END
"#;
let module = parse?;
let code = generate?;
Library (zero-copy borrowed types, parse-only workloads):
use ;
let module = parse?;
let config = CodeGenConfig ;
// Emits Utf8StringRef<'a> instead of Utf8String, struct gains <'a> lifetime
let code = generate_with_config?;
C Code Generation:
use ;
let schema = "...";
let module = parse?;
let c_code = generate_c?;
See ../docs/api-reference.md for the complete CLI and library API reference, ../docs/rust-generation.md for Rust code generation details, and ../docs/c-generation.md for C code generation and the libcsynta API.
Example
Input ASN.1:
Types DEFINITIONS ::= BEGIN
Percentage ::= INTEGER (0..100)
Protocol ::= INTEGER {tcp(6), udp(17), sctp(132)}
User ::= SEQUENCE {
name IA5String (SIZE (1..64)),
age Percentage,
email IA5String OPTIONAL
}
END
Generated Rust:
/// INTEGER (0..100)
;
pub type Protocol = Integer;
Usage:
let user = User ;
// Validation at compile time and runtime
let invalid = new; // Err("must be in range 0..100")
Multi-File Projects
synta-codegen supports automatic cross-module use statement generation and multi-file output:
# Rust: generate with crate-relative imports
# C: generate headers only into a directory (default)
# C: generate both headers and implementations
# C: generate build file + all C sources in one invocation
# Validate imports without generating code
Generated Rust use statements:
use crate;
See ../docs/rust-generation.md for the complete multi-module build.rs guide.
Documentation
ASN.1 Reference
- ASN.1 Support - What ASN.1 syntax is supported and what is not; complete support matrix
Language-Specific Generation
- Rust Generation - Type mappings, naming, constraint validation, build.rs integration
- C Generation - Type mappings, libcsynta API reference, memory contract, arena mode
Getting Started
- Tutorial - Step-by-step guide from basics to real-world examples
- API Reference - Complete CLI options, examples, and library API
Reference
- Limitations - Unsupported constructs and workarounds
- Troubleshooting - Common issues and solutions
Supported ASN.1 Constructs
Type Definitions
- SEQUENCE, SET, CHOICE
- SEQUENCE OF, SET OF
- All primitive types (INTEGER, BOOLEAN, OCTET STRING, etc.)
X.680 Constraints
- Value ranges:
INTEGER (0..100) - Size constraints:
IA5String (SIZE (1..64)) - Permitted alphabet:
IA5String (FROM ("0".."9")) - PATTERN constraints:
IA5String (PATTERN "[0-9]+")(with optionalregexfeature) - CONTAINING constraints:
OCTET STRING (CONTAINING Certificate)(with optionalvalidate_containingfeature) - Combined constraints:
IA5String (SIZE (4..6) FROM ("0".."9")) - Union, intersection, complement
- Inner type constraints
Field Modifiers
- OPTIONAL fields
- DEFAULT values
- Tagged fields ([0] EXPLICIT, [1] IMPLICIT)
Module Features
- IMPORTS and EXPORTS
- Type references
- Nested definitions
See ../docs/asn1-support.md for the complete support matrix.
synta-codegen vs. Manual Implementation
| Aspect | Manual | synta-codegen |
|---|---|---|
| Type definitions | Manual struct definitions | Auto-generated |
| Constraint validation | Manual checks in constructors | Auto-generated from schema |
| OPTIONAL fields | Manual Option handling | Auto-generated |
| DEFAULT values | Manual Default impl | Auto-generated |
| Type references | Manual imports | Auto-generated use statements |
| Maintenance | Update code when schema changes | Regenerate |
Real-World Support
synta-codegen can parse and generate code for:
- X.509 certificates (PKIX schemas), including SET OF RDN fields with correct 0x31 tag
- X.509 Certificate Revocation Lists (CRL, RFC 5280)
- PKCS#10 Certificate Signing Requests (CSR, RFC 2986)
- OCSP request/response (RFC 6960)
- RFC 3279 algorithm parameter types (DSA/DH domain params, ECDSA signature values, EC domain params)
- RFC 5755 Attribute Certificates (AC v2:
AttributeCertificate,Holder,AttCertIssuer, etc.) - RFC 4211 Certificate Request Message Format (CRMF:
CertTemplate,ProofOfPossession,PKIArchiveOptions, etc.) - RFC 9810 Certificate Management Protocol v3 (CMP:
PKIMessage,PKIHeader,PKIBody, etc.) - PKCS#7 / CMS (RFC 5652), PKCS#8 (RFC 5958), PKCS#9 (RFC 2985), PKCS#12 (RFC 7292)
- Kerberos V5 (RFC 4120), SPNEGO (RFC 4178), FAST (RFC 6113)
- Merkle Tree Certificates (draft-ietf-tls-merkle-tree-certs)
- LDAP directory schemas
- SNMP management information bases
- 5G/LTE protocol specifications
- Custom ASN.1 schemas
IMPLICIT-tagged CHOICE variants
When a CHOICE variant is annotated with #[asn1(tag(N, implicit))], the codegen
selects the correct decode path based on whether the inner type has a lifetime
parameter:
- Owned types (no lifetime): uses
ImplicitTag<T>as before - Borrowed types (lifetime
'a): reads the context tag + length and calls<T as DecodeImplicit>::decode_implicit(content_bytes, encoding)directly, avoiding thefor<'b> Decode<'b>HRTB that borrowed types cannot satisfy
This is transparent to schema authors: write [N] IMPLICIT SomeType in the schema
and the codegen picks the right path automatically.
Note: IMPLICIT tagging of a CHOICE inner type is prohibited by ASN.1 (CHOICE has
no single tag to replace). If the inner type of a variant is itself a CHOICE, use
EXPLICIT tagging: [N] EXPLICIT ChoiceType. The codegen emits EXPLICIT when the
inner type is a CHOICE or a type alias for one.
Development
Run tests:
Build the CLI:
Contributing
Contributions are welcome! Please see the main synta repository for contribution guidelines.
Current Limitations
- Table constraints and information objects not yet implemented
- Some X.680 advanced features not yet supported
See ../docs/limitations.md for details and workarounds.
Optional Features
Regex Validation for PATTERN Constraints
To enable runtime regex validation for PATTERN constraints, add the regex feature when using the generated code:
[]
= { = "0.1", = ["regex"] }
= "1.10"
= "1.19"
Example:
Email ::= IA5String (PATTERN "[a-z]+@[a-z]+\\.com")
Generated code (with regex feature):
// Static regex pattern compiled once
static PATTERN_0: = new;
Without the regex feature, the generated code includes a comment noting that pattern validation is disabled.
Runtime Validation for CONTAINING Constraints
To enable runtime validation for CONTAINING constraints, add the validate_containing feature when using the generated code:
[]
= { = "0.1", = ["validate_containing"] }
Example:
EncodedCertificate ::= OCTET STRING (CONTAINING Certificate)
Generated code (with validate_containing feature):
Without the validate_containing feature, the generated code includes a comment noting that CONTAINING validation is disabled. This allows for zero-overhead when validation is not needed.
See Also
- synta - The main ASN.1 encoding/decoding library
- synta-derive - Derive macros for ASN.1 types
- ITU-T X.680 - ASN.1 specification
- ITU-T X.690 - BER/DER/CER encoding rules
License
Licensed under either of:
- Apache License, Version 2.0 (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0)
- MIT license (LICENSE-MIT or http://opensource.org/licenses/MIT)
at your option.