synta 0.1.12

ASN.1 parser, decoder, and encoder library with DER/BER support and C FFI
Documentation
# API Reference

Complete reference for the synta-codegen library and command-line interface (Rust generation).

## Command-line interface

### Synopsis

```
synta-codegen [OPTIONS] <input.asn1> [extra.asn1 ...]
```

### Options

#### `-o, --output <file>`

Write output to `file`. Default: stdout.

#### `--output-dir <dir>`

Write one generated file per input module into `dir`. Files are written in
topological dependency order (base modules first). Cannot be combined with `-o`.

#### `--lang <language>`

Target language. Accepted values: `rust` (default), `c`.

#### `--check-imports`

Parse all input files and check for circular module import cycles. If a cycle is
detected, report it and exit with a non-zero status. No code is generated.

#### `--crate-imports`

Emit `use crate::module::Type` statements for imported ASN.1 types.

#### `--super-imports`

Emit `use super::module::Type` statements for imported ASN.1 types.

#### `--module-prefix <prefix>`

Emit `use <prefix>::module::Type` statements. The prefix is used verbatim followed
by `::`.

#### `--use-core`

Replace `std::` paths with `core::` equivalents in generated code (no_std
environments).

### Examples

**Single-file output**

```sh
synta-codegen schema.asn1 -o src/generated.rs
synta-codegen schema.asn1 --crate-imports -o src/generated.rs
synta-codegen schema.asn1 --super-imports -o src/generated.rs
synta-codegen schema.asn1 --module-prefix my_lib -o src/generated.rs
synta-codegen schema.asn1 --use-core -o src/generated.rs
cat schema.asn1 | synta-codegen > generated.rs
```

**Multi-file output**

```sh
synta-codegen base.asn1 user.asn1 --crate-imports --output-dir src/gen/
synta-codegen base.asn1 user.asn1 --check-imports
```

---

## Library API

### `parse`

```rust
pub fn parse(input: &str) -> Result<Module, ParseError>
```

Parse an ASN.1 module definition from `input`. Returns the parsed AST on success
or a `ParseError` with line and column information on failure. Accepts exactly one
module per call.

### `generate`

```rust
pub fn generate(module: &Module) -> Result<String, std::fmt::Error>
```

Generate Rust source code for `module` using default configuration: no import
statements emitted, `std::` paths used.

### `generate_with_config`

```rust
pub fn generate_with_config(
    module: &Module,
    config: CodeGenConfig,
) -> Result<String, std::fmt::Error>
```

Generate Rust source code applying the settings in `config`.

### `CodeGenConfig`

```rust
pub struct CodeGenConfig {
    pub module_path_prefix: Option<String>,
    pub use_core: bool,
    pub skip_imported_types: std::collections::HashSet<String>,
    pub imported_type_lifetimes: std::collections::HashMap<String, String>,
    pub string_type_mode: StringTypeMode,
    pub any_as_raw_der: bool,
    pub derive_mode: DeriveMode,
    pub raw_der_fields: std::collections::HashSet<String>,
}
```

Fields:

- `module_path_prefix` — when `Some(prefix)`, emit `use prefix::module::Type` for
  ASN.1 IMPORTS; `None` annotates imports as comments only.
- `use_core` — when `true`, emits `core::` instead of `std::` in generated paths.
- `skip_imported_types` — set of imported type names not declared locally (assumed
  to come from external modules).
- `imported_type_lifetimes` — map from imported type name to lifetime string (e.g.
  `"'a"`) for zero-copy types.
- `string_type_mode` — controls whether `OCTET STRING`, `BIT STRING`, and string
  types emit owned or zero-copy borrowed forms. See [`StringTypeMode`]#stringtypemode.
- `any_as_raw_der` — when `true`, `ANY` and `ANY DEFINED BY` fields are emitted as
  `RawDer<'a>` instead of `Element<'a>`.
- `derive_mode` — controls how derive macros are gated. See [`DeriveMode`]#derivemode.
- `raw_der_fields` — set of field names (after snake_case conversion) that are
  always emitted as `RawDer<'a>` regardless of their ASN.1 type; useful for
  deferring decoding of expensive fields such as `issuer`, `subject`, `extensions`.

Convenience constructors:

```rust
use synta_codegen::CodeGenConfig;

let config = CodeGenConfig::with_crate_imports();          // use crate::module::Type
let config = CodeGenConfig::with_super_imports();          // use super::module::Type
let config = CodeGenConfig::with_custom_prefix("my_lib"); // use my_lib::module::Type
```

### `StringTypeMode`

```rust
pub enum StringTypeMode {
    Owned,    // default
    Borrowed,
}
```

- `Owned` — emit heap-allocating owned types (`OctetString`, `BitString`,
  `Utf8String`, etc.). Default.
- `Borrowed` — emit zero-copy borrowed types (`OctetStringRef<'a>`,
  `BitStringRef<'a>`, `Utf8StringRef<'a>`, etc.).

### `DeriveMode`

```rust
pub enum DeriveMode {
    FeatureGated,      // default
    Always,
    Custom(String),
}
```

Controls how derive macros (`Asn1Sequence`, `Asn1Choice`, `Asn1Set`) and their
helper attributes are emitted.

- `FeatureGated` (default) — wraps every annotation in
  `#[cfg_attr(feature = "derive", …)]`. The consuming crate must declare
  `[features] derive = ["dep:synta-derive"]` in its `Cargo.toml`.
- `Always` — emits `#[derive(Asn1Sequence)]` unconditionally with no feature gate.
  Use when the consuming crate always depends on `synta-derive`.
- `Custom(name)` — uses a caller-supplied feature name instead of `"derive"`.

**Example:**

```rust
use synta_codegen::{CodeGenConfig, DeriveMode};

// Default: feature-gated (consuming crate needs a "derive" feature)
let config = CodeGenConfig::default();

// Always emit derive attributes unconditionally
let config = CodeGenConfig {
    derive_mode: DeriveMode::Always,
    ..CodeGenConfig::with_crate_imports()
};

// Use a custom feature name
let config = CodeGenConfig {
    derive_mode: DeriveMode::Custom("asn1-derive".to_string()),
    ..CodeGenConfig::with_crate_imports()
};
```

---

## AST types

These types are returned by `parse()` and consumed by the generation functions.
They are part of the public API but are primarily intended for tooling that needs
to inspect the parsed module.

### `Module`

```rust
pub struct Module {
    pub name: String,
    pub tagging: TaggingMode,
    pub imports: Vec<Import>,
    pub exports: Vec<String>,
    pub definitions: Vec<Definition>,
}
```

### `Definition`

```rust
pub struct Definition {
    pub name: String,
    pub ty: Type,
}
```

### `ParseError`

```rust
pub struct ParseError {
    pub message: String,
    pub line: usize,
    pub column: usize,
}
```

`ParseError` implements `std::fmt::Display` and `std::error::Error`.


---

## Convenience Traits

These traits are defined in the core `synta` crate and re-exported from its
crate root.  They are automatically available on all conforming types — no
additional feature flags are required.

### `ToDer`

```rust
pub trait ToDer: Encode + Sized {
    fn to_der(&self) -> Result<Vec<u8>, Error>;
    fn to_ber(&self) -> Result<Vec<u8>, Error>;
}
```

Blanket-implemented for every `T: Encode`.  Encodes a single value to DER or
BER bytes without constructing an `Encoder` manually.

### `FromDer`

```rust
pub trait FromDer: Sized {
    fn from_der(input: &[u8]) -> Result<Self, Error>;
    fn from_ber(input: &[u8]) -> Result<Self, Error>;
}
```

Blanket-implemented for every `T: for<'a> Decode<'a>` (owned/static types
only).  Decodes a single value from a byte slice without constructing a
`Decoder` manually.  Returns `Error::TrailingData` if the input contains bytes
beyond the decoded TLV.  Zero-copy borrowed types (e.g. `OctetStringRef<'a>`)
must use `Decoder` directly.

---

## See also

- [codegen/overview.md]codegen/overview.md — build.rs integration, multi-module projects
- [codegen/type-mappings.md]codegen/type-mappings.md — ASN.1 to Rust type table
- [asn1/limitations.md]asn1/limitations.md — supported ASN.1 syntax