nitro-codegen
Version:
The code-generator for react-native-nitro-modules.
86 lines (74 loc) • 2.71 kB
text/typescript
import { indent } from '../../utils.js'
import { createFileMetadataString } from '../helpers.js'
import type { SourceFile } from '../SourceFile.js'
import type { FunctionType } from '../types/FunctionType.js'
import { SwiftCxxBridgedType } from './SwiftCxxBridgedType.js'
import { getBridgeNamespace } from './SwiftHybridObjectBridge.js'
export function createSwiftFunctionBridge(
functionType: FunctionType
): SourceFile {
const swiftClassName = functionType.specializationName
const argsTypes = functionType.parameters.map((p) => {
const bridged = new SwiftCxxBridgedType(p)
return `${p.escapedName}: ${bridged.getTypeCode('swift')}`
})
const returnType = new SwiftCxxBridgedType(functionType.returnType)
const argsForward = functionType.parameters.map((p) => {
const bridged = new SwiftCxxBridgedType(p)
return bridged.parseFromCppToSwift(p.escapedName, 'swift')
})
let body: string
if (functionType.returnType.kind === 'void') {
body = `
self.closure(${argsForward.join(', ')})
`.trim()
} else {
body = `
let __result: ${functionType.returnType.getCode('swift')} = self.closure(${argsForward.join(', ')})
return ${returnType.parseFromSwiftToCpp('__result', 'swift')}
`.trim()
}
const code = `
${createFileMetadataString(`${swiftClassName}.swift`)}
import NitroModules
/**
* Wraps a Swift \`${functionType.getCode('swift')}\` as a class.
* This class can be used from C++, e.g. to wrap the Swift closure as a \`std::function\`.
*/
public final class ${swiftClassName} {
public typealias bridge = ${getBridgeNamespace()}
private let closure: ${functionType.getCode('swift')}
public init(_ closure: @escaping ${functionType.getCode('swift')}) {
self.closure = closure
}
@inline(__always)
public func call(${argsTypes.join(', ')}) -> ${returnType.getTypeCode('swift')} {
${indent(body, ' ')}
}
/**
* Casts this instance to a retained unsafe raw pointer.
* This acquires one additional strong reference on the object!
*/
@inline(__always)
public func toUnsafe() -> UnsafeMutableRawPointer {
return Unmanaged.passRetained(self).toOpaque()
}
/**
* Casts an unsafe pointer to a \`${swiftClassName}\`.
* The pointer has to be a retained opaque \`Unmanaged<${swiftClassName}>\`.
* This removes one strong reference from the object!
*/
@inline(__always)
public static func fromUnsafe(_ pointer: UnsafeMutableRawPointer) -> ${swiftClassName} {
return Unmanaged<${swiftClassName}>.fromOpaque(pointer).takeRetainedValue()
}
}
`.trim()
return {
content: code,
language: 'swift',
name: `${swiftClassName}.swift`,
platform: 'ios',
subdirectory: [],
}
}