# 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);
```