synta 0.1.6

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


This page documents how synta-codegen handles `OPTIONAL` and `DEFAULT` fields
in SEQUENCE and SET types.

## Struct Layout

For each OPTIONAL field `fieldname` of type `FieldType`, the generated struct
contains:

```c
bool       has_fieldname;
FieldType  fieldname;
```

The `has_fieldname` boolean appears immediately before its associated field.

### Example

```asn1
MySequence ::= SEQUENCE {
    required   INTEGER,
    optional1  OCTET STRING OPTIONAL,
    optional2  UTF8String OPTIONAL
}
```

Generates:

```c
struct MySequence {
    int64_t required;
    bool has_optional1;
    SyntaOctetString *optional1;
    bool has_optional2;
    SyntaOctetString *optional2;
};
```

## Decode Pattern

The generated decode implementation uses `synta_decoder_peek_tag()` to inspect
the next tag.  If the tag matches the expected tag for `fieldname`, the field
is decoded and `has_fieldname` is set to `true`.  If it does not match, the
field is left at its zero-initialized value and `has_fieldname` remains `false`.

```c,ignore
SyntaTag peeked;
err = synta_decoder_peek_tag(seq, &peeked);
if (err == SyntaErrorCode_Success &&
    peeked.class_ == SyntaTagClass_ContextSpecific &&
    peeked.number == 0) {
    err = FieldType_decode(seq, &out->fieldname);
    if (err != SyntaErrorCode_Success) return err;
    out->has_fieldname = true;
}
```

## Encode Pattern

The generated encode implementation checks `has_fieldname` before encoding:

```c,ignore
if (value->has_fieldname) {
    err = FieldType_encode(encoder, &value->fieldname);
    if (err != SyntaErrorCode_Success) return err;
}
```

## DEFAULT Fields

Fields with a `DEFAULT` value are handled the same way as `OPTIONAL` fields in
the generated code: a `has_fieldname` boolean tracks whether the field is
present.  The default value itself is recorded as a comment in the generated
header but is not automatically applied by `TypeName_decode`.  If the field is
absent, `has_fieldname` is `false` and the caller is responsible for applying
the default.

## Partial Decode Failure

If `TypeName_decode` returns a non-success error code partway through a
SEQUENCE, fields that were successfully decoded before the failure are left
in the struct.  They are **not** automatically freed.  Call `TypeName_free`
on the partially-filled struct to release any already-allocated fields:

```c,ignore
MyType result = {0};
SyntaErrorCode err = MyType_decode(decoder, &result);
if (err != SyntaErrorCode_Success) {
    MyType_free(&result);  /* safe even if result is partially filled */
    return err;
}
/* ... use result ... */
MyType_free(&result);
```