Boxed records (C4): resolve each record's copy/free function from the GIR copy-function/free-function attribute, else its own ref/copy and unref/free method, and render init(retaining:) plus an isolated deinit. The deinit is isolated because the package's default MainActor isolation makes accessing the non-Sendable pointer from a nonisolated deinit a hard error. The registry uses the same resolution so transfer=none returns copy instead of adopting a borrowed pointer. This supersedes the earlier deferral: the hypothesised OpaquePointer/Sendable barriers either did not hold or were solvable. Interfaces (C5): plan each interface method through planMethod and render it as a protocol requirement (no body); the conforming class supplies the C call.
557 lines
24 KiB
Swift
557 lines
24 KiB
Swift
// 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
|
|
/// 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
|
|
/// Access the underlying pointer of an object or interface wrapper.
|
|
case objectPointer
|
|
/// Pass the `rawValue` of an enum (Int → C int).
|
|
case enumRaw
|
|
/// Pass the `rawValue` of a bitfield (UInt32 → C uint).
|
|
case bitfieldRaw
|
|
/// Pass the pointer of a boxed record wrapper.
|
|
case boxedPointer
|
|
/// 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.
|
|
case stringCopy(free: Bool)
|
|
/// 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?)
|
|
/// 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 and
|
|
/// any follow-on cast for the type.
|
|
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
|
|
/// Whether the getter result needs a cast to the specific type (e.g.
|
|
/// `g_value_get_enum` returns a bare `gint` and must be cast to the enum).
|
|
public let needsCast: Bool
|
|
|
|
public init(typeMacro: String, getterSuffix: String, setterSuffix: String, needsCast: Bool = false) {
|
|
self.typeMacro = typeMacro; self.getterSuffix = getterSuffix
|
|
self.setterSuffix = setterSuffix; self.needsCast = needsCast
|
|
}
|
|
}
|
|
|
|
/// 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
|
|
/// 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
|
|
}
|
|
|
|
/// A single skipped symbol: what was skipped, and why.
|
|
///
|
|
/// Entries are written to `skip-reports/<Module>.json` by the CLI and diffed
|
|
/// by `scripts/compile-gate.sh` against `docs/skip-baseline/`.
|
|
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
|
|
/// monotonically non-decreasing across changes.
|
|
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
|
|
|
|
/// Creates coverage statistics.
|
|
///
|
|
/// - Parameters:
|
|
/// - boundCallables: Callables successfully planned and emitted.
|
|
/// - totalCallables: Total introspectable callables considered.
|
|
/// - boundTypes: Types successfully planned and emitted.
|
|
/// - totalTypes: Total introspectable types considered.
|
|
public init(boundCallables: Int = 0, totalCallables: Int = 0, boundTypes: Int = 0, totalTypes: Int = 0) {
|
|
self.boundCallables = boundCallables
|
|
self.totalCallables = totalCallables
|
|
self.boundTypes = boundTypes
|
|
self.totalTypes = totalTypes
|
|
}
|
|
}
|
|
|
|
/// 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)
|
|
}
|
|
|
|
/// 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 `<doc>` 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 `<doc>` 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. `"MAJOR_VERSION"`.
|
|
public let name: 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 `<doc>` element.
|
|
public let doc: String?
|
|
|
|
public init(name: String, value: String, swiftType: String, doc: String? = nil) {
|
|
self.name = name; 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 `<doc>` 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 class wrapper.
|
|
public struct ClassPlan: Equatable, Sendable {
|
|
/// The Swift class name (unqualified), e.g. `"Object"`.
|
|
public let name: 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?
|
|
/// 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
|
|
/// 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]
|
|
/// Module-qualified names of implemented interfaces (e.g. ["GObject.TypePlugin"]).
|
|
public let interfaces: [String]
|
|
/// Documentation from the GIR `<doc>` element.
|
|
public let doc: String?
|
|
|
|
public init(name: String, cType: String, parent: String? = nil,
|
|
isOpen: Bool = false, isAbstract: Bool = false,
|
|
getTypeFunction: String? = nil,
|
|
descendsFromInitiallyUnowned: Bool = false,
|
|
interfaces: [String] = [],
|
|
constructors: [CallablePlan] = [], methods: [CallablePlan] = [],
|
|
functions: [CallablePlan] = [], doc: String? = nil) {
|
|
self.name = name; self.cType = cType; self.parent = parent
|
|
self.isOpen = isOpen; self.isAbstract = isAbstract
|
|
self.getTypeFunction = getTypeFunction
|
|
self.descendsFromInitiallyUnowned = descendsFromInitiallyUnowned
|
|
self.interfaces = interfaces
|
|
self.constructors = constructors; self.methods = methods
|
|
self.functions = functions; self.doc = doc
|
|
}
|
|
}
|
|
|
|
/// The plan for a boxed record wrapper (opaque pointer class).
|
|
public struct RecordPlan: Equatable, Sendable {
|
|
public let name: String
|
|
public let cType: String
|
|
public let getTypeFunction: String?
|
|
public let copyFunction: String?
|
|
public let freeFunction: String?
|
|
public let doc: String?
|
|
|
|
public init(name: String, cType: String, getTypeFunction: String? = nil,
|
|
copyFunction: String? = nil, freeFunction: String? = nil,
|
|
doc: String? = nil) {
|
|
self.name = name; self.cType = cType
|
|
self.getTypeFunction = getTypeFunction
|
|
self.copyFunction = copyFunction; self.freeFunction = freeFunction
|
|
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]
|
|
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]
|
|
public let doc: String?
|
|
|
|
public init(name: String, cType: String, prereqs: [String] = [],
|
|
getTypeFunction: String? = nil, methods: [CallablePlan] = [],
|
|
doc: String? = nil) {
|
|
self.name = name; self.cType = cType; self.prereqs = prereqs
|
|
self.getTypeFunction = getTypeFunction; self.methods = methods; 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
|
|
/// 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, types: [TypePlan], skips: [SkipEntry],
|
|
coverage: CoverageStats) {
|
|
self.module = module; 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
|
|
/// Documentation from the GIR `<doc>` 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, 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.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
|
|
|
|
public init(swiftName: String, cArgIndex: Int, mapping: Mapping,
|
|
isInstanceParameter: Bool = false, isOutParameter: Bool = false) {
|
|
self.swiftName = swiftName; self.cArgIndex = cArgIndex
|
|
self.mapping = mapping; self.isInstanceParameter = isInstanceParameter
|
|
self.isOutParameter = isOutParameter
|
|
}
|
|
}
|