synta 0.1.6

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


## Lifecycle

### synta_decoder_new

Create a new decoder from a byte slice.

```c
SyntaDecoder *synta_decoder_new(const uint8_t *data,
                                 uintptr_t len,
                                 SyntaEncoding encoding);
```

**Parameters:**
- `data` — Pointer to encoded data (may be NULL if `len` is 0)
- `len` — Length of data in bytes
- `encoding` — Encoding rules (`SyntaEncoding_Der`, `SyntaEncoding_Ber`, or
  `SyntaEncoding_Cer`)

**Returns:** Decoder pointer, or NULL on error.

**Memory:** Returned decoder must be freed with `synta_decoder_free()`.

**Example:**
```c
const uint8_t data[] = {0x02, 0x01, 0x2A}; /* INTEGER 42 */
SyntaDecoder *decoder = synta_decoder_new(data, sizeof(data), SyntaEncoding_Der);
if (!decoder) {
    fprintf(stderr, "Failed: %s\n", synta_get_last_error_message());
    return 1;
}
```

### synta_decoder_new_with_config

Create a decoder with custom DoS-protection limits.

```c
SyntaDecoder *synta_decoder_new_with_config(const uint8_t *data,
                                             uintptr_t len,
                                             SyntaEncoding encoding,
                                             const SyntaDecoderConfig *config);
```

**Example:**
```c
SyntaDecoderConfig config = {
    .max_depth             = 32,
    .max_sequence_elements = 10000,
    .max_length            = 16 * 1024 * 1024  /* 16 MB */
};
SyntaDecoder *decoder = synta_decoder_new_with_config(
    data, len, SyntaEncoding_Der, &config);
```

### synta_decoder_free

Free a decoder and all associated resources.

```c
void synta_decoder_free(SyntaDecoder *decoder);
```

Safe to call with NULL.

## Decoder Utilities

### synta_decoder_remaining

Get the number of remaining bytes.

```c
uintptr_t synta_decoder_remaining(const SyntaDecoder *decoder);
```

### synta_decoder_at_end

Check if the decoder has consumed all input.

```c
bool synta_decoder_at_end(const SyntaDecoder *decoder);
```

### synta_decoder_peek_tag

Peek at the next tag without consuming it.

```c
SyntaErrorCode synta_decoder_peek_tag(const SyntaDecoder *decoder,
                                       SyntaTag *out);
```

**Example:**
```c
SyntaTag tag;
if (synta_decoder_peek_tag(decoder, &tag) == SyntaErrorCode_Success) {
    if (tag.class_ == SyntaTagClass_ContextSpecific && tag.number == 0) {
        /* Handle optional [0] field */
    }
}
```

## Primitive Type Decoding

### synta_decode_boolean

```c
SyntaErrorCode synta_decode_boolean(SyntaDecoder *decoder, bool *out);
```

### synta_decode_integer

```c
SyntaErrorCode synta_decode_integer(SyntaDecoder *decoder,
                                     SyntaInteger **out);
```

**Memory:** Returned integer must be freed with `synta_integer_free()`.

**Example:**
```c
SyntaInteger *integer = NULL;
if (synta_decode_integer(decoder, &integer) == SyntaErrorCode_Success) {
    int64_t value;
    if (synta_integer_to_i64(integer, &value) == SyntaErrorCode_Success) {
        printf("Integer: %lld\n", (long long)value);
    }
    synta_integer_free(integer);
}
```

### synta_decode_null

```c
SyntaErrorCode synta_decode_null(SyntaDecoder *decoder);
```

### synta_decode_real

Decode a REAL (IEEE 754 double) value.

```c
SyntaErrorCode synta_decode_real(SyntaDecoder *decoder, double *out);
```

### synta_decode_octet_string

```c
SyntaErrorCode synta_decode_octet_string(SyntaDecoder *decoder,
                                          SyntaOctetString **out);
```

**Memory:** Returned octet string must be freed with `synta_octet_string_free()`.

### synta_decode_bit_string

```c
SyntaErrorCode synta_decode_bit_string(SyntaDecoder *decoder,
                                        SyntaByteArray *out,
                                        uint8_t *unused_bits);
```

**Parameters:**
- `out` — Output byte array
- `unused_bits` — Number of unused bits in last byte (0-7)

**Memory:** Output byte array must be freed with `synta_byte_array_free()`.

### synta_decode_object_identifier

```c
SyntaErrorCode synta_decode_object_identifier(SyntaDecoder *decoder,
                                                SyntaObjectIdentifier **out);
```

**Memory:** Returned OID must be freed with `synta_oid_free()`.

## String Type Decoding

The string decode functions come in two flavours:

- **Validated** (`synta_decode_utf8_string`, etc.) — decode the typed string
  and enforce the character-set rules.  Return an owned `SyntaByteArray`.
- **Raw / `_os`** (`synta_decode_utf8_string_os`, etc.) — verify only the
  outer tag and length; return the content bytes verbatim as a
  `SyntaOctetString*` without character-set validation.  Useful when the
  content was already validated upstream or when dealing with non-conforming
  data.

### synta_decode_utf8_string

```c
SyntaErrorCode synta_decode_utf8_string(SyntaDecoder *decoder,
                                         SyntaByteArray *out);
```

**Memory:** Output byte array is **owned**; must be freed with `synta_byte_array_free()`.

### synta_decode_utf8_string_os

Decode a UTF8String (universal tag 12) into a `SyntaOctetString*` **without**
UTF-8 validation.

```c
SyntaErrorCode synta_decode_utf8_string_os(SyntaDecoder *decoder,
                                            SyntaOctetString **out);
```

**Memory:** Returned octet string must be freed with `synta_octet_string_free()`.

### synta_decode_printable_string

```c
SyntaErrorCode synta_decode_printable_string(SyntaDecoder *decoder,
                                               SyntaByteArray *out);
```

**Memory:** Output byte array is **owned**; must be freed with `synta_byte_array_free()`.

### synta_decode_printable_string_os

Decode a PrintableString (universal tag 19) into a `SyntaOctetString*` **without**
character-set validation.

```c
SyntaErrorCode synta_decode_printable_string_os(SyntaDecoder *decoder,
                                                 SyntaOctetString **out);
```

**Memory:** Returned octet string must be freed with `synta_octet_string_free()`.

### synta_decode_ia5_string

```c
SyntaErrorCode synta_decode_ia5_string(SyntaDecoder *decoder,
                                        SyntaByteArray *out);
```

**Memory:** Output byte array is **owned**; must be freed with `synta_byte_array_free()`.

### synta_decode_ia5_string_os

Decode an IA5String (universal tag 22) into a `SyntaOctetString*` **without**
ASCII-range validation.

```c
SyntaErrorCode synta_decode_ia5_string_os(SyntaDecoder *decoder,
                                           SyntaOctetString **out);
```

**Memory:** Returned octet string must be freed with `synta_octet_string_free()`.

### synta_decode_utctime_os

Decode a UTCTime (universal tag 23) into a `SyntaOctetString*` **without**
time-string syntax validation.

```c
SyntaErrorCode synta_decode_utctime_os(SyntaDecoder *decoder,
                                        SyntaOctetString **out);
```

**Memory:** Returned octet string must be freed with `synta_octet_string_free()`.

### synta_decode_generalized_time_os

Decode a GeneralizedTime (universal tag 24) into a `SyntaOctetString*` **without**
time-string syntax validation.

```c
SyntaErrorCode synta_decode_generalized_time_os(SyntaDecoder *decoder,
                                                 SyntaOctetString **out);
```

**Memory:** Returned octet string must be freed with `synta_octet_string_free()`.

## Constructed Type Decoding

### synta_decoder_enter_sequence

Enter a SEQUENCE and return a child decoder over its contents.

```c
SyntaErrorCode synta_decoder_enter_sequence(SyntaDecoder *decoder,
                                              SyntaDecoder **out);
```

**Memory:** Returned decoder must be freed with `synta_decoder_free()`.

**Example:**
```c
SyntaDecoder *seq_decoder = NULL;
if (synta_decoder_enter_sequence(decoder, &seq_decoder) == SyntaErrorCode_Success) {
    while (!synta_decoder_at_end(seq_decoder)) {
        /* Decode element */
    }
    synta_decoder_free(seq_decoder);
}
```

### synta_decoder_enter_set

Enter a SET.

```c
SyntaErrorCode synta_decoder_enter_set(SyntaDecoder *decoder,
                                        SyntaDecoder **out);
```

### synta_decoder_enter_constructed

Enter a constructed type with an explicit or implicit tag.

```c
SyntaErrorCode synta_decoder_enter_constructed(SyntaDecoder *decoder,
                                                 SyntaTag tag,
                                                 SyntaDecoder **out);
```

**Example:**
```c
SyntaTag tag;
synta_decoder_peek_tag(decoder, &tag);
if (tag.class_ == SyntaTagClass_ContextSpecific && tag.number == 0) {
    SyntaDecoder *inner = NULL;
    synta_decoder_enter_constructed(decoder, tag, &inner);
    /* Decode contents using inner */
    synta_decoder_free(inner);
}
```