synta 0.1.11

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


## Error Codes

```c
typedef enum SyntaErrorCode {
    SyntaErrorCode_Success                       = 0,
    SyntaErrorCode_InvalidTag                    = 1,
    SyntaErrorCode_InvalidLength                 = 2,
    SyntaErrorCode_UnexpectedEof                 = 3,
    SyntaErrorCode_InvalidEncoding               = 4,
    SyntaErrorCode_InvalidInteger                = 5,
    SyntaErrorCode_InvalidOid                    = 6,
    SyntaErrorCode_InvalidUtf8                   = 7,
    SyntaErrorCode_InvalidPrintableString        = 8,
    SyntaErrorCode_InvalidIA5String              = 9,
    SyntaErrorCode_InvalidBoolean                = 10,
    SyntaErrorCode_InvalidTime                   = 11,
    SyntaErrorCode_InvalidBitString              = 12,
    SyntaErrorCode_MaxDepthExceeded              = 13,
    SyntaErrorCode_MaxSequenceElementsExceeded   = 14,
    SyntaErrorCode_MaxLengthExceeded             = 15,
    SyntaErrorCode_BerViolation                  = 16,
    SyntaErrorCode_DerViolation                  = 17,
    SyntaErrorCode_CerViolation                  = 18,
    SyntaErrorCode_NullPointer                   = 19,
    SyntaErrorCode_InvalidArgument               = 20,
    SyntaErrorCode_OutOfMemory                   = 21,
    SyntaErrorCode_IntegerOverflow               = 22,
    SyntaErrorCode_IntegerUnderflow              = 23,
    SyntaErrorCode_Unknown                       = 999,
} SyntaErrorCode;
```

## Error Functions

### synta_error_message

Get a static error message for an error code.

```c
const char *synta_error_message(SyntaErrorCode code);
```

**Parameters:**
- `code` — Error code

**Returns:** Static string describing the error (never NULL).

**Example:**
```c
SyntaErrorCode err = synta_decode_integer(decoder, &integer);
if (err != SyntaErrorCode_Success) {
    printf("Error: %s\n", synta_error_message(err));
}
```

### synta_get_last_error_message

Get a detailed error message for the last error on the current thread.

```c
const char *synta_get_last_error_message(void);
```

**Returns:** Detailed error message, or NULL if no error has occurred on
this thread since the last clear.

The returned pointer is valid until the next FFI call on the same thread.

**Example:**
```c
SyntaCertificate *cert = synta_certificate_parse_der(data, len);
if (!cert) {
    const char *msg = synta_get_last_error_message();
    if (msg) {
        fprintf(stderr, "Detailed error: %s\n", msg);
    }
}
```

### synta_clear_last_error

Clear the thread-local error message.

```c
void synta_clear_last_error(void);
```

## Error Propagation Pattern

The recommended pattern for propagating errors is:

```c
SyntaDecoder *decoder = NULL;
SyntaInteger *integer = NULL;
int result = -1;

decoder = synta_decoder_new(data, len, SyntaEncoding_Der);
if (!decoder) {
    goto cleanup;
}

if (synta_decode_integer(decoder, &integer) != SyntaErrorCode_Success) {
    fprintf(stderr, "Decode failed: %s\n", synta_get_last_error_message());
    goto cleanup;
}

int64_t value;
if (synta_integer_to_i64(integer, &value) != SyntaErrorCode_Success) {
    goto cleanup;
}

printf("Value: %lld\n", (long long)value);
result = 0;

cleanup:
    synta_integer_free(integer);
    synta_decoder_free(decoder);
    return result;
```

## StoredError: Lazy Formatting

Internally, errors are stored as a `StoredError` enum that formats the error
string lazily on first access.  This means `synta_get_last_error_message()`
may perform string formatting on the first call after an error, but subsequent
calls return a cached pointer at no cost.

The storage is thread-local, so each thread has its own independent error
state.