synta 0.1.11

ASN.1 parser, decoder, and encoder library with DER/BER support and C FFI
Documentation
# Code Generation Overview

`synta-codegen` transforms ASN.1 module definitions into Rust source code.
It can be used as a command-line tool or as a Rust library in `build.rs`.

```mermaid
flowchart LR
    S[("schema.asn1")]
    P("parse()")
    A["Module AST"]
    G("generate_with_config()")
    R[("OUT_DIR/<br/>generated_types.rs")]
    M("include!()")
    L[("src/lib.rs")]

    S --> P --> A --> G --> R --> M --> L

    C{{"CodeGenConfig<br/>import style · StringTypeMode<br/>DeriveMode"}}
    C -.->|shapes output| G
```

## Quick start: CLI

Generate Rust from an ASN.1 schema file:

```sh
synta-codegen --lang rust schema.asn1 -o src/generated.rs
```

`--lang rust` is the default and may be omitted.

Generate into a directory (one file per ASN.1 module):

```sh
synta-codegen schema.asn1 --output-dir src/gen/
```

## Quick start: Library API

```rust
use synta_codegen::{parse, generate, generate_with_config, CodeGenConfig};

let src = std::fs::read_to_string("schema.asn1")?;
let module = parse(&src)?;

// Defaults: std paths, no import prefix, owned string types
let rust_code = generate(&module)?;

// With crate-relative imports
let rust_code = generate_with_config(&module, CodeGenConfig::with_crate_imports())?;
```

## build.rs integration

Add `synta-codegen` as a build dependency:

```toml
[build-dependencies]
synta-codegen = { path = "../synta-codegen" }
```

In `build.rs`:

```rust
use std::path::PathBuf;
use synta_codegen::{parse, generate_with_config, CodeGenConfig};

fn main() {
    let schema = std::fs::read_to_string("schema.asn1")
        .expect("failed to read schema.asn1");

    let module = parse(&schema).expect("failed to parse ASN.1");
    let config = CodeGenConfig::with_crate_imports();
    let code = generate_with_config(&module, config)
        .expect("failed to generate Rust code");

    let out_dir = PathBuf::from(std::env::var("OUT_DIR").unwrap());
    std::fs::write(out_dir.join("generated_types.rs"), code)
        .expect("failed to write generated_types.rs");

    println!("cargo:rerun-if-changed=schema.asn1");
}
```

In `src/lib.rs`:

```rust
include!(concat!(env!("OUT_DIR"), "/generated_types.rs"));
```

## Multi-module build.rs

When schemas import from each other, list them in dependency order:

```rust
use synta_codegen::{parse, generate_with_config, CodeGenConfig};
use std::{fs, path::PathBuf};

fn main() {
    let modules = ["base_types", "user_module", "admin_module"];
    let out_dir = PathBuf::from(std::env::var("OUT_DIR").unwrap());
    let config = CodeGenConfig::with_crate_imports();

    for name in &modules {
        let schema = fs::read_to_string(format!("schemas/{name}.asn1"))
            .unwrap_or_else(|e| panic!("failed to read {name}.asn1: {e}"));
        let module = parse(&schema)
            .unwrap_or_else(|e| panic!("failed to parse {name}.asn1: {e}"));
        let code = generate_with_config(&module, config.clone())
            .unwrap_or_else(|e| panic!("failed to generate {name}: {e}"));
        fs::write(out_dir.join(format!("{name}.rs")), code)
            .unwrap_or_else(|e| panic!("failed to write {name}.rs: {e}"));
        println!("cargo:rerun-if-changed=schemas/{name}.asn1");
    }
}
```

In `src/lib.rs`:

```rust
mod base_types   { include!(concat!(env!("OUT_DIR"), "/base_types.rs"));   }
mod user_module  { include!(concat!(env!("OUT_DIR"), "/user_module.rs"));  }
mod admin_module { include!(concat!(env!("OUT_DIR"), "/admin_module.rs")); }

pub use base_types::{BaseType1, BaseType2};
pub use user_module::User;
```

## Recommended project layout

```
my-project/
├── Cargo.toml
├── build.rs
├── schemas/
│   ├── base_types.asn1
│   ├── user_module.asn1
│   └── admin_module.asn1
└── src/
    ├── lib.rs        (contains the include! macros above)
    └── manual.rs     (hand-written code that uses the generated types)
```

## What is NOT generated

The following are parsed and understood by synta-codegen but produce no Rust
output:

- Table constraints and information object class instances/object sets.
  CLASS definitions emit a documentation comment but no DER-encodable type.
- Serde derive attributes (available as a separate synta-derive feature).
- Trait implementations beyond `Debug`, `Clone`, and `PartialEq`.
- Explicit encode/decode methods (handled by the synta derive macros at
  compile time).
- User-defined constraint validation hooks.

## Next steps

- [Type Mappings]type-mappings.md — ASN.1 to Rust type table
- [Naming]naming.md — identifier conversion rules
- [OPTIONAL and DEFAULT]optional-default.md — optional field handling
- [Tagged Fields]tagged-fields.md — IMPLICIT and EXPLICIT tags
- [Imports]imports.md — IMPORTS and module references
- [Owned vs Borrowed]owned-vs-borrowed.md — StringTypeMode and lifetimes
- [Constraints]constraints.md — value/size/alphabet constraint validation
- [no_std]no-std.md — no_std and alloc support