958 lines
46 KiB
Swift
958 lines
46 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
|
|
/// 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 `<Name>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/<Module>.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 `<function>`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 `<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. `"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 `<doc>` 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 `<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 signal connection.
|
|
///
|
|
/// Each signal on a class or interface generates a typed trampoline
|
|
/// (`@convention(c)` static func) and a `connect<Name>(…)` 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 `<doc>` 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 `<doc>` 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 (`"<Namespace>.<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 `<doc>` 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 `<Name>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 `<Name>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_<suffix>` / `g_value_set_<suffix>`.
|
|
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 `<doc>` 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 `<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, 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
|
|
/// `<name>.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<UnsafeMutablePointer<CChar>?>?",
|
|
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<UnsafePointer<CChar>?>?",
|
|
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<UnsafePointer<CChar>?>?",
|
|
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"))
|
|
}
|
|
}
|