synta 0.1.9

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


`synta-codegen --lang c` generates complete C code (both headers and
implementations) from ASN.1 schemas, providing production-ready
encoder/decoder functions that work with the libcsynta C API.

## The Pipeline

1. Parse one or more ASN.1 schema files.
2. Topologically sort all type definitions (leaf types first).
3. Emit a C header (`.h`) with type definitions, forward declarations, and
   function prototypes.
4. Emit a C implementation (`.c`) with full `TypeName_decode`,
   `TypeName_encode`, and `TypeName_free` implementations.

Every function calls libcsynta directly; the generated `.c` file has no other
dependencies beyond `<string.h>` and `<stdlib.h>`.

## Quick Start

```bash
# Generate C header to stdout
synta-codegen --lang c schema.asn1

# Generate header to a file
synta-codegen --lang c -o types.h schema.asn1

# Generate implementation file (--impl names the header to #include)
synta-codegen --lang c --impl types.h -o types.c schema.asn1

# Specify a custom path for synta.h inside the generated header
synta-codegen --lang c --header-path /usr/local/include/synta.h -o types.h schema.asn1
```

### Compile and Link

```bash
cc -c types.c -o types.o $(pkg-config --cflags csynta)
cc myapp.c types.o -o myapp $(pkg-config --libs csynta)
```

Without pkg-config:

```bash
cc -I/path/to/synta/include -c types.c -o types.o
cc myapp.c types.o -o myapp -L/path/to/synta/lib -lcsynta
```

The generated code requires a C99-capable compiler (`-std=c99` or later).

## What You Get

### Header File (.h)

- Type definitions (structs, enums, unions) in topological order
- Forward declarations
- Function prototypes (`TypeName_decode`, `TypeName_encode`, `TypeName_free`)
- Optional helper functions (`TypeName_init`, `TypeName_validate`,
  `TypeName_print`) when `--with-helpers` is active
- C/C++ compatibility (`extern "C"` guards)

Every generated header begins with:

```c
#include <stdint.h>
#include <stdbool.h>
#include "synta.h"   /* or the path given by --header-path */
```

### Implementation File (.c)

- Full `TypeName_decode` implementations using `synta_decoder_*` functions
- Full `TypeName_encode` implementations using `synta_encoder_*` functions
- `TypeName_free` with NULL-safe cleanup of every heap-allocated field
- Error propagation on every libcsynta call

## Generated Function Signatures

For each type `TypeName` the generator emits at minimum three functions:

```c,ignore
/* Decode from DER/BER into an already-allocated struct */
SyntaErrorCode TypeName_decode(SyntaDecoder *decoder, TypeName *out);

/* Encode a struct to DER/BER via an existing encoder */
SyntaErrorCode TypeName_encode(SyntaEncoder *encoder, const TypeName *value);

/* Release all heap resources owned by the struct.
   Does NOT free the struct itself. */
void TypeName_free(TypeName *value);
```

With `--with-helpers`, three additional static inline helpers appear in the
header (see [Helper Functions](build-integration.md)).

With `--arena`, an additional `TypeName_decode_arena()` variant is generated
(see [Arena Allocator](arena-allocator.md)).

## Full End-to-End Example

### Input: ASN.1 Schema

```asn1
Certificate DEFINITIONS ::= BEGIN
    AlgorithmIdentifier ::= SEQUENCE {
        algorithm    OBJECT IDENTIFIER,
        parameters   ANY DEFINED BY algorithm OPTIONAL
    }
END
```

### Generated Header (certificate.h, excerpt)

```c
#ifndef CERTIFICATE_H
#define CERTIFICATE_H

#include <stdint.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include "synta.h"

#ifdef __cplusplus
extern "C" {
#endif

typedef struct AlgorithmIdentifier AlgorithmIdentifier;

struct AlgorithmIdentifier {
    SyntaObjectIdentifier* algorithm;
    bool has_parameters;
    SyntaOctetString* parameters;
};

SyntaErrorCode algorithm_identifier_decode(SyntaDecoder* decoder,
                                           AlgorithmIdentifier* out);
SyntaErrorCode algorithm_identifier_encode(SyntaEncoder* encoder,
                                           const AlgorithmIdentifier* value);
void algorithm_identifier_free(AlgorithmIdentifier* value);

#ifdef __cplusplus
}
#endif
#endif /* CERTIFICATE_H */
```

### Usage in Application Code

```c
#include "certificate.h"

int main(void) {
    AlgorithmIdentifier alg_id;
    algorithm_identifier_init(&alg_id);  /* zeroes all fields */

    alg_id.algorithm = synta_oid_from_string("1.2.840.113549.1.1.11");
    alg_id.has_parameters = false;

    SyntaEncoder *encoder = synta_encoder_new(SyntaEncoding_Der);
    SyntaErrorCode err = algorithm_identifier_encode(encoder, &alg_id);
    if (err != SyntaErrorCode_Success) {
        fprintf(stderr, "Encode error: %s\n", synta_error_message(err));
        return 1;
    }

    SyntaByteArray encoded = {0};
    synta_encoder_finish(encoder, &encoded);
    /* encoder consumed by synta_encoder_finish; do not free it */

    /* Decode back */
    SyntaDecoder *decoder = synta_decoder_new(encoded.data, encoded.len,
                                              SyntaEncoding_Der);
    AlgorithmIdentifier decoded;
    algorithm_identifier_init(&decoded);
    err = algorithm_identifier_decode(decoder, &decoded);

    /* Cleanup */
    algorithm_identifier_free(&alg_id);
    algorithm_identifier_free(&decoded);
    synta_decoder_free(decoder);
    synta_byte_array_free(&encoded);
    return 0;
}
```

## Code Generation Statistics

From the X.509 certificate example schema (10 types):

- **Header file**: approximately 192 lines
- **Implementation file**: approximately 665 lines
- **Total**: approximately 857 lines of production-ready C code

## Supported Features

### Fully Supported

- SEQUENCE / SET types with full encode/decode
- SEQUENCE OF / SET OF with dynamic array allocation
- CHOICE types as discriminated unions (tag enum + union)
- INTEGER types including named numbers (enums) and constrained ranges
- BIT STRING (dedicated `SyntaBitString` struct)
- OBJECT IDENTIFIER
- OCTET STRING and string variants (UTF8String, PrintableString, IA5String)
- Time types (UTCTime, GeneralizedTime)
- Optional fields with presence flags
- Type references between defined types
- Error handling and cleanup

### Partial Support

- `[N] EXPLICIT` tagged fields — fully supported for primitive and TypeRef
  inner types; anonymous inline SEQUENCE/SET inside an EXPLICIT tag is not
  yet supported
- `[N] IMPLICIT` tagged fields — fully supported for structural inner types
  (SEQUENCE, SET, SEQUENCE OF, SET OF, and TypeRefs that resolve to them)

### Not Yet Implemented

- Complex constraint validation in generated code (see [Constraints]constraints.md)

## Multi-Module Projects

For schemas that import types from other schemas, use `--output-dir` with
`--emit both`:

```bash
synta-codegen --lang c --emit both --output-dir ./generated/ \
    base.asn1 extension.asn1
```

Each module produces a `<stem>.h` and `<stem>.c` pair in topological order.
Import references resolve to the corresponding module header.

Use `--check-imports` to validate inter-module imports without generating
output:

```bash
synta-codegen --check-imports base.asn1 extension.asn1
```