From 2354510090a74bf5e75966e40815704680de5654 Mon Sep 17 00:00:00 2001 From: Sebastian Imlay Date: Wed, 24 Apr 2024 15:02:46 -0400 Subject: [PATCH] Added swift source to tracking --- Cargo.toml | 2 +- Makefile.toml | 18 - .../liveview-native-core-swift/Package.swift | 4 +- .../Sources/LiveViewNativeCore/.gitignore | 2 - .../LiveViewNativeCore.swift | 1733 +++++++++++++++++ 5 files changed, 1736 insertions(+), 23 deletions(-) delete mode 100644 crates/core/liveview-native-core-swift/Sources/LiveViewNativeCore/.gitignore create mode 100644 crates/core/liveview-native-core-swift/Sources/LiveViewNativeCore/LiveViewNativeCore.swift diff --git a/Cargo.toml b/Cargo.toml index 5ede928c7..7ce7764f8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,7 +5,7 @@ members = [ ] [workspace.package] -version = "0.3.0" +version = "0.3.0-alpha" rust-version = "1.64" authors = [ "Paul Schoenfelder ", diff --git a/Makefile.toml b/Makefile.toml index 173299e87..1de7581d2 100644 --- a/Makefile.toml +++ b/Makefile.toml @@ -97,24 +97,6 @@ echo "*************************************" ''' ] -[tasks.check] -category = "Build" -description = "Runs cargo check" -command = "rustup" -args = ["run", "${CARGO_MAKE_TOOLCHAIN}", "cargo", "check", "${@}"] - -[tasks.build] -category = "Build" -description = "Runs cargo build" -command = "rustup" -args = [ - "run", "${CARGO_MAKE_TOOLCHAIN}", - "cargo", "build", - "--profile", "${CARGO_PROFILE}", - "--", "@@remove-empty(CARGO_MAKE_CARGO_VERBOSE_FLAGS)", - "${@}" -] - [tasks.create-lipo-universal-directories] workspace = false private = true diff --git a/crates/core/liveview-native-core-swift/Package.swift b/crates/core/liveview-native-core-swift/Package.swift index a373b334e..54238fbf1 100644 --- a/crates/core/liveview-native-core-swift/Package.swift +++ b/crates/core/liveview-native-core-swift/Package.swift @@ -10,9 +10,9 @@ if useLocalFramework { rustFramework = .binaryTarget( name: "liveview_native_core", path: "../../../target/uniffi/swift/liveview_native_core.xcframework" - ) + ) } else { - let releaseTag = "0.3.0" + let releaseTag = "0.3.0-alpha" let releaseChecksum = "59be62944e5dccf36898d5cf0d6700e5ef87b42cfdab1e8c5721bbe96abe63f3" rustFramework = .binaryTarget( name: "liveview_native_core", diff --git a/crates/core/liveview-native-core-swift/Sources/LiveViewNativeCore/.gitignore b/crates/core/liveview-native-core-swift/Sources/LiveViewNativeCore/.gitignore deleted file mode 100644 index edd32223d..000000000 --- a/crates/core/liveview-native-core-swift/Sources/LiveViewNativeCore/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -LiveViewNativeCore.swift -PhoenixChannelsClient.swift diff --git a/crates/core/liveview-native-core-swift/Sources/LiveViewNativeCore/LiveViewNativeCore.swift b/crates/core/liveview-native-core-swift/Sources/LiveViewNativeCore/LiveViewNativeCore.swift new file mode 100644 index 000000000..1f0d16ec2 --- /dev/null +++ b/crates/core/liveview-native-core-swift/Sources/LiveViewNativeCore/LiveViewNativeCore.swift @@ -0,0 +1,1733 @@ +// This file was autogenerated by some hot garbage in the `uniffi` crate. +// Trust me, you don't want to mess with it! + +// swiftlint:disable all +import Foundation + +// Depending on the consumer's build setup, the low-level FFI code +// might be in a separate module, or it might be compiled inline into +// this module. This is a bit of light hackery to work with both. +#if canImport(LiveViewNativeCoreFFI) + import LiveViewNativeCoreFFI +#endif + +private extension RustBuffer { + // Allocate a new buffer, copying the contents of a `UInt8` array. + init(bytes: [UInt8]) { + let rbuf = bytes.withUnsafeBufferPointer { ptr in + RustBuffer.from(ptr) + } + self.init(capacity: rbuf.capacity, len: rbuf.len, data: rbuf.data) + } + + static func empty() -> RustBuffer { + RustBuffer(capacity: 0, len: 0, data: nil) + } + + static func from(_ ptr: UnsafeBufferPointer) -> RustBuffer { + try! rustCall { ffi_liveview_native_core_rustbuffer_from_bytes(ForeignBytes(bufferPointer: ptr), $0) } + } + + // Frees the buffer in place. + // The buffer must not be used after this is called. + func deallocate() { + try! rustCall { ffi_liveview_native_core_rustbuffer_free(self, $0) } + } +} + +private extension ForeignBytes { + init(bufferPointer: UnsafeBufferPointer) { + self.init(len: Int32(bufferPointer.count), data: bufferPointer.baseAddress) + } +} + +// For every type used in the interface, we provide helper methods for conveniently +// lifting and lowering that type from C-compatible data, and for reading and writing +// values of that type in a buffer. + +// Helper classes/extensions that don't change. +// Someday, this will be in a library of its own. + +private extension Data { + init(rustBuffer: RustBuffer) { + // TODO: This copies the buffer. Can we read directly from a + // Rust buffer? + self.init(bytes: rustBuffer.data!, count: Int(rustBuffer.len)) + } +} + +// Define reader functionality. Normally this would be defined in a class or +// struct, but we use standalone functions instead in order to make external +// types work. +// +// With external types, one swift source file needs to be able to call the read +// method on another source file's FfiConverter, but then what visibility +// should Reader have? +// - If Reader is fileprivate, then this means the read() must also +// be fileprivate, which doesn't work with external types. +// - If Reader is internal/public, we'll get compile errors since both source +// files will try define the same type. +// +// Instead, the read() method and these helper functions input a tuple of data + +private func createReader(data: Data) -> (data: Data, offset: Data.Index) { + (data: data, offset: 0) +} + +// Reads an integer at the current offset, in big-endian order, and advances +// the offset on success. Throws if reading the integer would move the +// offset past the end of the buffer. +private func readInt(_ reader: inout (data: Data, offset: Data.Index)) throws -> T { + let range = reader.offset ..< reader.offset + MemoryLayout.size + guard reader.data.count >= range.upperBound else { + throw UniffiInternalError.bufferOverflow + } + if T.self == UInt8.self { + let value = reader.data[reader.offset] + reader.offset += 1 + return value as! T + } + var value: T = 0 + let _ = withUnsafeMutableBytes(of: &value) { reader.data.copyBytes(to: $0, from: range) } + reader.offset = range.upperBound + return value.bigEndian +} + +// Reads an arbitrary number of bytes, to be used to read +// raw bytes, this is useful when lifting strings +private func readBytes(_ reader: inout (data: Data, offset: Data.Index), count: Int) throws -> [UInt8] { + let range = reader.offset ..< (reader.offset + count) + guard reader.data.count >= range.upperBound else { + throw UniffiInternalError.bufferOverflow + } + var value = [UInt8](repeating: 0, count: count) + value.withUnsafeMutableBufferPointer { buffer in + reader.data.copyBytes(to: buffer, from: range) + } + reader.offset = range.upperBound + return value +} + +// Reads a float at the current offset. +private func readFloat(_ reader: inout (data: Data, offset: Data.Index)) throws -> Float { + return try Float(bitPattern: readInt(&reader)) +} + +// Reads a float at the current offset. +private func readDouble(_ reader: inout (data: Data, offset: Data.Index)) throws -> Double { + return try Double(bitPattern: readInt(&reader)) +} + +// Indicates if the offset has reached the end of the buffer. +private func hasRemaining(_ reader: (data: Data, offset: Data.Index)) -> Bool { + return reader.offset < reader.data.count +} + +// Define writer functionality. Normally this would be defined in a class or +// struct, but we use standalone functions instead in order to make external +// types work. See the above discussion on Readers for details. + +private func createWriter() -> [UInt8] { + return [] +} + +private func writeBytes(_ writer: inout [UInt8], _ byteArr: S) where S: Sequence, S.Element == UInt8 { + writer.append(contentsOf: byteArr) +} + +// Writes an integer in big-endian order. +// +// Warning: make sure what you are trying to write +// is in the correct type! +private func writeInt(_ writer: inout [UInt8], _ value: T) { + var value = value.bigEndian + withUnsafeBytes(of: &value) { writer.append(contentsOf: $0) } +} + +private func writeFloat(_ writer: inout [UInt8], _ value: Float) { + writeInt(&writer, value.bitPattern) +} + +private func writeDouble(_ writer: inout [UInt8], _ value: Double) { + writeInt(&writer, value.bitPattern) +} + +// Protocol for types that transfer other types across the FFI. This is +// analogous go the Rust trait of the same name. +private protocol FfiConverter { + associatedtype FfiType + associatedtype SwiftType + + static func lift(_ value: FfiType) throws -> SwiftType + static func lower(_ value: SwiftType) -> FfiType + static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> SwiftType + static func write(_ value: SwiftType, into buf: inout [UInt8]) +} + +// Types conforming to `Primitive` pass themselves directly over the FFI. +private protocol FfiConverterPrimitive: FfiConverter where FfiType == SwiftType {} + +extension FfiConverterPrimitive { + public static func lift(_ value: FfiType) throws -> SwiftType { + return value + } + + public static func lower(_ value: SwiftType) -> FfiType { + return value + } +} + +// Types conforming to `FfiConverterRustBuffer` lift and lower into a `RustBuffer`. +// Used for complex types where it's hard to write a custom lift/lower. +private protocol FfiConverterRustBuffer: FfiConverter where FfiType == RustBuffer {} + +extension FfiConverterRustBuffer { + public static func lift(_ buf: RustBuffer) throws -> SwiftType { + var reader = createReader(data: Data(rustBuffer: buf)) + let value = try read(from: &reader) + if hasRemaining(reader) { + throw UniffiInternalError.incompleteData + } + buf.deallocate() + return value + } + + public static func lower(_ value: SwiftType) -> RustBuffer { + var writer = createWriter() + write(value, into: &writer) + return RustBuffer(bytes: writer) + } +} + +// An error type for FFI errors. These errors occur at the UniFFI level, not +// the library level. +private enum UniffiInternalError: LocalizedError { + case bufferOverflow + case incompleteData + case unexpectedOptionalTag + case unexpectedEnumCase + case unexpectedNullPointer + case unexpectedRustCallStatusCode + case unexpectedRustCallError + case unexpectedStaleHandle + case rustPanic(_ message: String) + + public var errorDescription: String? { + switch self { + case .bufferOverflow: return "Reading the requested value would read past the end of the buffer" + case .incompleteData: return "The buffer still has data after lifting its containing value" + case .unexpectedOptionalTag: return "Unexpected optional tag; should be 0 or 1" + case .unexpectedEnumCase: return "Raw enum value doesn't match any cases" + case .unexpectedNullPointer: return "Raw pointer value was null" + case .unexpectedRustCallStatusCode: return "Unexpected RustCallStatus code" + case .unexpectedRustCallError: return "CALL_ERROR but no errorClass specified" + case .unexpectedStaleHandle: return "The object in the handle map has been dropped already" + case let .rustPanic(message): return message + } + } +} + +private extension NSLock { + func withLock(f: () throws -> T) rethrows -> T { + lock() + defer { self.unlock() } + return try f() + } +} + +private let CALL_SUCCESS: Int8 = 0 +private let CALL_ERROR: Int8 = 1 +private let CALL_UNEXPECTED_ERROR: Int8 = 2 +private let CALL_CANCELLED: Int8 = 3 + +private extension RustCallStatus { + init() { + self.init( + code: CALL_SUCCESS, + errorBuf: RustBuffer( + capacity: 0, + len: 0, + data: nil + ) + ) + } +} + +private func rustCall(_ callback: (UnsafeMutablePointer) -> T) throws -> T { + try makeRustCall(callback, errorHandler: nil) +} + +private func rustCallWithError( + _ errorHandler: @escaping (RustBuffer) throws -> Error, + _ callback: (UnsafeMutablePointer) -> T +) throws -> T { + try makeRustCall(callback, errorHandler: errorHandler) +} + +private func makeRustCall( + _ callback: (UnsafeMutablePointer) -> T, + errorHandler: ((RustBuffer) throws -> Error)? +) throws -> T { + uniffiEnsureInitialized() + var callStatus = RustCallStatus() + let returnedVal = callback(&callStatus) + try uniffiCheckCallStatus(callStatus: callStatus, errorHandler: errorHandler) + return returnedVal +} + +private func uniffiCheckCallStatus( + callStatus: RustCallStatus, + errorHandler: ((RustBuffer) throws -> Error)? +) throws { + switch callStatus.code { + case CALL_SUCCESS: + return + + case CALL_ERROR: + if let errorHandler = errorHandler { + throw try errorHandler(callStatus.errorBuf) + } else { + callStatus.errorBuf.deallocate() + throw UniffiInternalError.unexpectedRustCallError + } + + case CALL_UNEXPECTED_ERROR: + // When the rust code sees a panic, it tries to construct a RustBuffer + // with the message. But if that code panics, then it just sends back + // an empty buffer. + if callStatus.errorBuf.len > 0 { + throw try UniffiInternalError.rustPanic(FfiConverterString.lift(callStatus.errorBuf)) + } else { + callStatus.errorBuf.deallocate() + throw UniffiInternalError.rustPanic("Rust panic") + } + + case CALL_CANCELLED: + fatalError("Cancellation not supported yet") + + default: + throw UniffiInternalError.unexpectedRustCallStatusCode + } +} + +private func uniffiTraitInterfaceCall( + callStatus: UnsafeMutablePointer, + makeCall: () throws -> T, + writeReturn: (T) -> Void +) { + do { + try writeReturn(makeCall()) + } catch { + callStatus.pointee.code = CALL_UNEXPECTED_ERROR + callStatus.pointee.errorBuf = FfiConverterString.lower(String(describing: error)) + } +} + +private func uniffiTraitInterfaceCallWithError( + callStatus: UnsafeMutablePointer, + makeCall: () throws -> T, + writeReturn: (T) -> Void, + lowerError: (E) -> RustBuffer +) { + do { + try writeReturn(makeCall()) + } catch let error as E { + callStatus.pointee.code = CALL_ERROR + callStatus.pointee.errorBuf = lowerError(error) + } catch { + callStatus.pointee.code = CALL_UNEXPECTED_ERROR + callStatus.pointee.errorBuf = FfiConverterString.lower(String(describing: error)) + } +} + +private class UniffiHandleMap { + private var map: [UInt64: T] = [:] + private let lock = NSLock() + private var currentHandle: UInt64 = 1 + + func insert(obj: T) -> UInt64 { + lock.withLock { + let handle = currentHandle + currentHandle += 1 + map[handle] = obj + return handle + } + } + + func get(handle: UInt64) throws -> T { + try lock.withLock { + guard let obj = map[handle] else { + throw UniffiInternalError.unexpectedStaleHandle + } + return obj + } + } + + @discardableResult + func remove(handle: UInt64) throws -> T { + try lock.withLock { + guard let obj = map.removeValue(forKey: handle) else { + throw UniffiInternalError.unexpectedStaleHandle + } + return obj + } + } + + var count: Int { + map.count + } +} + +// Public interface members begin here. + +private struct FfiConverterInt32: FfiConverterPrimitive { + typealias FfiType = Int32 + typealias SwiftType = Int32 + + public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> Int32 { + return try lift(readInt(&buf)) + } + + public static func write(_ value: Int32, into buf: inout [UInt8]) { + writeInt(&buf, lower(value)) + } +} + +private struct FfiConverterString: FfiConverter { + typealias SwiftType = String + typealias FfiType = RustBuffer + + public static func lift(_ value: RustBuffer) throws -> String { + defer { + value.deallocate() + } + if value.data == nil { + return String() + } + let bytes = UnsafeBufferPointer(start: value.data!, count: Int(value.len)) + return String(bytes: bytes, encoding: String.Encoding.utf8)! + } + + public static func lower(_ value: String) -> RustBuffer { + return value.utf8CString.withUnsafeBufferPointer { ptr in + // The swift string gives us int8_t, we want uint8_t. + ptr.withMemoryRebound(to: UInt8.self) { ptr in + // The swift string gives us a trailing null byte, we don't want it. + let buf = UnsafeBufferPointer(rebasing: ptr.prefix(upTo: ptr.count - 1)) + return RustBuffer.from(buf) + } + } + } + + public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> String { + let len: Int32 = try readInt(&buf) + return try String(bytes: readBytes(&buf, count: Int(len)), encoding: String.Encoding.utf8)! + } + + public static func write(_ value: String, into buf: inout [UInt8]) { + let len = Int32(value.utf8.count) + writeInt(&buf, len) + writeBytes(&buf, value.utf8) + } +} + +public protocol DocumentProtocol: AnyObject { + func children(_ nodeRef: NodeRef) -> [NodeRef] + + func get(_ nodeRef: NodeRef) -> NodeData + + func getAttributes(_ nodeRef: NodeRef) -> [Attribute] + + func getParent(_ nodeRef: NodeRef) -> NodeRef? + + func mergeFragmentJson(_ json: String) throws + + func render() -> String + + func root() -> NodeRef + + func setEventHandler(_ handler: DocumentChangeHandler) +} + +open class Document: + DocumentProtocol +{ + fileprivate let pointer: UnsafeMutableRawPointer! + + /// Used to instantiate a [FFIObject] without an actual pointer, for fakes in tests, mostly. + public struct NoPointer { + public init() {} + } + + // TODO: We'd like this to be `private` but for Swifty reasons, + // we can't implement `FfiConverter` without making this `required` and we can't + // make it `required` without making it `public`. + public required init(unsafeFromRawPointer pointer: UnsafeMutableRawPointer) { + self.pointer = pointer + } + + /// This constructor can be used to instantiate a fake object. + /// - Parameter noPointer: Placeholder value so we can have a constructor separate from the default empty one that may be implemented for classes extending [FFIObject]. + /// + /// - Warning: + /// Any object instantiated with this constructor cannot be passed to an actual Rust-backed object. Since there isn't a backing [Pointer] the FFI lower functions will crash. + public init(noPointer _: NoPointer) { + pointer = nil + } + + public func uniffiClonePointer() -> UnsafeMutableRawPointer { + return try! rustCall { uniffi_liveview_native_core_fn_clone_document(self.pointer, $0) } + } + + // No primary constructor declared for this class. + + deinit { + guard let pointer = pointer else { + return + } + + try! rustCall { uniffi_liveview_native_core_fn_free_document(pointer, $0) } + } + + public static func empty() -> Document { + return try! FfiConverterTypeDocument.lift(try! rustCall { + uniffi_liveview_native_core_fn_constructor_document_empty($0 + ) + }) + } + + public static func parse(_ input: String) throws -> Document { + return try FfiConverterTypeDocument.lift(rustCallWithError(FfiConverterTypeParseError.lift) { + uniffi_liveview_native_core_fn_constructor_document_parse( + FfiConverterString.lower(input), $0 + ) + }) + } + + public static func parseFragmentJson(_ input: String) throws -> Document { + return try FfiConverterTypeDocument.lift(rustCallWithError(FfiConverterTypeRenderError.lift) { + uniffi_liveview_native_core_fn_constructor_document_parse_fragment_json( + FfiConverterString.lower(input), $0 + ) + }) + } + + open func children(_ nodeRef: NodeRef) -> [NodeRef] { + return try! FfiConverterSequenceTypeNodeRef.lift(try! rustCall { + uniffi_liveview_native_core_fn_method_document_children(self.uniffiClonePointer(), + FfiConverterTypeNodeRef.lower(nodeRef), $0) + }) + } + + open func get(_ nodeRef: NodeRef) -> NodeData { + return try! FfiConverterTypeNodeData.lift(try! rustCall { + uniffi_liveview_native_core_fn_method_document_get(self.uniffiClonePointer(), + FfiConverterTypeNodeRef.lower(nodeRef), $0) + }) + } + + open func getAttributes(_ nodeRef: NodeRef) -> [Attribute] { + return try! FfiConverterSequenceTypeAttribute.lift(try! rustCall { + uniffi_liveview_native_core_fn_method_document_get_attributes(self.uniffiClonePointer(), + FfiConverterTypeNodeRef.lower(nodeRef), $0) + }) + } + + open func getParent(_ nodeRef: NodeRef) -> NodeRef? { + return try! FfiConverterOptionTypeNodeRef.lift(try! rustCall { + uniffi_liveview_native_core_fn_method_document_get_parent(self.uniffiClonePointer(), + FfiConverterTypeNodeRef.lower(nodeRef), $0) + }) + } + + open func mergeFragmentJson(_ json: String) throws { try rustCallWithError(FfiConverterTypeRenderError.lift) { + uniffi_liveview_native_core_fn_method_document_merge_fragment_json(self.uniffiClonePointer(), + FfiConverterString.lower(json), $0) + } + } + + open func render() -> String { + return try! FfiConverterString.lift(try! rustCall { + uniffi_liveview_native_core_fn_method_document_render(self.uniffiClonePointer(), $0) + }) + } + + open func root() -> NodeRef { + return try! FfiConverterTypeNodeRef.lift(try! rustCall { + uniffi_liveview_native_core_fn_method_document_root(self.uniffiClonePointer(), $0) + }) + } + + open func setEventHandler(_ handler: DocumentChangeHandler) { try! rustCall { + uniffi_liveview_native_core_fn_method_document_set_event_handler(self.uniffiClonePointer(), + FfiConverterCallbackInterfaceDocumentChangeHandler.lower(handler), $0) + } + } +} + +public struct FfiConverterTypeDocument: FfiConverter { + typealias FfiType = UnsafeMutableRawPointer + typealias SwiftType = Document + + public static func lift(_ pointer: UnsafeMutableRawPointer) throws -> Document { + return Document(unsafeFromRawPointer: pointer) + } + + public static func lower(_ value: Document) -> UnsafeMutableRawPointer { + return value.uniffiClonePointer() + } + + public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> Document { + let v: UInt64 = try readInt(&buf) + // The Rust code won't compile if a pointer won't fit in a UInt64. + // We have to go via `UInt` because that's the thing that's the size of a pointer. + let ptr = UnsafeMutableRawPointer(bitPattern: UInt(truncatingIfNeeded: v)) + if ptr == nil { + throw UniffiInternalError.unexpectedNullPointer + } + return try lift(ptr!) + } + + public static func write(_ value: Document, into buf: inout [UInt8]) { + // This fiddling is because `Int` is the thing that's the same size as a pointer. + // The Rust code won't compile if a pointer won't fit in a `UInt64`. + writeInt(&buf, UInt64(bitPattern: Int64(Int(bitPattern: lower(value))))) + } +} + +public func FfiConverterTypeDocument_lift(_ pointer: UnsafeMutableRawPointer) throws -> Document { + return try FfiConverterTypeDocument.lift(pointer) +} + +public func FfiConverterTypeDocument_lower(_ value: Document) -> UnsafeMutableRawPointer { + return FfiConverterTypeDocument.lower(value) +} + +public protocol NodeProtocol: AnyObject { + func attributes() -> [Attribute] + + func data() -> NodeData + + func display() -> String + + func document() -> Document + + func getChildren() -> [NodeRef] + + func id() -> NodeRef +} + +open class Node: + NodeProtocol +{ + fileprivate let pointer: UnsafeMutableRawPointer! + + /// Used to instantiate a [FFIObject] without an actual pointer, for fakes in tests, mostly. + public struct NoPointer { + public init() {} + } + + // TODO: We'd like this to be `private` but for Swifty reasons, + // we can't implement `FfiConverter` without making this `required` and we can't + // make it `required` without making it `public`. + public required init(unsafeFromRawPointer pointer: UnsafeMutableRawPointer) { + self.pointer = pointer + } + + /// This constructor can be used to instantiate a fake object. + /// - Parameter noPointer: Placeholder value so we can have a constructor separate from the default empty one that may be implemented for classes extending [FFIObject]. + /// + /// - Warning: + /// Any object instantiated with this constructor cannot be passed to an actual Rust-backed object. Since there isn't a backing [Pointer] the FFI lower functions will crash. + public init(noPointer _: NoPointer) { + pointer = nil + } + + public func uniffiClonePointer() -> UnsafeMutableRawPointer { + return try! rustCall { uniffi_liveview_native_core_fn_clone_node(self.pointer, $0) } + } + + public convenience init(_ document: Document, _ id: NodeRef, _ data: NodeData) { + let pointer = + try! rustCall { + uniffi_liveview_native_core_fn_constructor_node_new( + FfiConverterTypeDocument.lower(document), + FfiConverterTypeNodeRef.lower(id), + FfiConverterTypeNodeData.lower(data), $0 + ) + } + self.init(unsafeFromRawPointer: pointer) + } + + deinit { + guard let pointer = pointer else { + return + } + + try! rustCall { uniffi_liveview_native_core_fn_free_node(pointer, $0) } + } + + open func attributes() -> [Attribute] { + return try! FfiConverterSequenceTypeAttribute.lift(try! rustCall { + uniffi_liveview_native_core_fn_method_node_attributes(self.uniffiClonePointer(), $0) + }) + } + + open func data() -> NodeData { + return try! FfiConverterTypeNodeData.lift(try! rustCall { + uniffi_liveview_native_core_fn_method_node_data(self.uniffiClonePointer(), $0) + }) + } + + open func display() -> String { + return try! FfiConverterString.lift(try! rustCall { + uniffi_liveview_native_core_fn_method_node_display(self.uniffiClonePointer(), $0) + }) + } + + open func document() -> Document { + return try! FfiConverterTypeDocument.lift(try! rustCall { + uniffi_liveview_native_core_fn_method_node_document(self.uniffiClonePointer(), $0) + }) + } + + open func getChildren() -> [NodeRef] { + return try! FfiConverterSequenceTypeNodeRef.lift(try! rustCall { + uniffi_liveview_native_core_fn_method_node_get_children(self.uniffiClonePointer(), $0) + }) + } + + open func id() -> NodeRef { + return try! FfiConverterTypeNodeRef.lift(try! rustCall { + uniffi_liveview_native_core_fn_method_node_id(self.uniffiClonePointer(), $0) + }) + } +} + +public struct FfiConverterTypeNode: FfiConverter { + typealias FfiType = UnsafeMutableRawPointer + typealias SwiftType = Node + + public static func lift(_ pointer: UnsafeMutableRawPointer) throws -> Node { + return Node(unsafeFromRawPointer: pointer) + } + + public static func lower(_ value: Node) -> UnsafeMutableRawPointer { + return value.uniffiClonePointer() + } + + public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> Node { + let v: UInt64 = try readInt(&buf) + // The Rust code won't compile if a pointer won't fit in a UInt64. + // We have to go via `UInt` because that's the thing that's the size of a pointer. + let ptr = UnsafeMutableRawPointer(bitPattern: UInt(truncatingIfNeeded: v)) + if ptr == nil { + throw UniffiInternalError.unexpectedNullPointer + } + return try lift(ptr!) + } + + public static func write(_ value: Node, into buf: inout [UInt8]) { + // This fiddling is because `Int` is the thing that's the same size as a pointer. + // The Rust code won't compile if a pointer won't fit in a `UInt64`. + writeInt(&buf, UInt64(bitPattern: Int64(Int(bitPattern: lower(value))))) + } +} + +public func FfiConverterTypeNode_lift(_ pointer: UnsafeMutableRawPointer) throws -> Node { + return try FfiConverterTypeNode.lift(pointer) +} + +public func FfiConverterTypeNode_lower(_ value: Node) -> UnsafeMutableRawPointer { + return FfiConverterTypeNode.lower(value) +} + +public protocol NodeRefProtocol: AnyObject { + func ref() -> Int32 +} + +open class NodeRef: + NodeRefProtocol +{ + fileprivate let pointer: UnsafeMutableRawPointer! + + /// Used to instantiate a [FFIObject] without an actual pointer, for fakes in tests, mostly. + public struct NoPointer { + public init() {} + } + + // TODO: We'd like this to be `private` but for Swifty reasons, + // we can't implement `FfiConverter` without making this `required` and we can't + // make it `required` without making it `public`. + public required init(unsafeFromRawPointer pointer: UnsafeMutableRawPointer) { + self.pointer = pointer + } + + /// This constructor can be used to instantiate a fake object. + /// - Parameter noPointer: Placeholder value so we can have a constructor separate from the default empty one that may be implemented for classes extending [FFIObject]. + /// + /// - Warning: + /// Any object instantiated with this constructor cannot be passed to an actual Rust-backed object. Since there isn't a backing [Pointer] the FFI lower functions will crash. + public init(noPointer _: NoPointer) { + pointer = nil + } + + public func uniffiClonePointer() -> UnsafeMutableRawPointer { + return try! rustCall { uniffi_liveview_native_core_fn_clone_noderef(self.pointer, $0) } + } + + // No primary constructor declared for this class. + + deinit { + guard let pointer = pointer else { + return + } + + try! rustCall { uniffi_liveview_native_core_fn_free_noderef(pointer, $0) } + } + + open func ref() -> Int32 { + return try! FfiConverterInt32.lift(try! rustCall { + uniffi_liveview_native_core_fn_method_noderef_ref(self.uniffiClonePointer(), $0) + }) + } +} + +public struct FfiConverterTypeNodeRef: FfiConverter { + typealias FfiType = UnsafeMutableRawPointer + typealias SwiftType = NodeRef + + public static func lift(_ pointer: UnsafeMutableRawPointer) throws -> NodeRef { + return NodeRef(unsafeFromRawPointer: pointer) + } + + public static func lower(_ value: NodeRef) -> UnsafeMutableRawPointer { + return value.uniffiClonePointer() + } + + public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> NodeRef { + let v: UInt64 = try readInt(&buf) + // The Rust code won't compile if a pointer won't fit in a UInt64. + // We have to go via `UInt` because that's the thing that's the size of a pointer. + let ptr = UnsafeMutableRawPointer(bitPattern: UInt(truncatingIfNeeded: v)) + if ptr == nil { + throw UniffiInternalError.unexpectedNullPointer + } + return try lift(ptr!) + } + + public static func write(_ value: NodeRef, into buf: inout [UInt8]) { + // This fiddling is because `Int` is the thing that's the same size as a pointer. + // The Rust code won't compile if a pointer won't fit in a `UInt64`. + writeInt(&buf, UInt64(bitPattern: Int64(Int(bitPattern: lower(value))))) + } +} + +public func FfiConverterTypeNodeRef_lift(_ pointer: UnsafeMutableRawPointer) throws -> NodeRef { + return try FfiConverterTypeNodeRef.lift(pointer) +} + +public func FfiConverterTypeNodeRef_lower(_ value: NodeRef) -> UnsafeMutableRawPointer { + return FfiConverterTypeNodeRef.lower(value) +} + +public struct Attribute { + public var name: AttributeName + public var value: String? + + // Default memberwise initializers are never public by default, so we + // declare one manually. + public init(name: AttributeName, value: String?) { + self.name = name + self.value = value + } +} + +extension Attribute: Equatable, Hashable { + public static func == (lhs: Attribute, rhs: Attribute) -> Bool { + if lhs.name != rhs.name { + return false + } + if lhs.value != rhs.value { + return false + } + return true + } + + public func hash(into hasher: inout Hasher) { + hasher.combine(name) + hasher.combine(value) + } +} + +public struct FfiConverterTypeAttribute: FfiConverterRustBuffer { + public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> Attribute { + return + try Attribute( + name: FfiConverterTypeAttributeName.read(from: &buf), + value: FfiConverterOptionString.read(from: &buf) + ) + } + + public static func write(_ value: Attribute, into buf: inout [UInt8]) { + FfiConverterTypeAttributeName.write(value.name, into: &buf) + FfiConverterOptionString.write(value.value, into: &buf) + } +} + +public func FfiConverterTypeAttribute_lift(_ buf: RustBuffer) throws -> Attribute { + return try FfiConverterTypeAttribute.lift(buf) +} + +public func FfiConverterTypeAttribute_lower(_ value: Attribute) -> RustBuffer { + return FfiConverterTypeAttribute.lower(value) +} + +/** + * Represents the fully-qualified name of an attribute + */ +public struct AttributeName { + /** + * This is used by svg attributes, e.g. `xlink-href` + */ + public var namespace: String? + public var name: String + + // Default memberwise initializers are never public by default, so we + // declare one manually. + public init( + /** + * This is used by svg attributes, e.g. `xlink-href` + */ namespace: String?, name: String + ) { + self.namespace = namespace + self.name = name + } +} + +extension AttributeName: Equatable, Hashable { + public static func == (lhs: AttributeName, rhs: AttributeName) -> Bool { + if lhs.namespace != rhs.namespace { + return false + } + if lhs.name != rhs.name { + return false + } + return true + } + + public func hash(into hasher: inout Hasher) { + hasher.combine(namespace) + hasher.combine(name) + } +} + +public struct FfiConverterTypeAttributeName: FfiConverterRustBuffer { + public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> AttributeName { + return + try AttributeName( + namespace: FfiConverterOptionString.read(from: &buf), + name: FfiConverterString.read(from: &buf) + ) + } + + public static func write(_ value: AttributeName, into buf: inout [UInt8]) { + FfiConverterOptionString.write(value.namespace, into: &buf) + FfiConverterString.write(value.name, into: &buf) + } +} + +public func FfiConverterTypeAttributeName_lift(_ buf: RustBuffer) throws -> AttributeName { + return try FfiConverterTypeAttributeName.lift(buf) +} + +public func FfiConverterTypeAttributeName_lower(_ value: AttributeName) -> RustBuffer { + return FfiConverterTypeAttributeName.lower(value) +} + +/** + * An `Element` is a typed node in a document, with the ability to carry attributes and contain other nodes. + */ +public struct Element { + public var name: ElementName + public var attributes: [Attribute] + + // Default memberwise initializers are never public by default, so we + // declare one manually. + public init(name: ElementName, attributes: [Attribute]) { + self.name = name + self.attributes = attributes + } +} + +extension Element: Equatable, Hashable { + public static func == (lhs: Element, rhs: Element) -> Bool { + if lhs.name != rhs.name { + return false + } + if lhs.attributes != rhs.attributes { + return false + } + return true + } + + public func hash(into hasher: inout Hasher) { + hasher.combine(name) + hasher.combine(attributes) + } +} + +public struct FfiConverterTypeElement: FfiConverterRustBuffer { + public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> Element { + return + try Element( + name: FfiConverterTypeElementName.read(from: &buf), + attributes: FfiConverterSequenceTypeAttribute.read(from: &buf) + ) + } + + public static func write(_ value: Element, into buf: inout [UInt8]) { + FfiConverterTypeElementName.write(value.name, into: &buf) + FfiConverterSequenceTypeAttribute.write(value.attributes, into: &buf) + } +} + +public func FfiConverterTypeElement_lift(_ buf: RustBuffer) throws -> Element { + return try FfiConverterTypeElement.lift(buf) +} + +public func FfiConverterTypeElement_lower(_ value: Element) -> RustBuffer { + return FfiConverterTypeElement.lower(value) +} + +/** + * Represents the fully-qualified name of an element + */ +public struct ElementName { + public var namespace: String? + public var name: String + + // Default memberwise initializers are never public by default, so we + // declare one manually. + public init(namespace: String?, name: String) { + self.namespace = namespace + self.name = name + } +} + +extension ElementName: Equatable, Hashable { + public static func == (lhs: ElementName, rhs: ElementName) -> Bool { + if lhs.namespace != rhs.namespace { + return false + } + if lhs.name != rhs.name { + return false + } + return true + } + + public func hash(into hasher: inout Hasher) { + hasher.combine(namespace) + hasher.combine(name) + } +} + +public struct FfiConverterTypeElementName: FfiConverterRustBuffer { + public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> ElementName { + return + try ElementName( + namespace: FfiConverterOptionString.read(from: &buf), + name: FfiConverterString.read(from: &buf) + ) + } + + public static func write(_ value: ElementName, into buf: inout [UInt8]) { + FfiConverterOptionString.write(value.namespace, into: &buf) + FfiConverterString.write(value.name, into: &buf) + } +} + +public func FfiConverterTypeElementName_lift(_ buf: RustBuffer) throws -> ElementName { + return try FfiConverterTypeElementName.lift(buf) +} + +public func FfiConverterTypeElementName_lower(_ value: ElementName) -> RustBuffer { + return FfiConverterTypeElementName.lower(value) +} + +// Note that we don't yet support `indirect` for enums. +// See https://github.com/mozilla/uniffi-rs/issues/396 for further discussion. + +public enum ChangeType { + case change + case add + case remove + case replace +} + +public struct FfiConverterTypeChangeType: FfiConverterRustBuffer { + typealias SwiftType = ChangeType + + public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> ChangeType { + let variant: Int32 = try readInt(&buf) + switch variant { + case 1: return .change + + case 2: return .add + + case 3: return .remove + + case 4: return .replace + + default: throw UniffiInternalError.unexpectedEnumCase + } + } + + public static func write(_ value: ChangeType, into buf: inout [UInt8]) { + switch value { + case .change: + writeInt(&buf, Int32(1)) + + case .add: + writeInt(&buf, Int32(2)) + + case .remove: + writeInt(&buf, Int32(3)) + + case .replace: + writeInt(&buf, Int32(4)) + } + } +} + +public func FfiConverterTypeChangeType_lift(_ buf: RustBuffer) throws -> ChangeType { + return try FfiConverterTypeChangeType.lift(buf) +} + +public func FfiConverterTypeChangeType_lower(_ value: ChangeType) -> RustBuffer { + return FfiConverterTypeChangeType.lower(value) +} + +extension ChangeType: Equatable, Hashable {} + +// Note that we don't yet support `indirect` for enums. +// See https://github.com/mozilla/uniffi-rs/issues/396 for further discussion. + +public enum EventType { + case changed +} + +public struct FfiConverterTypeEventType: FfiConverterRustBuffer { + typealias SwiftType = EventType + + public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> EventType { + let variant: Int32 = try readInt(&buf) + switch variant { + case 1: return .changed + + default: throw UniffiInternalError.unexpectedEnumCase + } + } + + public static func write(_ value: EventType, into buf: inout [UInt8]) { + switch value { + case .changed: + writeInt(&buf, Int32(1)) + } + } +} + +public func FfiConverterTypeEventType_lift(_ buf: RustBuffer) throws -> EventType { + return try FfiConverterTypeEventType.lift(buf) +} + +public func FfiConverterTypeEventType_lower(_ value: EventType) -> RustBuffer { + return FfiConverterTypeEventType.lower(value) +} + +extension EventType: Equatable, Hashable {} + +// Note that we don't yet support `indirect` for enums. +// See https://github.com/mozilla/uniffi-rs/issues/396 for further discussion. + +public enum MergeError { + case fragmentTypeMismatch + case createComponentFromUpdate + case createChildFromUpdateFragment + case addChildToExisting + case streamIdMisMatch + case stream(error: StreamConversionError + ) +} + +public struct FfiConverterTypeMergeError: FfiConverterRustBuffer { + typealias SwiftType = MergeError + + public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> MergeError { + let variant: Int32 = try readInt(&buf) + switch variant { + case 1: return .fragmentTypeMismatch + + case 2: return .createComponentFromUpdate + + case 3: return .createChildFromUpdateFragment + + case 4: return .addChildToExisting + + case 5: return .streamIdMisMatch + + case 6: return try .stream(error: FfiConverterTypeStreamConversionError.read(from: &buf) + ) + + default: throw UniffiInternalError.unexpectedEnumCase + } + } + + public static func write(_ value: MergeError, into buf: inout [UInt8]) { + switch value { + case .fragmentTypeMismatch: + writeInt(&buf, Int32(1)) + + case .createComponentFromUpdate: + writeInt(&buf, Int32(2)) + + case .createChildFromUpdateFragment: + writeInt(&buf, Int32(3)) + + case .addChildToExisting: + writeInt(&buf, Int32(4)) + + case .streamIdMisMatch: + writeInt(&buf, Int32(5)) + + case let .stream(error): + writeInt(&buf, Int32(6)) + FfiConverterTypeStreamConversionError.write(error, into: &buf) + } + } +} + +public func FfiConverterTypeMergeError_lift(_ buf: RustBuffer) throws -> MergeError { + return try FfiConverterTypeMergeError.lift(buf) +} + +public func FfiConverterTypeMergeError_lower(_ value: MergeError) -> RustBuffer { + return FfiConverterTypeMergeError.lower(value) +} + +extension MergeError: Equatable, Hashable {} + +// Note that we don't yet support `indirect` for enums. +// See https://github.com/mozilla/uniffi-rs/issues/396 for further discussion. +/** + * This enum represents the valid node types of a `Document` tree + */ + +public enum NodeData { + /** + * A marker node that indicates the root of a document + * + * A document may only have a single root, and it has no attributes + */ + case root + /** + * A typed node that can carry attributes and may contain other nodes + */ + case nodeElement(element: Element + ) + /** + * A leaf node is an untyped node, typically text, and does not have any attributes or children + */ + case leaf(value: String + ) +} + +public struct FfiConverterTypeNodeData: FfiConverterRustBuffer { + typealias SwiftType = NodeData + + public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> NodeData { + let variant: Int32 = try readInt(&buf) + switch variant { + case 1: return .root + + case 2: return try .nodeElement(element: FfiConverterTypeElement.read(from: &buf) + ) + + case 3: return try .leaf(value: FfiConverterString.read(from: &buf) + ) + + default: throw UniffiInternalError.unexpectedEnumCase + } + } + + public static func write(_ value: NodeData, into buf: inout [UInt8]) { + switch value { + case .root: + writeInt(&buf, Int32(1)) + + case let .nodeElement(element): + writeInt(&buf, Int32(2)) + FfiConverterTypeElement.write(element, into: &buf) + + case let .leaf(value): + writeInt(&buf, Int32(3)) + FfiConverterString.write(value, into: &buf) + } + } +} + +public func FfiConverterTypeNodeData_lift(_ buf: RustBuffer) throws -> NodeData { + return try FfiConverterTypeNodeData.lift(buf) +} + +public func FfiConverterTypeNodeData_lower(_ value: NodeData) -> RustBuffer { + return FfiConverterTypeNodeData.lower(value) +} + +extension NodeData: Equatable, Hashable {} + +/** + * Represents the possible types of failure that can occur while parsing a `Document` + */ +public enum ParseError { + case Reader(message: String) + + case Tokenizer(message: String) +} + +public struct FfiConverterTypeParseError: FfiConverterRustBuffer { + typealias SwiftType = ParseError + + public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> ParseError { + let variant: Int32 = try readInt(&buf) + switch variant { + case 1: return try .Reader( + message: FfiConverterString.read(from: &buf) + ) + + case 2: return try .Tokenizer( + message: FfiConverterString.read(from: &buf) + ) + + default: throw UniffiInternalError.unexpectedEnumCase + } + } + + public static func write(_ value: ParseError, into buf: inout [UInt8]) { + switch value { + case .Reader(_ /* message is ignored*/ ): + writeInt(&buf, Int32(1)) + case .Tokenizer(_ /* message is ignored*/ ): + writeInt(&buf, Int32(2)) + } + } +} + +extension ParseError: Equatable, Hashable {} + +extension ParseError: Error {} + +public enum RenderError { + case NoComponents(message: String) + + case NoTemplates(message: String) + + case TemplateNotFound(message: String) + + case ComponentNotFound(message: String) + + case MergeError(message: String) + + case ChildNotFoundForTemplate(message: String) + + case ChildNotFoundForStatic(message: String) + + case CousinNotFound(message: String) + + case SerdeError(message: String) + + case ParseError(message: String) +} + +public struct FfiConverterTypeRenderError: FfiConverterRustBuffer { + typealias SwiftType = RenderError + + public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> RenderError { + let variant: Int32 = try readInt(&buf) + switch variant { + case 1: return try .NoComponents( + message: FfiConverterString.read(from: &buf) + ) + + case 2: return try .NoTemplates( + message: FfiConverterString.read(from: &buf) + ) + + case 3: return try .TemplateNotFound( + message: FfiConverterString.read(from: &buf) + ) + + case 4: return try .ComponentNotFound( + message: FfiConverterString.read(from: &buf) + ) + + case 5: return try .MergeError( + message: FfiConverterString.read(from: &buf) + ) + + case 6: return try .ChildNotFoundForTemplate( + message: FfiConverterString.read(from: &buf) + ) + + case 7: return try .ChildNotFoundForStatic( + message: FfiConverterString.read(from: &buf) + ) + + case 8: return try .CousinNotFound( + message: FfiConverterString.read(from: &buf) + ) + + case 9: return try .SerdeError( + message: FfiConverterString.read(from: &buf) + ) + + case 10: return try .ParseError( + message: FfiConverterString.read(from: &buf) + ) + + default: throw UniffiInternalError.unexpectedEnumCase + } + } + + public static func write(_ value: RenderError, into buf: inout [UInt8]) { + switch value { + case .NoComponents(_ /* message is ignored*/ ): + writeInt(&buf, Int32(1)) + case .NoTemplates(_ /* message is ignored*/ ): + writeInt(&buf, Int32(2)) + case .TemplateNotFound(_ /* message is ignored*/ ): + writeInt(&buf, Int32(3)) + case .ComponentNotFound(_ /* message is ignored*/ ): + writeInt(&buf, Int32(4)) + case .MergeError(_ /* message is ignored*/ ): + writeInt(&buf, Int32(5)) + case .ChildNotFoundForTemplate(_ /* message is ignored*/ ): + writeInt(&buf, Int32(6)) + case .ChildNotFoundForStatic(_ /* message is ignored*/ ): + writeInt(&buf, Int32(7)) + case .CousinNotFound(_ /* message is ignored*/ ): + writeInt(&buf, Int32(8)) + case .SerdeError(_ /* message is ignored*/ ): + writeInt(&buf, Int32(9)) + case .ParseError(_ /* message is ignored*/ ): + writeInt(&buf, Int32(10)) + } + } +} + +extension RenderError: Equatable, Hashable {} + +extension RenderError: Error {} + +// Note that we don't yet support `indirect` for enums. +// See https://github.com/mozilla/uniffi-rs/issues/396 for further discussion. + +public enum StreamConversionError { + case noStreamId +} + +public struct FfiConverterTypeStreamConversionError: FfiConverterRustBuffer { + typealias SwiftType = StreamConversionError + + public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> StreamConversionError { + let variant: Int32 = try readInt(&buf) + switch variant { + case 1: return .noStreamId + + default: throw UniffiInternalError.unexpectedEnumCase + } + } + + public static func write(_ value: StreamConversionError, into buf: inout [UInt8]) { + switch value { + case .noStreamId: + writeInt(&buf, Int32(1)) + } + } +} + +public func FfiConverterTypeStreamConversionError_lift(_ buf: RustBuffer) throws -> StreamConversionError { + return try FfiConverterTypeStreamConversionError.lift(buf) +} + +public func FfiConverterTypeStreamConversionError_lower(_ value: StreamConversionError) -> RustBuffer { + return FfiConverterTypeStreamConversionError.lower(value) +} + +extension StreamConversionError: Equatable, Hashable {} + +public protocol DocumentChangeHandler: AnyObject { + func handle(_ changeType: ChangeType, _ nodeRef: NodeRef, _ nodeData: NodeData, _ parent: NodeRef?) +} + +// Magic number for the Rust proxy to call using the same mechanism as every other method, +// to free the callback once it's dropped by Rust. +private let IDX_CALLBACK_FREE: Int32 = 0 +// Callback return codes +private let UNIFFI_CALLBACK_SUCCESS: Int32 = 0 +private let UNIFFI_CALLBACK_ERROR: Int32 = 1 +private let UNIFFI_CALLBACK_UNEXPECTED_ERROR: Int32 = 2 + +// Put the implementation in a struct so we don't pollute the top-level namespace +private enum UniffiCallbackInterfaceDocumentChangeHandler { + // Create the VTable using a series of closures. + // Swift automatically converts these into C callback functions. + static var vtable: UniffiVTableCallbackInterfaceDocumentChangeHandler = .init( + handle: { ( + uniffiHandle: UInt64, + changeType: RustBuffer, + nodeRef: UnsafeMutableRawPointer, + nodeData: RustBuffer, + parent: RustBuffer, + _: UnsafeMutableRawPointer, + uniffiCallStatus: UnsafeMutablePointer + ) in + let makeCall = { + () throws in + guard let uniffiObj = try? FfiConverterCallbackInterfaceDocumentChangeHandler.handleMap.get(handle: uniffiHandle) else { + throw UniffiInternalError.unexpectedStaleHandle + } + return try uniffiObj.handle( + FfiConverterTypeChangeType.lift(changeType), + FfiConverterTypeNodeRef.lift(nodeRef), + FfiConverterTypeNodeData.lift(nodeData), + FfiConverterOptionTypeNodeRef.lift(parent) + ) + } + + let writeReturn = { () } + uniffiTraitInterfaceCall( + callStatus: uniffiCallStatus, + makeCall: makeCall, + writeReturn: writeReturn + ) + }, + uniffiFree: { (uniffiHandle: UInt64) in + let result = try? FfiConverterCallbackInterfaceDocumentChangeHandler.handleMap.remove(handle: uniffiHandle) + if result == nil { + print("Uniffi callback interface DocumentChangeHandler: handle missing in uniffiFree") + } + } + ) +} + +private func uniffiCallbackInitDocumentChangeHandler() { + uniffi_liveview_native_core_fn_init_callback_vtable_documentchangehandler(&UniffiCallbackInterfaceDocumentChangeHandler.vtable) +} + +// FfiConverter protocol for callback interfaces +private enum FfiConverterCallbackInterfaceDocumentChangeHandler { + fileprivate static var handleMap = UniffiHandleMap() +} + +extension FfiConverterCallbackInterfaceDocumentChangeHandler: FfiConverter { + typealias SwiftType = DocumentChangeHandler + typealias FfiType = UInt64 + + public static func lift(_ handle: UInt64) throws -> SwiftType { + try handleMap.get(handle: handle) + } + + public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> SwiftType { + let handle: UInt64 = try readInt(&buf) + return try lift(handle) + } + + public static func lower(_ v: SwiftType) -> UInt64 { + return handleMap.insert(obj: v) + } + + public static func write(_ v: SwiftType, into buf: inout [UInt8]) { + writeInt(&buf, lower(v)) + } +} + +private struct FfiConverterOptionString: FfiConverterRustBuffer { + typealias SwiftType = String? + + public static func write(_ value: SwiftType, into buf: inout [UInt8]) { + guard let value = value else { + writeInt(&buf, Int8(0)) + return + } + writeInt(&buf, Int8(1)) + FfiConverterString.write(value, into: &buf) + } + + public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> SwiftType { + switch try readInt(&buf) as Int8 { + case 0: return nil + case 1: return try FfiConverterString.read(from: &buf) + default: throw UniffiInternalError.unexpectedOptionalTag + } + } +} + +private struct FfiConverterOptionTypeNodeRef: FfiConverterRustBuffer { + typealias SwiftType = NodeRef? + + public static func write(_ value: SwiftType, into buf: inout [UInt8]) { + guard let value = value else { + writeInt(&buf, Int8(0)) + return + } + writeInt(&buf, Int8(1)) + FfiConverterTypeNodeRef.write(value, into: &buf) + } + + public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> SwiftType { + switch try readInt(&buf) as Int8 { + case 0: return nil + case 1: return try FfiConverterTypeNodeRef.read(from: &buf) + default: throw UniffiInternalError.unexpectedOptionalTag + } + } +} + +private struct FfiConverterSequenceTypeNodeRef: FfiConverterRustBuffer { + typealias SwiftType = [NodeRef] + + public static func write(_ value: [NodeRef], into buf: inout [UInt8]) { + let len = Int32(value.count) + writeInt(&buf, len) + for item in value { + FfiConverterTypeNodeRef.write(item, into: &buf) + } + } + + public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> [NodeRef] { + let len: Int32 = try readInt(&buf) + var seq = [NodeRef]() + seq.reserveCapacity(Int(len)) + for _ in 0 ..< len { + try seq.append(FfiConverterTypeNodeRef.read(from: &buf)) + } + return seq + } +} + +private struct FfiConverterSequenceTypeAttribute: FfiConverterRustBuffer { + typealias SwiftType = [Attribute] + + public static func write(_ value: [Attribute], into buf: inout [UInt8]) { + let len = Int32(value.count) + writeInt(&buf, len) + for item in value { + FfiConverterTypeAttribute.write(item, into: &buf) + } + } + + public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> [Attribute] { + let len: Int32 = try readInt(&buf) + var seq = [Attribute]() + seq.reserveCapacity(Int(len)) + for _ in 0 ..< len { + try seq.append(FfiConverterTypeAttribute.read(from: &buf)) + } + return seq + } +} + +private enum InitializationResult { + case ok + case contractVersionMismatch + case apiChecksumMismatch +} + +// Use a global variables to perform the versioning checks. Swift ensures that +// the code inside is only computed once. +private var initializationResult: InitializationResult { + // Get the bindings contract version from our ComponentInterface + let bindings_contract_version = 26 + // Get the scaffolding contract version by calling the into the dylib + let scaffolding_contract_version = ffi_liveview_native_core_uniffi_contract_version() + if bindings_contract_version != scaffolding_contract_version { + return InitializationResult.contractVersionMismatch + } + if uniffi_liveview_native_core_checksum_method_document_children() != 59121 { + return InitializationResult.apiChecksumMismatch + } + if uniffi_liveview_native_core_checksum_method_document_get() != 61396 { + return InitializationResult.apiChecksumMismatch + } + if uniffi_liveview_native_core_checksum_method_document_get_attributes() != 42016 { + return InitializationResult.apiChecksumMismatch + } + if uniffi_liveview_native_core_checksum_method_document_get_parent() != 49974 { + return InitializationResult.apiChecksumMismatch + } + if uniffi_liveview_native_core_checksum_method_document_merge_fragment_json() != 40898 { + return InitializationResult.apiChecksumMismatch + } + if uniffi_liveview_native_core_checksum_method_document_render() != 31975 { + return InitializationResult.apiChecksumMismatch + } + if uniffi_liveview_native_core_checksum_method_document_root() != 55719 { + return InitializationResult.apiChecksumMismatch + } + if uniffi_liveview_native_core_checksum_method_document_set_event_handler() != 18356 { + return InitializationResult.apiChecksumMismatch + } + if uniffi_liveview_native_core_checksum_method_node_attributes() != 60381 { + return InitializationResult.apiChecksumMismatch + } + if uniffi_liveview_native_core_checksum_method_node_data() != 10189 { + return InitializationResult.apiChecksumMismatch + } + if uniffi_liveview_native_core_checksum_method_node_display() != 36109 { + return InitializationResult.apiChecksumMismatch + } + if uniffi_liveview_native_core_checksum_method_node_document() != 33196 { + return InitializationResult.apiChecksumMismatch + } + if uniffi_liveview_native_core_checksum_method_node_get_children() != 13889 { + return InitializationResult.apiChecksumMismatch + } + if uniffi_liveview_native_core_checksum_method_node_id() != 22538 { + return InitializationResult.apiChecksumMismatch + } + if uniffi_liveview_native_core_checksum_method_noderef_ref() != 32879 { + return InitializationResult.apiChecksumMismatch + } + if uniffi_liveview_native_core_checksum_constructor_document_empty() != 49805 { + return InitializationResult.apiChecksumMismatch + } + if uniffi_liveview_native_core_checksum_constructor_document_parse() != 495 { + return InitializationResult.apiChecksumMismatch + } + if uniffi_liveview_native_core_checksum_constructor_document_parse_fragment_json() != 46839 { + return InitializationResult.apiChecksumMismatch + } + if uniffi_liveview_native_core_checksum_constructor_node_new() != 23337 { + return InitializationResult.apiChecksumMismatch + } + if uniffi_liveview_native_core_checksum_method_documentchangehandler_handle() != 11175 { + return InitializationResult.apiChecksumMismatch + } + + uniffiCallbackInitDocumentChangeHandler() + return InitializationResult.ok +} + +private func uniffiEnsureInitialized() { + switch initializationResult { + case .ok: + break + case .contractVersionMismatch: + fatalError("UniFFI contract version mismatch: try cleaning and rebuilding your project") + case .apiChecksumMismatch: + fatalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } +} + +// swiftlint:enable all