Skip to main content
Version: dev

Field Configuration

This page covers macro-level field configuration in Swift.

Available Macro Attributes

  • @ForyStruct on struct/class models
  • @ForyEnum on C-style enum models
  • @ForyUnion and @ForyCase on associated-value enum models
  • @ForyField(encoding: ...) on numeric fields
  • @ListField, @SetField, and @MapField for nested collection field metadata

@ForyField(encoding:)

Use @ForyField to override integer encoding strategy.

@ForyStruct
struct Metrics: Equatable {
@ForyField(encoding: .fixed)
var u32Fixed: UInt32 = 0

@ForyField(encoding: .tagged)
var u64Tagged: UInt64 = 0
}

Supported combinations

Swift typeSupported encoding valuesDefault encoding
Int32.varint, .fixed.varint
UInt32.varint, .fixed.varint
Int64.varint, .fixed, .tagged.varint
UInt64.varint, .fixed, .tagged.varint
Int.varint, .fixed, .tagged.varint
UInt.varint, .fixed, .tagged.varint

Compile-time validation rejects unsupported combinations (for example, Int32 with .tagged).

Nested Collection Field Metadata

Use @ListField, @SetField, and @MapField when a nested field needs type-specific wire metadata, such as fixed or tagged integer encoding inside a container.

@ForyStruct
struct NestedMetrics: Equatable {
@ListField(element: .encoding(.fixed))
var values: [Int32?] = []

@SetField(element: .encoding(.fixed))
var ids: Set<UInt32?> = []

@MapField(key: .encoding(.fixed), value: .encoding(.tagged))
var byId: [Int32: UInt64] = [:]

@MapField(value: .list(element: .encoding(.fixed)))
var groups: [String: [Int32?]] = [:]
}

Non-null List elements with fixed-width signed or unsigned integer metadata are classified and encoded as the matching Fory primitive packed-array type. Set fields stay classified as Fory sets, including fixed-width integer sets.

When the Swift property type is an alias or otherwise needs a full hint, use @ForyField(type:):

typealias MetricsMap = [String: [Int32?]]

@ForyStruct
struct AliasMetrics: Equatable {
@ForyField(type: .map(
key: .string,
value: .list(.int32(nullable: true, encoding: .fixed))
))
var metrics: MetricsMap = [:]
}

Union payloads use the same DSL through @ForyCase(payload:):

@ForyUnion
enum Event: Equatable {
@ForyCase(id: 1)
case created(String)

@ForyCase(id: 2, payload: .uint64(encoding: .fixed))
case deleted(UInt64)
}

Model Macro Requirements

Struct and class fields

  • Stored properties must declare explicit types
  • Computed properties are ignored
  • Static/class properties are ignored

Class requirement

Classes annotated with @ForyStruct must provide a required init() for default construction.

@ForyStruct
final class Node {
var value: Int32 = 0
var next: Node? = nil

required init() {}
}

Dynamic Any Fields in Macro Types

Fory model macros support dynamic fields and nested containers:

  • Any, AnyObject, any Serializer
  • AnyHashable
  • [Any]
  • [String: Any]
  • [Int32: Any]
  • [AnyHashable: Any]

Current limitations:

  • Dictionary<K, Any> is only supported when K is String, Int32, or AnyHashable