# Constraints
synta-codegen can optionally generate runtime constraint checks in the `.c`
implementation file. By default, constraints appear as comments only.
## Default (No Flags)
Value range constraints, size constraints, PATTERN constraints, and CONTAINING
constraints are emitted as comments only. No runtime validation code is
generated.
## --with-regex (POSIX Regex)
For fields with a PATTERN constraint, the generated code uses POSIX
`regcomp()`/`regexec()` from `<regex.h>`:
- The pattern is compiled once (static variable, compiled on first call).
- Each decode call runs `regexec()` against the decoded string bytes.
- A failed match returns `SyntaErrorCode_InvalidEncoding`.
Link requirement: on most platforms `<regex.h>` is part of libc. No extra
library is needed.
## --with-pcre (PCRE2)
For PATTERN constraints, uses PCRE2 (`<pcre2.h>`):
- The pattern is compiled once with `pcre2_compile()`.
- Each decode call runs `pcre2_match()`.
- A failed match returns `SyntaErrorCode_InvalidEncoding`.
Link requirement: `-lpcre2-8` (or the appropriate PCRE2 variant for your
character width).
## --with-containing (CONTAINING Constraint)
For fields carrying a CONTAINING constraint (indicating that the raw bytes
must be valid encodings of another type), the generated code allocates a
scratch decoder, decodes the inner type, and frees it:
```c,ignore
SyntaDecoder *scratch = synta_decoder_new(
synta_octet_string_data(out->field),
synta_octet_string_len(out->field),
SyntaEncoding_Der);
if (!scratch) return SyntaErrorCode_OutOfMemory;
InnerType tmp = {0};
err = InnerType_decode(scratch, &tmp);
InnerType_free(&tmp);
synta_decoder_free(scratch);
if (err != SyntaErrorCode_Success) return err;
```
Without `--with-containing`, the check is a comment only.
## Constrained INTEGER
Constrained INTEGER types (`INTEGER (low..high)`) always generate a newtype
struct with inline validation helpers, regardless of constraint flags:
```c
/* INTEGER (0..100) */
typedef struct { uint8_t value; } Percentage;
static inline bool percentage_new(uint8_t v, Percentage* out) {
if (!(v <= 100LL)) return false;
out->value = v;
return true;
}
static inline Percentage percentage_new_unchecked(uint8_t v) {
Percentage out; out.value = v; return out;
}
static inline uint8_t percentage_get(const Percentage* self) {
return self->value;
}
```
The range check is always performed by `percentage_new()`; use
`percentage_new_unchecked()` only when the value is already known to be valid.