// BindingPlan.swift // Types describing the outcome of binding analysis: which symbols were bound, // which were skipped, and why. This file is the foundation of the binding-plan // layer — the explicit marshalling plans (`CallablePlan` et al.) that replace // direct IR-to-string code generation are added here as the layer is built out. import Foundation /// Whether a mapped type's Swift declaration has been generated yet. /// The planner uses this to defer callables that reference types not yet /// emitted (e.g. functions taking `Source` before the `Source` class is /// generated). public enum BindingCategory: String, Equatable, Sendable { /// Primitive, enum, bitfield, string, or alias — no dependencies. case ready /// Object or interface — needs a class/stub before callables can use it. case needsClass /// Boxed record — needs a record wrapper. case needsRecord /// Callback type — needs a typealias before callables can use it. case callback /// A type that will never be generated (foreign, unknown). case unavailable } // MARK: - Value Marshalling /// How a Swift value is marshalled **into** a C function call argument. /// /// Describes the transformation applied to each parameter before the call. /// The renderer never sees `GIRType` — it only combines these marshalling /// shapes with the plan's type names. public enum MarshalIn: Equatable, Sendable { /// Passed directly with no conversion (e.g. `Int32` → `gint32`). case direct /// Passed through a numeric cast to the target type (e.g. `Int` → `gint8`). /// - Parameter targetType: The Swift numeric type to cast to. case numericCast(targetType: String) /// Convert `Bool` to `gboolean` via `? 1 : 0`. case boolToGboolean /// Convert `String` to a C string (`withCString` / `utf8` pointer). case stringToC /// Convert `[String]` to a NULL-terminated C `char **` (mutable outer + elements). case stringArrayToC /// Convert `[String]` to a NULL-terminated C `const char * const *` (const outer + elements). case stringConstArrayToC /// Convert `[String]` to a NULL-terminated C `const char **` (const elements, mutable outer pointer). case stringConstElementArrayToC /// Convert `[Wrapper]` to a C array of instance pointers (`T **`), NULL-terminated. case objectArrayToC /// Convert `[T]` of C-scalar values to a contiguous C buffer (`const T *`). case scalarArrayToC /// Access the underlying pointer of an object wrapper. /// - Parameter consumingRefFunction: The C ref function to call on the /// pointer before the call when the callee consumes a reference /// (`transfer-ownership="full"`), e.g. `"g_object_ref"` or /// `"gtk_expression_ref"`; `nil` for `transfer-ownership="none"` (and /// the degenerate `"container"`), where the pointer is only borrowed. /// The Swift wrapper keeps its own reference and unrefs in `deinit`, so /// a consumed reference MUST be balanced here or the wrapper /// over-releases (use-after-free). case objectPointer(consumingRefFunction: String?) /// Access the underlying pointer of an interface-typed wrapper (a /// protocol existential `any Foo`). /// - Parameter consumingRefFunction: See `objectPointer`. case interfacePointer(consumingRefFunction: String?) /// Pass the `rawValue` of an enum (Int → C int). case enumRaw /// Pass the `rawValue` of a bitfield (UInt32 → C uint). case bitfieldRaw /// Access the pointer of a boxed record. When `consumingCopyFunction` is /// non-nil, the callee consumes a copied pointer while the Swift wrapper /// keeps ownership of the original. /// - Parameters: /// - consumingCopyFunction: The record copy/ref function to call before /// passing a transfer-full argument, or `nil` for borrowed input. /// - copyReturnsVoid: Whether the copy/ref function returns `void`, in /// which case the original pointer is passed after invoking it. case boxedPointer(consumingCopyFunction: String?, copyReturnsVoid: Bool) /// Box a Swift closure for C callback trampoline dispatch. /// - Parameters: /// - scope: The callback lifetime from the GIR `scope` attribute. /// - destroyTrampoline: The per-signature destroy trampoline C name, /// or `""` when no destroy is needed (namespace-level typealiases). case callbackBox(scope: CallbackScope?, destroyTrampoline: String) /// Unsupported — causes the whole callable to be skipped. /// - Parameter reason: Why the parameter cannot be marshalled. case unsupported(reason: String) } /// How a C return value is marshalled **out** into Swift. /// /// Describes the transformation applied to the C function's return value /// to produce the Swift-typed result that callers see. public enum MarshalOut: Equatable, Sendable { /// Direct assignment with no conversion. case direct /// Cast from a C numeric type to the target Swift type. /// - Parameter fromType: The C type being cast from. case numericCast(fromType: String) /// Convert `gboolean` (Int32) to `Bool` via `!= 0`. case gbooleanToBool /// Copy a C string, optionally freeing the source. /// - Parameter free: When `true`, the caller owns the string and must `g_free` it. /// - Parameter constPointee: Whether the C out-param pointee is `const /// char*` (`true`) rather than mutable `char*` (`false`). Only /// meaningful for out-parameters (see `outParamLocalType`); irrelevant /// for in-params (bridged via `withCString`) and return values. case stringCopy(free: Bool, constPointee: Bool = true) /// Wrap an object pointer, optionally sinking a floating ref. /// - Parameter sink: When `true`, call `g_object_ref_sink` (for InitiallyUnowned constructors). case objectWrap(sink: Bool) /// Wrap an object pointer with `g_object_ref` (for transfer=none returns). case objectRetain /// Convert an integer raw value to an enum case. /// - Parameter swiftType: The fully qualified Swift enum type name. case enumFromRaw(swiftType: String) /// Convert a C flags value to a Swift `OptionSet` bitfield. /// - Parameter swiftType: The fully qualified Swift bitfield type name. case bitfieldFromRaw(swiftType: String) /// Wrap a boxed record pointer, optionally copying. /// - Parameter copy: When `true`, call the copy function to take a reference. /// - Parameter copyFunction: The C copy/ref function from the GIR (e.g. `g_value_copy`). case boxedWrap(copy: Bool, copyFunction: String?) /// Wrap an object pointer as the concrete `Ref` interface wrapper, /// returned as the protocol existential. /// - Parameter adopt: When `true`, take ownership (`init(takingOwnership:)`, /// transfer=full); when `false`, retain a borrowed reference /// (`init(retaining:)`, transfer=none). case interfaceWrap(adopt: Bool) /// Unsupported — causes the whole callable to be skipped. /// - Parameter reason: Why the return value cannot be marshalled. case unsupported(reason: String) } /// How a type is accessed through the GValue machinery. /// /// Properties without a GIR `getter=` / `setter=` annotation fall back to /// `g_object_get` / `g_object_set`, which dispatches through the GType system. /// These ops supply the correct `g_value_get_*` / `g_value_set_*` calls for /// the type. Any numeric bridging the getter needs (e.g. `g_value_get_enum` /// returns `gint` while a Swift enum uses an `Int` raw value) is applied by /// the renderer via `numericCast`, keyed off `getterSuffix`. public struct GValueOps: Equatable, Sendable { /// The GType macro name used with `g_object_get`/`_set`. /// Examples: `"G_TYPE_INT"`, `"G_TYPE_STRING"`, `"G_TYPE_OBJECT"`. public let typeMacro: String /// The `g_value_get_*` function suffix, e.g. `"int"`, `"enum"`, `"boxed"`. public let getterSuffix: String /// The `g_value_set_*` function suffix, e.g. `"int"`, `"enum"`, `"boxed"`. public let setterSuffix: String /// For `getterSuffix == "boxed"` only: whether the boxed record has a /// known GIR copy function. Selects `init(retaining:)` (copies the /// borrowed `g_value_get_boxed` pointer) when `true`, or /// `init(takingOwnership:)` (adopts it as-is — the only initializer a /// no-copy-function record exposes, see `renderRecord`) when `false`. /// Ignored for every other suffix. public let hasCopyFunction: Bool public init(typeMacro: String, getterSuffix: String, setterSuffix: String, hasCopyFunction: Bool = false) { self.typeMacro = typeMacro; self.getterSuffix = getterSuffix self.setterSuffix = setterSuffix; self.hasCopyFunction = hasCopyFunction } } /// The reason a GIR symbol was excluded from binding generation. /// /// Every symbol the generator cannot (or should not) bind is skipped as a /// whole, with one of these reasons recorded in the module's ``SkipReport``. /// The compile gate diffs reports against a committed baseline: a new skip in /// a category the generator claims to support is a regression. public enum SkipReason: String, Codable, CaseIterable, Sendable { /// The symbol references a namespace with no loaded GIR (e.g. `cairo`). case foreignNamespace /// A parameter, return, or field type could not be resolved. case unknownType /// The callable is variadic (`...` / `va_list`), which cannot be bridged. case varargs /// The callable has an unsupported `direction="out"` parameter. case outParameter /// The callable has an unsupported `direction="inout"` parameter. case inoutParameter /// A C array parameter or return has no length annotation. case arrayWithoutLength /// A C array has a usable length annotation, but array bridging is /// not yet implemented. case arrayBridgingUnimplemented /// The type involves a container (GList, GSList, GHashTable, …) that is /// not yet bridged. case containerType /// A callback parameter has no user-data slot, so a Swift closure cannot /// be attached. case callbackWithoutUserData /// A callback parameter has a `scope` the generator does not support. case unsupportedCallbackScope /// The record has no GType registration and no configured lifetime /// functions, so it cannot be safely wrapped. case plainRecord /// The record is a class/interface structure (`glib:is-gtype-struct-for`) /// and is never bound. case gtypeStruct /// The symbol is marked `introspectable="0"` in the GIR. case notIntrospectable /// The symbol is deprecated and configured for removal. case deprecatedRemoved /// The symbol is shadowed by another (`shadowed-by`). case shadowedSymbol /// The symbol was explicitly ignored via configuration. case configIgnored /// A property type has no supported GValue accessor category. case unsupportedGValueCategory /// The symbol's Swift name collides with another symbol in the same /// module after case conversion (e.g. `CSET_A_2_Z` and `CSET_a_2_z` /// both map to `csetA2Z`); the first occurrence wins. case nameCollision /// A method in an interface protocol requirement has no consistently- /// witnessed signature across all implementing classes. The requirement /// is dropped from the protocol to keep it compilable. case interfaceMethodSignatureDrift /// A boxed record returned `transfer-ownership="none"` has no copy/ref /// function but a free function, so adopting the borrowed pointer as owned /// would double-free. The callable is skipped. case boxedBorrowedWithoutCopy /// A transfer-full boxed-record in-parameter has no copy function, so the /// wrapper cannot safely preserve its owned pointer while the callee consumes /// a separate copy. case boxedConsumedWithoutCopy /// A namespace function's `moved-to` target type could not be found. case movedToTargetMissing /// A constructor has out-params, which cannot be expressed as a Swift /// `init` (an init cannot also return out-value tuples). The constructor /// is skipped. case constructorOutParams /// A signal parameter or return type could not be mapped. case signalUnmappableParam /// A type declaration duplicates one already declared in a dependency /// module (e.g. GObject re-declaring GLib's `IOCondition`); the /// downstream duplicate is skipped so unqualified cross-module /// references stay unambiguous. case duplicateOfDependency /// A class member (property or method) is already declared, with an /// identical Swift name, by an ancestor class planned in this module; /// the subclass copy is redundant (GObject inheritance provides it). case inheritedMember } /// A single skipped symbol: what was skipped, and why. /// /// Entries are written to `skip-reports/.json` by the CLI and diffed /// by `scripts/compile-gate.sh` against `regression/tierN/` (JSON files only). public struct SkipEntry: Codable, Equatable, Sendable { /// Fully qualified GIR symbol name, e.g. `"Gtk.Widget.measure"`. public let symbol: String /// The C identifier of the symbol, when known (e.g. `"gtk_widget_measure"`). public let cIdentifier: String? /// The category of the skip. public let reason: SkipReason /// Human-readable specifics, e.g. `"parameter 'baseline' has direction=out"`. public let detail: String /// Creates a skip entry. /// /// - Parameters: /// - symbol: Fully qualified GIR symbol name. /// - cIdentifier: The C identifier, if known. /// - reason: The skip category. /// - detail: Human-readable specifics for the report. public init(symbol: String, cIdentifier: String? = nil, reason: SkipReason, detail: String) { self.symbol = symbol self.cIdentifier = cIdentifier self.reason = reason self.detail = detail } } /// Binding coverage statistics for one generated module. /// /// Coverage is the fraction of introspectable callables that received a /// complete binding plan. The compile gate requires coverage to be public struct CoverageStats: Codable, Equatable, Sendable { /// Number of callables successfully planned and emitted. public var boundCallables: Int /// Total introspectable callables considered (bound + skipped). public var totalCallables: Int /// Number of types successfully planned and emitted. public var boundTypes: Int /// Total introspectable types considered (bound + skipped). public var totalTypes: Int /// Namespace-level callbacks successfully planned and emitted (D6). public var boundCallbacks: Int /// Total namespace-level callbacks considered (bound + skipped). public var totalCallbacks: Int /// GObject signals successfully planned and emitted (Phase D). public var boundSignals: Int /// Total signals considered (bound + skipped). public var totalSignals: Int public init(boundCallables: Int = 0, totalCallables: Int = 0, boundTypes: Int = 0, totalTypes: Int = 0, boundCallbacks: Int = 0, totalCallbacks: Int = 0, boundSignals: Int = 0, totalSignals: Int = 0) { self.boundCallables = boundCallables; self.totalCallables = totalCallables self.boundTypes = boundTypes; self.totalTypes = totalTypes self.boundCallbacks = boundCallbacks; self.totalCallbacks = totalCallbacks self.boundSignals = boundSignals; self.totalSignals = totalSignals } } /// The complete skip report for one generated module. /// /// Serialized as stable, sorted, pretty-printed JSON so reports are /// line-diffable by the compile gate and reviewable in version control. public struct SkipReport: Codable, Equatable, Sendable { /// The Swift module this report describes (e.g. `"GLib"`). public let module: String /// All skipped symbols, sorted by symbol name. public let entries: [SkipEntry] /// Coverage statistics for the module. public let stats: CoverageStats /// Creates a skip report, sorting entries by symbol name for stable output. /// /// - Parameters: /// - module: The Swift module name. /// - entries: Skipped symbols in any order; stored sorted. /// - stats: Coverage statistics for the module. public init(module: String, entries: [SkipEntry], stats: CoverageStats) { self.module = module self.entries = entries.sorted { $0.symbol < $1.symbol } self.stats = stats } /// Encodes the report as stable pretty-printed JSON with sorted keys. /// /// - Returns: UTF-8 JSON data suitable for writing to disk and diffing. /// - Throws: An `EncodingError` if serialization fails. public func jsonData() throws -> Data { let encoder = JSONEncoder() encoder.outputFormatting = [.prettyPrinted, .sortedKeys, .withoutEscapingSlashes] return try encoder.encode(self) } } // MARK: - Type Plans /// The binding plan for a single GIR type (enum, bitfield, constant, alias, /// class, interface, record, or callback). The renderer consumes these and /// never sees `GIRType`, `IRModel`, or the registry directly. public enum TypePlan: Sendable { /// An enumeration with deduplicated raw values. case enumeration(EnumPlan) /// An OptionSet bitfield with verbatim raw values. case bitfield(BitfieldPlan) /// A global constant. case constant(ConstantPlan) /// A type alias. case alias(AliasPlan) /// A GObject class wrapper. case `class`(ClassPlan) /// A GObject interface wrapper. case interface(InterfacePlan) /// A boxed record wrapper. case record(RecordPlan) /// A callable (function, method, or constructor). case callable(CallablePlan) /// A GIO `*_async`/`*_finish` pair, rendered as one Swift `async` /// method, at namespace level (paired ``s, not class/record/ /// interface members — those live on `ClassPlan.asyncMethods` etc.). case asyncCallable(AsyncCallablePlan) /// A namespace-level callback typealias. case callback(CallbackTypePlan) } /// The plan for a GIR enumeration: cases and alias variables (deduplicated /// raw values). public struct EnumPlan: Equatable, Sendable { /// The Swift enum name (unqualified), e.g. `"ConnectFlags"`. public let name: String /// The C type name, e.g. `"GConnectFlags"`. public let cType: String /// The primary cases (first occurrence of each raw value). public let cases: [EnumCase] /// Duplicate raw values emitted as `public static var` aliases. public let aliases: [EnumAlias] /// Whether this enum has a GType registration (for GValue access). public let hasGType: Bool /// Documentation from the GIR `` element. public let doc: String? public init(name: String, cType: String, cases: [EnumCase], aliases: [EnumAlias], hasGType: Bool = false, doc: String? = nil) { self.name = name; self.cType = cType; self.cases = cases self.aliases = aliases; self.hasGType = hasGType; self.doc = doc } } /// A single case of an enumeration: name, raw value, and C identifier. public struct EnumCase: Equatable, Sendable { /// The Swift case name (keyword-escaped), e.g. `"after"`. public let name: String /// The numeric raw value as a string, e.g. `"1"`. public let rawValue: String /// The full C identifier, e.g. `"G_CONNECT_AFTER"`. public let cIdentifier: String public init(name: String, rawValue: String, cIdentifier: String) { self.name = name; self.rawValue = rawValue; self.cIdentifier = cIdentifier } } /// A duplicate raw-value member emitted as a `public static var` alias. public struct EnumAlias: Equatable, Sendable { /// The alias variable name, e.g. `"baselineFill"`. public let name: String /// The primary case this alias points to, e.g. `"baseline"`. public let targetCaseName: String public init(name: String, targetCaseName: String) { self.name = name; self.targetCaseName = targetCaseName } } /// The plan for a GIR bitfield (flags type) emitted as an `OptionSet`. public struct BitfieldPlan: Equatable, Sendable { /// The Swift struct name (unqualified), e.g. `"ConnectFlags"`. public let name: String /// The C type name, e.g. `"GConnectFlags"`. public let cType: String /// The flag members with their verbatim raw values. public let members: [EnumCase] /// Whether this bitfield has a GType registration. public let hasGType: Bool /// Documentation from the GIR `` element. public let doc: String? public init(name: String, cType: String, members: [EnumCase], hasGType: Bool = false, doc: String? = nil) { self.name = name; self.cType = cType; self.members = members self.hasGType = hasGType; self.doc = doc } } /// The plan for a global constant. public struct ConstantPlan: Equatable, Sendable { /// The Swift name of the constant, e.g. `"majorVersion"`. public let name: String /// The original GIR constant name, e.g. `"MAJOR_VERSION"`. Rendered into /// the doc comment so the C spelling stays greppable after the rename. public let girName: String /// The literal value as a string, e.g. `"2"`. public let value: String /// The Swift type of the constant, e.g. `"Int"`. public let swiftType: String /// Documentation from the GIR `` element. public let doc: String? public init(name: String, girName: String, value: String, swiftType: String, doc: String? = nil) { self.name = name; self.girName = girName; self.value = value self.swiftType = swiftType; self.doc = doc } } /// The plan for a type alias. public struct AliasPlan: Equatable, Sendable { /// The Swift alias name, e.g. `"MyType"`. public let name: String /// The target type name, module-qualified when cross-module. public let swiftType: String /// Documentation from the GIR `` element. public let doc: String? public init(name: String, swiftType: String, doc: String? = nil) { self.name = name; self.swiftType = swiftType; self.doc = doc } } /// The plan for a GObject signal connection. /// /// Each signal on a class or interface generates a typed trampoline /// (`@convention(c)` static func) and a `connect(…)` method that /// boxes the Swift closure, passes it to `g_signal_connect_data`, /// and returns a `SignalHandle`. public struct SignalPlan: Equatable, Sendable { /// The owning class's Swift name, e.g. `"Object"`. public let owningClassName: String /// The GIR signal name, e.g. `"clicked"`, `"notify"`. public let girName: String /// The camelCased Swift name, e.g. `"clicked"`. public let swiftName: String /// Whether the signal supports detail strings (`"notify::label"`). public let isDetailed: Bool /// The signal handler parameters (includes implicit instance param at cArgIndex 0). public let parameters: [ParameterPlan] /// The return mapping, or `nil` for `void`. public let returnMapping: Mapping? /// The `@convention(c)` trampoline's C-level name, unique per module. public let trampolineCName: String /// `true` when the owning type is a `protocol` (GObject interface) /// rather than a concrete class — the trampoline's instance parameter /// must be wrapped via the interface's `Ref` concrete wrapper, not the /// interface protocol itself (which has no initializers). public let ownerIsInterface: Bool /// Documentation from the GIR `` element. public let doc: String? public init(owningClassName: String, girName: String, swiftName: String, isDetailed: Bool = false, parameters: [ParameterPlan] = [], returnMapping: Mapping? = nil, trampolineCName: String, ownerIsInterface: Bool = false, doc: String? = nil) { self.owningClassName = owningClassName; self.girName = girName self.swiftName = swiftName; self.isDetailed = isDetailed self.parameters = parameters; self.returnMapping = returnMapping self.trampolineCName = trampolineCName; self.ownerIsInterface = ownerIsInterface self.doc = doc } } /// The plan for a namespace-level callback type. /// /// Renders as both a C-compatible `@convention(c)` typealias for C callbacks /// and a Swift-friendly `@escaping` typealias for use in generated connect methods. public struct CallbackTypePlan: Equatable, Sendable { /// The Swift type name, e.g. `"GClosureNotify"`. public let name: String /// The Swift closure form, e.g. `"@escaping (UnsafeMutableRawPointer?) -> Void"`. public let swiftType: String /// The C-compatible convention(c) form for trampoline signatures. public let cSwiftType: String /// Documentation from the GIR `` element. public let doc: String? public init(name: String, swiftType: String, cSwiftType: String, doc: String? = nil) { self.name = name; self.swiftType = swiftType; self.cSwiftType = cSwiftType; self.doc = doc } } /// The plan for a GObject class wrapper. public struct ClassPlan: Equatable, Sendable { /// The Swift class name (unqualified), e.g. `"Object"`. public let name: String /// The fully qualified GIR name (`"."`), e.g. /// `"GObject.Object"`. Unlike `name`/`parent`, which are Swift spellings /// that may collide across modules sharing a simple name (e.g. /// `Gst.Object` vs `GObject.Object`), this and `parentGIRName` are /// always unambiguous — the safe key for any cross-module ancestor /// lookup (see `planModules`'s inherited-member dedup post-pass). public let girName: String /// The C type name, e.g. `"GObject"`. public let cType: String /// The module-qualified Swift parent class name, or `nil` for root. /// E.g. `nil` for `GObject.Object`, `"GObject.InitiallyUnowned"` for `Gtk.Widget`. public let parent: String? /// The parent's fully qualified GIR name, or `nil` for root. See `girName`. public let parentGIRName: String? /// Whether the class is `open` (subclassed by at least one other type). public let isOpen: Bool /// Whether the class is abstract — no constructors emitted. public let isAbstract: Bool /// The `glib:get-type` function name, e.g. `"g_object_get_type"`. public let getTypeFunction: String? /// Whether this class descends from `InitiallyUnowned`, requiring /// `g_object_ref_sink` on construction. public let descendsFromInitiallyUnowned: Bool /// The C function that takes a reference on this class's underlying /// pointer (`init(retaining:)`). `"g_object_ref"` for ordinary /// `GObject`-derived classes; overridden for classes that root their own /// non-`GObject` fundamental type hierarchy (e.g. `GParamSpec`'s /// `g_param_spec_ref_sink` — see `TypeRegistry.refUnrefFunctions`). public let refFunc: String /// The C function that releases a reference on this class's underlying /// pointer, called from the root class's `isolated deinit`. /// `"g_object_unref"` for ordinary `GObject`-derived classes; /// overridden for classes that root their own non-`GObject` fundamental /// type hierarchy (e.g. `GParamSpec`'s `g_param_spec_unref` — see /// `TypeRegistry.refUnrefFunctions`). public let unrefFunc: String /// Planned constructors (empty for abstract classes). public let constructors: [CallablePlan] /// Planned instance methods. public let methods: [CallablePlan] /// Planned static/class functions. public let functions: [CallablePlan] /// Planned GObject properties. public let properties: [PropertyPlan] /// Planned GObject signals. public let signals: [SignalPlan] /// Module-qualified names of implemented interfaces (e.g. ["GObject.TypePlugin"]). public let interfaces: [String] /// Planned GIO `*_async`/`*_finish` pairs, each rendered as one Swift /// `async` method after `methods`. public let asyncMethods: [AsyncCallablePlan] /// Documentation from the GIR `` element. public let doc: String? public init(name: String, girName: String, cType: String, parent: String? = nil, parentGIRName: String? = nil, isOpen: Bool = false, isAbstract: Bool = false, getTypeFunction: String? = nil, descendsFromInitiallyUnowned: Bool = false, refFunc: String = "g_object_ref", unrefFunc: String = "g_object_unref", interfaces: [String] = [], constructors: [CallablePlan] = [], methods: [CallablePlan] = [], functions: [CallablePlan] = [], properties: [PropertyPlan] = [], signals: [SignalPlan] = [], asyncMethods: [AsyncCallablePlan] = [], doc: String? = nil) { self.name = name; self.girName = girName; self.cType = cType self.parent = parent; self.parentGIRName = parentGIRName self.isOpen = isOpen; self.isAbstract = isAbstract self.getTypeFunction = getTypeFunction self.descendsFromInitiallyUnowned = descendsFromInitiallyUnowned self.refFunc = refFunc self.unrefFunc = unrefFunc self.interfaces = interfaces self.constructors = constructors; self.methods = methods self.functions = functions; self.properties = properties self.signals = signals self.asyncMethods = asyncMethods self.doc = doc } } public struct RecordPlan: Equatable, Sendable { public let name: String public let cType: String public let getTypeFunction: String? public let copyFunction: String? /// Whether `copyFunction` returns `void` rather than the (possibly new) /// pointer - true for plain refcounting functions like /// `gst_atomic_queue_ref` that bump the refcount in place instead of /// following the `GstBuffer`/`GObject`-style `T *ref(T *)` convention. /// Determines whether `init(retaining:)` reassigns `self.pointer` from /// the call's return value or keeps the argument pointer as-is. public let copyReturnsVoid: Bool public let freeFunction: String? /// Constructors declared on the boxed record. public let constructors: [CallablePlan] /// Instance methods declared on the boxed record. public let methods: [CallablePlan] /// Static functions associated with the boxed record. public let functions: [CallablePlan] /// Planned GIO `*_async`/`*_finish` pairs, each rendered as one Swift /// `async` method after `methods`. public let asyncMethods: [AsyncCallablePlan] public let doc: String? public init(name: String, cType: String, getTypeFunction: String? = nil, copyFunction: String? = nil, copyReturnsVoid: Bool = false, freeFunction: String? = nil, constructors: [CallablePlan] = [], methods: [CallablePlan] = [], functions: [CallablePlan] = [], asyncMethods: [AsyncCallablePlan] = [], doc: String? = nil) { self.name = name; self.cType = cType self.getTypeFunction = getTypeFunction self.copyFunction = copyFunction; self.copyReturnsVoid = copyReturnsVoid self.freeFunction = freeFunction self.constructors = constructors; self.methods = methods self.functions = functions self.asyncMethods = asyncMethods self.doc = doc } } /// The plan for a GObject interface wrapper. public struct InterfacePlan: Equatable, Sendable { public let name: String public let cType: String public let prereqs: [String] /// The Swift name of a prerequisite that is a *class* (not another /// interface), if any — e.g. `TlsServerConnection` prerequisites /// `TlsConnection`. The protocol inheritance clause then constrains /// `Self: TlsConnection`, so the concrete `Ref` wrapper must /// subclass it directly (inheriting its `pointer`/init/deinit) rather /// than declaring its own bare ref-counted storage. public let classPrereq: String? public let getTypeFunction: String? /// The interface's instance methods, rendered as protocol requirements. /// The implementing class supplies each method body (the C symbol lives on /// the class, not the interface — see `planInterface`). public let methods: [CallablePlan] /// Properties declared by this interface, rendered as protocol requirements. public let properties: [PropertyPlan] /// Signals declared by this interface. public let signals: [SignalPlan] /// Planned GIO `*_async`/`*_finish` pairs, rendered as default `async` /// method implementations inside the protocol extension, after `methods`. public let asyncMethods: [AsyncCallablePlan] /// The module-qualified Swift name, e.g. `"GObject.TypePlugin"`. /// Used to match against `ClassPlan.interfaces` entries. public let qualifiedName: String /// `true` when this interface's implementers are GObject-derived (i.e. /// `var pointer` refers to a ref-counted `GObject*`). Gates emission of /// the concrete `Ref` wrapper, which manages that refcount. public let isGObject: Bool public let doc: String? public init(name: String, cType: String, prereqs: [String] = [], classPrereq: String? = nil, getTypeFunction: String? = nil, methods: [CallablePlan] = [], properties: [PropertyPlan] = [], signals: [SignalPlan] = [], asyncMethods: [AsyncCallablePlan] = [], qualifiedName: String = "", isGObject: Bool = true, doc: String? = nil) { self.name = name; self.cType = cType; self.prereqs = prereqs self.classPrereq = classPrereq self.getTypeFunction = getTypeFunction; self.methods = methods self.properties = properties; self.signals = signals self.asyncMethods = asyncMethods self.qualifiedName = qualifiedName self.isGObject = isGObject self.doc = doc } } /// How a single property accessor (the getter or the setter) is implemented. /// /// The planner prefers ``delegate`` whenever GIR states a `getter=`/`setter=` /// method that was itself successfully planned, because that method already /// encodes the correct nullability and ownership. It falls back to ``gvalue`` /// — the uniform GObject property machinery — for pure GObject properties that /// have no dedicated C accessor. public enum PropertyAccessorPlan: Equatable, Sendable { /// Read or write the value through the GObject GValue machinery: /// `g_value_init(&v, typeMacro)` + `g_object_get_property` / `_set_property` /// + `g_value_get_` / `g_value_set_`. case gvalue(typeMacro: String, valueSuffix: String, hasCopyFunction: Bool = false) /// Forward to an already-generated accessor method on the same type, named /// by the GIR `getter=` / `setter=` attribute (e.g. `getLabel`/`setLabel`). /// `argumentLabel` is the setter method's parameter label, or `nil` for a /// getter (which takes no arguments). case delegate(method: String, argumentLabel: String?) } /// The plan for one GObject property: a named, typed Swift computed property. /// /// Each accessor is planned independently as a ``PropertyAccessor`` — either a /// delegation to a generated method or the GValue machinery. A property whose /// type has no `GValueOps` AND no delegable accessor is skipped with /// ``SkipReason/unsupportedGValueCategory``. public struct PropertyPlan: Equatable, Sendable { /// The Swift property name (lowerCamelCase), e.g. `"sourceProperty"`. public let swiftName: String /// The original GIR property name, e.g. `"source-property"`. Used for the /// `g_object_get_property` / `g_object_set_property` name argument. public let girName: String /// The Swift type of the property, e.g. `"String"`, `"Object?"`, or /// `"BindingFlags"`. When an accessor is delegated, this is the delegated /// method's exact type (so nullability is inherited). public let swiftType: String /// The read accessor. Always present — even a write-only GObject property is /// back-read through GValue, since a Swift computed property needs a getter. public let getter: PropertyAccessorPlan /// The write accessor, or `nil` for a read-only property. Construct-only /// properties are read-only (a runtime setter would silently no-op). public let setter: PropertyAccessorPlan? /// Documentation from the GIR `` element. public let doc: String? public init(swiftName: String, girName: String, swiftType: String, getter: PropertyAccessorPlan, setter: PropertyAccessorPlan?, doc: String? = nil) { self.swiftName = swiftName; self.girName = girName self.swiftType = swiftType self.getter = getter; self.setter = setter self.doc = doc } } /// The complete plan for one Swift module: every type planned, every symbol /// skipped, and the coverage statistics computed from them. public struct ModulePlan: Sendable { /// The Swift module name, e.g. `"GLib"`. public let module: String /// Direct dependency modules this module's files must `import`, e.g. /// `["GLib", "GModule", "GObject"]` for `Gio`. Sorted, deduplicated. public let dependencyModules: [String] /// All successfully planned types. public let types: [TypePlan] /// Every skipped symbol with its reason. public let skips: [SkipEntry] /// Coverage statistics derived from planned and skipped counts. public let coverage: CoverageStats public init(module: String, dependencyModules: [String] = [], types: [TypePlan], skips: [SkipEntry], coverage: CoverageStats) { self.module = module; self.dependencyModules = dependencyModules; self.types = types; self.skips = skips self.coverage = coverage } /// The skip report serialised from this module's skips and coverage. public var skipReport: SkipReport { SkipReport(module: module, entries: skips, stats: coverage) } } // MARK: - Callable Plans /// The complete binding plan for one callable (function, method, or constructor). /// /// Every parameter has been fully mapped by the TypeMapper; the renderer only /// combines the `Mapping` values into a Swift function signature and a C call. public struct CallablePlan: Equatable, Sendable { /// The Swift name of the function/method/constructor (keyword-escaped). public let name: String /// The C function identifier, e.g. `"gtk_widget_set_visible"`. public let cIdentifier: String /// The parameters in Swift declaration order. public let parameters: [ParameterPlan] /// The return mapping, or `nil` for a void function. public let returnMapping: Mapping? /// `true` when this callable is a class/static function (not an instance /// method). Constructor callables are implicitly static. public let isStatic: Bool /// `true` when this callable is a constructor. public let isConstructor: Bool /// The ownership init variant for constructor callables: `nil` for /// non-constructors; `.takingOwnership`, `.retaining`, or /// `.sinkingRef` for constructors. public let ownershipInit: OwnershipInit? /// `true` when this callable takes a trailing `GError**` and can throw. public let throwsError: Bool /// `true` when an ancestor class declares an instance method of the /// same Swift selector (name + arity) — e.g. `Gst.Pipeline.getBus()` /// narrowing `Gst.Element.getBus()`'s return type. Emits the `override` /// keyword, required by Swift whenever a subclass redeclares a /// same-selector member rather than overloading it. public let isOverride: Bool /// Documentation from the GIR `` element. public let doc: String? public init(name: String, cIdentifier: String, parameters: [ParameterPlan], returnMapping: Mapping? = nil, isStatic: Bool = false, isConstructor: Bool = false, ownershipInit: OwnershipInit? = nil, throwsError: Bool = false, isOverride: Bool = false, doc: String? = nil) { self.name = name; self.cIdentifier = cIdentifier; self.parameters = parameters self.returnMapping = returnMapping; self.isStatic = isStatic self.isConstructor = isConstructor; self.ownershipInit = ownershipInit self.throwsError = throwsError; self.isOverride = isOverride; self.doc = doc } } /// How a constructor takes ownership of the new GObject instance. public enum OwnershipInit: String, Equatable, Sendable { /// `transfer-ownership="full"`: store the pointer, no additional ref. case takingOwnership /// `transfer-ownership="none"`, non-floating: call `g_object_ref`. case retaining /// The class descends from `InitiallyUnowned`: call `g_object_ref_sink`. case sinkingRef } /// One parameter of a `CallablePlan`: its Swift name, C argument position, /// and the complete type mapping. public struct ParameterPlan: Equatable, Sendable { /// The Swift parameter name (keyword-escaped). public let swiftName: String /// The zero-based index in the C function's argument list (all parameters, /// including instance parameter). public let cArgIndex: Int /// The complete type mapping for this parameter. public let mapping: Mapping /// `true` when this parameter is the implicit instance (`self`). public let isInstanceParameter: Bool /// `true` if this parameter has `direction="out"` and will be returned from /// the Swift function rather than passed as an argument. public let isOutParameter: Bool /// For callback-box params: the C arg index of the separate user-data /// parameter this callback feeds. `nil` when this param doubles as /// its own user-data (`closureIndex == cArgIndex`). public let closureIndex: Int? /// For callback-box params: the C arg index of the separate DestroyNotify /// parameter. `nil` when none. public let destroyIndex: Int? /// When set, this C param is a synthesized array length (argc); its value is /// `.count` and it is omitted from the Swift signature. public let synthesizedLengthOf: String? /// The `GAsyncReadyCallback`-protocol role of this parameter, or `nil` /// for an ordinary parameter. Set only on the trailing callback/ /// user-data pair of a GIO `*_async` starter; such parameters are /// filled by the generated async bridge and omitted from the Swift /// signature (see `swiftSignature`, `cArguments`). public let asyncRole: AsyncParameterRole? public init(swiftName: String, cArgIndex: Int, mapping: Mapping, isInstanceParameter: Bool = false, isOutParameter: Bool = false, closureIndex: Int? = nil, destroyIndex: Int? = nil, synthesizedLengthOf: String? = nil, asyncRole: AsyncParameterRole? = nil) { self.swiftName = swiftName; self.cArgIndex = cArgIndex self.mapping = mapping; self.isInstanceParameter = isInstanceParameter self.isOutParameter = isOutParameter self.closureIndex = closureIndex; self.destroyIndex = destroyIndex self.synthesizedLengthOf = synthesizedLengthOf self.asyncRole = asyncRole } } /// The role a C parameter plays in the `GAsyncReadyCallback` protocol of a /// GIO async starter. Such parameters are filled by the generated bridge /// and omitted from the Swift signature. public enum AsyncParameterRole: Equatable, Sendable { /// The `GAsyncReadyCallback` argument. case callback /// The callback's `user_data` argument. case userData } /// The plan for one GIO asynchronous operation: the `*_async` starter /// paired with its `*_finish` completion, rendered as a single Swift /// `async` method. public struct AsyncCallablePlan: Equatable, Sendable { /// The starter callable. Its callback and user-data parameters carry a /// non-nil `asyncRole` and never appear in the Swift signature. public let starter: CallablePlan /// The paired `*_finish` callable, already planned on the same owner. public let finish: CallablePlan /// The Swift type qualifying `finish` when it is static; `nil` for /// instance methods and namespace-level functions. public let finishOwner: String? public init(starter: CallablePlan, finish: CallablePlan, finishOwner: String? = nil) { self.starter = starter; self.finish = finish; self.finishOwner = finishOwner } } extension Mapping { /// Maps a `[String]` parameter to a NULL-terminated C `char **` array. static let stringArrayMapping = Mapping( swiftType: "[String]", cSwiftType: "UnsafeMutablePointer?>?", marshalIn: .stringArrayToC, marshalOut: .unsupported(reason: "C array return not yet bridged")) /// Maps a `[String]` parameter to a NULL-terminated C `const char * const *` array. static let constStringArrayMapping = Mapping( swiftType: "[String]", cSwiftType: "UnsafePointer?>?", marshalIn: .stringConstArrayToC, marshalOut: .unsupported(reason: "C array return not yet bridged")) /// Maps a `[String]` parameter to a C `const char **` (const elements, /// mutable outer pointer), NULL-terminated. static let constElementStringArrayMapping = Mapping( swiftType: "[String]", cSwiftType: "UnsafeMutablePointer?>?", marshalIn: .stringConstElementArrayToC, marshalOut: .unsupported(reason: "C array return not yet bridged")) /// Maps a C array of object/interface pointers to `[Wrapper]`. /// - Parameter element: The already-mapped element type. static func objectArrayMapping(element: Mapping) -> Mapping { Mapping(swiftType: "[\(element.swiftType)]", cSwiftType: "UnsafeMutableRawPointer?", marshalIn: .objectArrayToC, marshalOut: .unsupported(reason: "C array return not yet bridged"), category: element.category) } /// Maps a contiguous C buffer of scalars to `[T]`. /// - Parameter element: The already-mapped element type. static func scalarArrayMapping(element: Mapping) -> Mapping { Mapping(swiftType: "[\(element.swiftType)]", cSwiftType: "UnsafeMutablePointer<\(element.swiftType)>?", marshalIn: .scalarArrayToC, marshalOut: .unsupported(reason: "C array return not yet bridged")) } }