diff --git a/Package.swift b/Package.swift index ad9f5dc8..893d0be7 100644 --- a/Package.swift +++ b/Package.swift @@ -6,7 +6,7 @@ import PackageDescription let liveview_native_core_framework: Target // To relase, toggle this to `false` -let useLocalFramework = true +let useLocalFramework = false if useLocalFramework { liveview_native_core_framework = .binaryTarget( name: "liveview_native_core", @@ -14,7 +14,7 @@ if useLocalFramework { ) } else { let releaseTag = "0.4.0-alpha-6" - let releaseChecksum = "f3972f4d40732c884c98426b28550376abaff20a3490b73367ad170f1f0bcca9" + let releaseChecksum = "96e5207d82b73ea85600b7570d89fe8c647c184e37fe8e4dd9d5662df8bb33db" liveview_native_core_framework = .binaryTarget( name: "liveview_native_core", url: "https://github.com/liveview-native/liveview-native-core/releases/download/\(releaseTag)/liveview_native_core.xcframework.zip", 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 00000000..bf3e5a01 --- /dev/null +++ b/crates/core/liveview-native-core-swift/Sources/LiveViewNativeCore/LiveViewNativeCore.swift @@ -0,0 +1,2522 @@ +// 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 to 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 { + let neverThrow: ((RustBuffer) throws -> Never)? = nil + return try makeRustCall(callback, errorHandler: neverThrow) +} + +private func rustCallWithError( + _ errorHandler: @escaping (RustBuffer) throws -> E, + _ callback: (UnsafeMutablePointer) -> T +) throws -> T { + try makeRustCall(callback, errorHandler: errorHandler) +} + +private func makeRustCall( + _ callback: (UnsafeMutablePointer) -> T, + errorHandler: ((RustBuffer) throws -> E)? +) 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 -> E)? +) 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) + } +} + +private struct FfiConverterData: FfiConverterRustBuffer { + typealias SwiftType = Data + + public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> Data { + let len: Int32 = try readInt(&buf) + return try Data(readBytes(&buf, count: Int(len))) + } + + public static func write(_ value: Data, into buf: inout [UInt8]) { + let len = Int32(value.count) + writeInt(&buf, len) + writeBytes(&buf, value) + } +} + +private struct FfiConverterDuration: FfiConverterRustBuffer { + typealias SwiftType = TimeInterval + + public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> TimeInterval { + let seconds: UInt64 = try readInt(&buf) + let nanoseconds: UInt32 = try readInt(&buf) + return Double(seconds) + (Double(nanoseconds) / 1.0e9) + } + + public static func write(_ value: TimeInterval, into buf: inout [UInt8]) { + if value.rounded(.down) > Double(Int64.max) { + fatalError("Duration overflow, exceeds max bounds supported by Uniffi") + } + + if value < 0 { + fatalError("Invalid duration, must be non-negative") + } + + let seconds = UInt64(value) + let nanoseconds = UInt32((value - Double(seconds)) * 1.0e9) + writeInt(&buf, seconds) + writeInt(&buf, nanoseconds) + } +} + +public protocol DocumentProtocol: AnyObject { + func children(_ nodeRef: NodeRef) -> [NodeRef] + + func get(_ nodeRef: NodeRef) -> NodeData + + func getAttributes(_ nodeRef: NodeRef) -> [Attribute] + + func getNode(_ nodeRef: NodeRef) -> Node + + 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 getNode(_ nodeRef: NodeRef) -> Node { + return try! FfiConverterTypeNode.lift(try! rustCall { + uniffi_liveview_native_core_fn_method_document_get_node(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 LiveChannelProtocol: AnyObject { + func channel() -> Channel + + func getPhxRefFromUploadJoinPayload() throws -> String + + func joinPayload() -> Payload + + func mergeDiffs() async throws + + func uploadFile(_ file: LiveFile) async throws + + func validateUpload(_ file: LiveFile) async throws -> Payload +} + +open class LiveChannel: + LiveChannelProtocol +{ + 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_livechannel(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_livechannel(pointer, $0) } + } + + open func channel() -> Channel { + return try! FfiConverterTypeChannel_lift(try! rustCall { + uniffi_liveview_native_core_fn_method_livechannel_channel(self.uniffiClonePointer(), $0) + }) + } + + open func getPhxRefFromUploadJoinPayload() throws -> String { + return try FfiConverterString.lift(rustCallWithError(FfiConverterTypeLiveSocketError.lift) { + uniffi_liveview_native_core_fn_method_livechannel_get_phx_ref_from_upload_join_payload(self.uniffiClonePointer(), $0) + }) + } + + open func joinPayload() -> Payload { + return try! FfiConverterTypePayload_lift(try! rustCall { + uniffi_liveview_native_core_fn_method_livechannel_join_payload(self.uniffiClonePointer(), $0) + }) + } + + open func mergeDiffs() async throws { + return + try await uniffiRustCallAsync( + rustFutureFunc: { + uniffi_liveview_native_core_fn_method_livechannel_merge_diffs( + self.uniffiClonePointer() + ) + }, + pollFunc: ffi_liveview_native_core_rust_future_poll_void, + completeFunc: ffi_liveview_native_core_rust_future_complete_void, + freeFunc: ffi_liveview_native_core_rust_future_free_void, + liftFunc: { $0 }, + errorHandler: FfiConverterTypeLiveSocketError.lift + ) + } + + open func uploadFile(_ file: LiveFile) async throws { + return + try await uniffiRustCallAsync( + rustFutureFunc: { + uniffi_liveview_native_core_fn_method_livechannel_upload_file( + self.uniffiClonePointer(), + FfiConverterTypeLiveFile.lower(file) + ) + }, + pollFunc: ffi_liveview_native_core_rust_future_poll_void, + completeFunc: ffi_liveview_native_core_rust_future_complete_void, + freeFunc: ffi_liveview_native_core_rust_future_free_void, + liftFunc: { $0 }, + errorHandler: FfiConverterTypeLiveSocketError.lift + ) + } + + open func validateUpload(_ file: LiveFile) async throws -> Payload { + return + try await uniffiRustCallAsync( + rustFutureFunc: { + uniffi_liveview_native_core_fn_method_livechannel_validate_upload( + self.uniffiClonePointer(), + FfiConverterTypeLiveFile.lower(file) + ) + }, + pollFunc: ffi_liveview_native_core_rust_future_poll_rust_buffer, + completeFunc: ffi_liveview_native_core_rust_future_complete_rust_buffer, + freeFunc: ffi_liveview_native_core_rust_future_free_rust_buffer, + liftFunc: FfiConverterTypePayload_lift, + errorHandler: FfiConverterTypeLiveSocketError.lift + ) + } +} + +public struct FfiConverterTypeLiveChannel: FfiConverter { + typealias FfiType = UnsafeMutableRawPointer + typealias SwiftType = LiveChannel + + public static func lift(_ pointer: UnsafeMutableRawPointer) throws -> LiveChannel { + return LiveChannel(unsafeFromRawPointer: pointer) + } + + public static func lower(_ value: LiveChannel) -> UnsafeMutableRawPointer { + return value.uniffiClonePointer() + } + + public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> LiveChannel { + 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: LiveChannel, 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 FfiConverterTypeLiveChannel_lift(_ pointer: UnsafeMutableRawPointer) throws -> LiveChannel { + return try FfiConverterTypeLiveChannel.lift(pointer) +} + +public func FfiConverterTypeLiveChannel_lower(_ value: LiveChannel) -> UnsafeMutableRawPointer { + return FfiConverterTypeLiveChannel.lower(value) +} + +public protocol LiveFileProtocol: AnyObject {} + +open class LiveFile: + LiveFileProtocol +{ + 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_livefile(self.pointer, $0) } + } + + public convenience init(_ contents: Data, _ fileType: String, _ name: String, _ phxId: String) { + let pointer = + try! rustCall { + uniffi_liveview_native_core_fn_constructor_livefile_new( + FfiConverterData.lower(contents), + FfiConverterString.lower(fileType), + FfiConverterString.lower(name), + FfiConverterString.lower(phxId), $0 + ) + } + self.init(unsafeFromRawPointer: pointer) + } + + deinit { + guard let pointer = pointer else { + return + } + + try! rustCall { uniffi_liveview_native_core_fn_free_livefile(pointer, $0) } + } +} + +public struct FfiConverterTypeLiveFile: FfiConverter { + typealias FfiType = UnsafeMutableRawPointer + typealias SwiftType = LiveFile + + public static func lift(_ pointer: UnsafeMutableRawPointer) throws -> LiveFile { + return LiveFile(unsafeFromRawPointer: pointer) + } + + public static func lower(_ value: LiveFile) -> UnsafeMutableRawPointer { + return value.uniffiClonePointer() + } + + public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> LiveFile { + 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: LiveFile, 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 FfiConverterTypeLiveFile_lift(_ pointer: UnsafeMutableRawPointer) throws -> LiveFile { + return try FfiConverterTypeLiveFile.lift(pointer) +} + +public func FfiConverterTypeLiveFile_lower(_ value: LiveFile) -> UnsafeMutableRawPointer { + return FfiConverterTypeLiveFile.lower(value) +} + +public protocol LiveSocketProtocol: AnyObject { + func joinLiveviewChannel() async throws -> LiveChannel + + func socket() -> Socket +} + +open class LiveSocket: + LiveSocketProtocol +{ + 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_livesocket(self.pointer, $0) } + } + + public convenience init(_ url: String, _ timeout: TimeInterval) async throws { + let pointer = + try await uniffiRustCallAsync( + rustFutureFunc: { + uniffi_liveview_native_core_fn_constructor_livesocket_new(FfiConverterString.lower(url), FfiConverterDuration.lower(timeout)) + }, + pollFunc: ffi_liveview_native_core_rust_future_poll_pointer, + completeFunc: ffi_liveview_native_core_rust_future_complete_pointer, + freeFunc: ffi_liveview_native_core_rust_future_free_pointer, + liftFunc: FfiConverterTypeLiveSocket.lift, + errorHandler: FfiConverterTypeLiveSocketError.lift + ) + + .uniffiClonePointer() + self.init(unsafeFromRawPointer: pointer) + } + + deinit { + guard let pointer = pointer else { + return + } + + try! rustCall { uniffi_liveview_native_core_fn_free_livesocket(pointer, $0) } + } + + public static func connect(_ url: String, _ timeout: TimeInterval) async throws -> LiveSocket { + return + try await uniffiRustCallAsync( + rustFutureFunc: { + uniffi_liveview_native_core_fn_constructor_livesocket_connect(FfiConverterString.lower(url), FfiConverterDuration.lower(timeout)) + }, + pollFunc: ffi_liveview_native_core_rust_future_poll_pointer, + completeFunc: ffi_liveview_native_core_rust_future_complete_pointer, + freeFunc: ffi_liveview_native_core_rust_future_free_pointer, + liftFunc: FfiConverterTypeLiveSocket.lift, + errorHandler: FfiConverterTypeLiveSocketError.lift + ) + } + + open func joinLiveviewChannel() async throws -> LiveChannel { + return + try await uniffiRustCallAsync( + rustFutureFunc: { + uniffi_liveview_native_core_fn_method_livesocket_join_liveview_channel( + self.uniffiClonePointer() + ) + }, + pollFunc: ffi_liveview_native_core_rust_future_poll_pointer, + completeFunc: ffi_liveview_native_core_rust_future_complete_pointer, + freeFunc: ffi_liveview_native_core_rust_future_free_pointer, + liftFunc: FfiConverterTypeLiveChannel.lift, + errorHandler: FfiConverterTypeLiveSocketError.lift + ) + } + + open func socket() -> Socket { + return try! FfiConverterTypeSocket_lift(try! rustCall { + uniffi_liveview_native_core_fn_method_livesocket_socket(self.uniffiClonePointer(), $0) + }) + } +} + +public struct FfiConverterTypeLiveSocket: FfiConverter { + typealias FfiType = UnsafeMutableRawPointer + typealias SwiftType = LiveSocket + + public static func lift(_ pointer: UnsafeMutableRawPointer) throws -> LiveSocket { + return LiveSocket(unsafeFromRawPointer: pointer) + } + + public static func lower(_ value: LiveSocket) -> UnsafeMutableRawPointer { + return value.uniffiClonePointer() + } + + public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> LiveSocket { + 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: LiveSocket, 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 FfiConverterTypeLiveSocket_lift(_ pointer: UnsafeMutableRawPointer) throws -> LiveSocket { + return try FfiConverterTypeLiveSocket.lift(pointer) +} + +public func FfiConverterTypeLiveSocket_lower(_ value: LiveSocket) -> UnsafeMutableRawPointer { + return FfiConverterTypeLiveSocket.lower(value) +} + +public protocol NodeProtocol: AnyObject { + func attributes() -> [Attribute] + + func data() -> NodeData + + func display() -> String + + func document() -> Document + + func getAttribute(_ name: AttributeName) -> Attribute? + + func getChildren() -> [Node] + + func getDepthFirstChildren() -> [Node] + + 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 getAttribute(_ name: AttributeName) -> Attribute? { + return try! FfiConverterOptionTypeAttribute.lift(try! rustCall { + uniffi_liveview_native_core_fn_method_node_get_attribute(self.uniffiClonePointer(), + FfiConverterTypeAttributeName.lower(name), $0) + }) + } + + open func getChildren() -> [Node] { + return try! FfiConverterSequenceTypeNode.lift(try! rustCall { + uniffi_liveview_native_core_fn_method_node_get_children(self.uniffiClonePointer(), $0) + }) + } + + open func getDepthFirstChildren() -> [Node] { + return try! FfiConverterSequenceTypeNode.lift(try! rustCall { + uniffi_liveview_native_core_fn_method_node_get_depth_first_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 {} + +public enum LiveSocketError { + case Phoenix(error: String + ) + case Request(error: String + ) + case Parse(error: ParseError + ) + case JsonDeserialization(error: String + ) + case CsfrTokenMissing + case PhoenixIdMissing + case PhoenixSessionMissing + case PhoenixStaticMissing + case PhoenixMainMissing + case NoHostInUrl + case NoUploadToken + case SchemeNotSupported(scheme: String + ) + case Upload(error: UploadError + ) + case NoDocumentInJoinPayload + case DocumentMerge(error: MergeError + ) + case DocumentRender(error: RenderError + ) + case NoInputRefInDocument + case Serde(error: String + ) + case Events(error: String + ) +} + +public struct FfiConverterTypeLiveSocketError: FfiConverterRustBuffer { + typealias SwiftType = LiveSocketError + + public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> LiveSocketError { + let variant: Int32 = try readInt(&buf) + switch variant { + case 1: return try .Phoenix( + error: FfiConverterString.read(from: &buf) + ) + case 2: return try .Request( + error: FfiConverterString.read(from: &buf) + ) + case 3: return try .Parse( + error: FfiConverterTypeParseError.read(from: &buf) + ) + case 4: return try .JsonDeserialization( + error: FfiConverterString.read(from: &buf) + ) + case 5: return .CsfrTokenMissing + case 6: return .PhoenixIdMissing + case 7: return .PhoenixSessionMissing + case 8: return .PhoenixStaticMissing + case 9: return .PhoenixMainMissing + case 10: return .NoHostInUrl + case 11: return .NoUploadToken + case 12: return try .SchemeNotSupported( + scheme: FfiConverterString.read(from: &buf) + ) + case 13: return try .Upload( + error: FfiConverterTypeUploadError.read(from: &buf) + ) + case 14: return .NoDocumentInJoinPayload + case 15: return try .DocumentMerge( + error: FfiConverterTypeMergeError.read(from: &buf) + ) + case 16: return try .DocumentRender( + error: FfiConverterTypeRenderError.read(from: &buf) + ) + case 17: return .NoInputRefInDocument + case 18: return try .Serde( + error: FfiConverterString.read(from: &buf) + ) + case 19: return try .Events( + error: FfiConverterString.read(from: &buf) + ) + default: throw UniffiInternalError.unexpectedEnumCase + } + } + + public static func write(_ value: LiveSocketError, into buf: inout [UInt8]) { + switch value { + case let .Phoenix(error): + writeInt(&buf, Int32(1)) + FfiConverterString.write(error, into: &buf) + + case let .Request(error): + writeInt(&buf, Int32(2)) + FfiConverterString.write(error, into: &buf) + + case let .Parse(error): + writeInt(&buf, Int32(3)) + FfiConverterTypeParseError.write(error, into: &buf) + + case let .JsonDeserialization(error): + writeInt(&buf, Int32(4)) + FfiConverterString.write(error, into: &buf) + + case .CsfrTokenMissing: + writeInt(&buf, Int32(5)) + + case .PhoenixIdMissing: + writeInt(&buf, Int32(6)) + + case .PhoenixSessionMissing: + writeInt(&buf, Int32(7)) + + case .PhoenixStaticMissing: + writeInt(&buf, Int32(8)) + + case .PhoenixMainMissing: + writeInt(&buf, Int32(9)) + + case .NoHostInUrl: + writeInt(&buf, Int32(10)) + + case .NoUploadToken: + writeInt(&buf, Int32(11)) + + case let .SchemeNotSupported(scheme): + writeInt(&buf, Int32(12)) + FfiConverterString.write(scheme, into: &buf) + + case let .Upload(error): + writeInt(&buf, Int32(13)) + FfiConverterTypeUploadError.write(error, into: &buf) + + case .NoDocumentInJoinPayload: + writeInt(&buf, Int32(14)) + + case let .DocumentMerge(error): + writeInt(&buf, Int32(15)) + FfiConverterTypeMergeError.write(error, into: &buf) + + case let .DocumentRender(error): + writeInt(&buf, Int32(16)) + FfiConverterTypeRenderError.write(error, into: &buf) + + case .NoInputRefInDocument: + writeInt(&buf, Int32(17)) + + case let .Serde(error): + writeInt(&buf, Int32(18)) + FfiConverterString.write(error, into: &buf) + + case let .Events(error): + writeInt(&buf, Int32(19)) + FfiConverterString.write(error, into: &buf) + } + } +} + +extension LiveSocketError: Equatable, Hashable {} + +extension LiveSocketError: Foundation.LocalizedError { + public var errorDescription: String? { + String(reflecting: self) + } +} + +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) + } + } +} + +extension MergeError: Equatable, Hashable {} + +extension MergeError: Foundation.LocalizedError { + public var errorDescription: String? { + String(reflecting: self) + } +} + +// 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: Foundation.LocalizedError { + public var errorDescription: String? { + String(reflecting: self) + } +} + +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: Foundation.LocalizedError { + public var errorDescription: String? { + String(reflecting: self) + } +} + +public enum StreamConversionError { + case NoStreamId(message: String) +} + +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 try .NoStreamId( + message: FfiConverterString.read(from: &buf) + ) + + default: throw UniffiInternalError.unexpectedEnumCase + } + } + + public static func write(_ value: StreamConversionError, into buf: inout [UInt8]) { + switch value { + case .NoStreamId(_ /* message is ignored*/ ): + writeInt(&buf, Int32(1)) + } + } +} + +extension StreamConversionError: Equatable, Hashable {} + +extension StreamConversionError: Foundation.LocalizedError { + public var errorDescription: String? { + String(reflecting: self) + } +} + +public enum UploadError { + case FileTooLarge + case FileNotAccepted + case Other(error: String + ) +} + +public struct FfiConverterTypeUploadError: FfiConverterRustBuffer { + typealias SwiftType = UploadError + + public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> UploadError { + let variant: Int32 = try readInt(&buf) + switch variant { + case 1: return .FileTooLarge + case 2: return .FileNotAccepted + case 3: return try .Other( + error: FfiConverterString.read(from: &buf) + ) + default: throw UniffiInternalError.unexpectedEnumCase + } + } + + public static func write(_ value: UploadError, into buf: inout [UInt8]) { + switch value { + case .FileTooLarge: + writeInt(&buf, Int32(1)) + + case .FileNotAccepted: + writeInt(&buf, Int32(2)) + + case let .Other(error): + writeInt(&buf, Int32(3)) + FfiConverterString.write(error, into: &buf) + } + } +} + +extension UploadError: Equatable, Hashable {} + +extension UploadError: Foundation.LocalizedError { + public var errorDescription: String? { + String(reflecting: self) + } +} + +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 FfiConverterOptionTypeAttribute: FfiConverterRustBuffer { + typealias SwiftType = Attribute? + + public static func write(_ value: SwiftType, into buf: inout [UInt8]) { + guard let value = value else { + writeInt(&buf, Int8(0)) + return + } + writeInt(&buf, Int8(1)) + FfiConverterTypeAttribute.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 FfiConverterTypeAttribute.read(from: &buf) + default: throw UniffiInternalError.unexpectedOptionalTag + } + } +} + +private struct FfiConverterSequenceTypeNode: FfiConverterRustBuffer { + typealias SwiftType = [Node] + + public static func write(_ value: [Node], into buf: inout [UInt8]) { + let len = Int32(value.count) + writeInt(&buf, len) + for item in value { + FfiConverterTypeNode.write(item, into: &buf) + } + } + + public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> [Node] { + let len: Int32 = try readInt(&buf) + var seq = [Node]() + seq.reserveCapacity(Int(len)) + for _ in 0 ..< len { + try seq.append(FfiConverterTypeNode.read(from: &buf)) + } + return seq + } +} + +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 let UNIFFI_RUST_FUTURE_POLL_READY: Int8 = 0 +private let UNIFFI_RUST_FUTURE_POLL_MAYBE_READY: Int8 = 1 + +private let uniffiContinuationHandleMap = UniffiHandleMap>() + +private func uniffiRustCallAsync( + rustFutureFunc: () -> UInt64, + pollFunc: (UInt64, @escaping UniffiRustFutureContinuationCallback, UInt64) -> Void, + completeFunc: (UInt64, UnsafeMutablePointer) -> F, + freeFunc: (UInt64) -> Void, + liftFunc: (F) throws -> T, + errorHandler: ((RustBuffer) throws -> Swift.Error)? +) async throws -> T { + // Make sure to call uniffiEnsureInitialized() since future creation doesn't have a + // RustCallStatus param, so doesn't use makeRustCall() + uniffiEnsureInitialized() + let rustFuture = rustFutureFunc() + defer { + freeFunc(rustFuture) + } + var pollResult: Int8 + repeat { + pollResult = await withUnsafeContinuation { + pollFunc( + rustFuture, + uniffiFutureContinuationCallback, + uniffiContinuationHandleMap.insert(obj: $0) + ) + } + } while pollResult != UNIFFI_RUST_FUTURE_POLL_READY + + return try liftFunc(makeRustCall( + { completeFunc(rustFuture, $0) }, + errorHandler: errorHandler + )) +} + +// Callback handlers for an async calls. These are invoked by Rust when the future is ready. They +// lift the return value or error and resume the suspended function. +private func uniffiFutureContinuationCallback(handle: UInt64, pollResult: Int8) { + if let continuation = try? uniffiContinuationHandleMap.remove(handle: handle) { + continuation.resume(returning: pollResult) + } else { + print("uniffiFutureContinuationCallback invalid handle") + } +} + +private enum InitializationResult { + case ok + case contractVersionMismatch + case apiChecksumMismatch +} + +// Use a global variable 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_node() != 62413 { + 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_livechannel_channel() != 14836 { + return InitializationResult.apiChecksumMismatch + } + if uniffi_liveview_native_core_checksum_method_livechannel_get_phx_ref_from_upload_join_payload() != 35275 { + return InitializationResult.apiChecksumMismatch + } + if uniffi_liveview_native_core_checksum_method_livechannel_join_payload() != 65526 { + return InitializationResult.apiChecksumMismatch + } + if uniffi_liveview_native_core_checksum_method_livechannel_merge_diffs() != 5265 { + return InitializationResult.apiChecksumMismatch + } + if uniffi_liveview_native_core_checksum_method_livechannel_upload_file() != 60235 { + return InitializationResult.apiChecksumMismatch + } + if uniffi_liveview_native_core_checksum_method_livechannel_validate_upload() != 48635 { + return InitializationResult.apiChecksumMismatch + } + if uniffi_liveview_native_core_checksum_method_livesocket_join_liveview_channel() != 7366 { + return InitializationResult.apiChecksumMismatch + } + if uniffi_liveview_native_core_checksum_method_livesocket_socket() != 14037 { + 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_attribute() != 29873 { + return InitializationResult.apiChecksumMismatch + } + if uniffi_liveview_native_core_checksum_method_node_get_children() != 25833 { + return InitializationResult.apiChecksumMismatch + } + if uniffi_liveview_native_core_checksum_method_node_get_depth_first_children() != 59594 { + 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_livefile_new() != 61934 { + return InitializationResult.apiChecksumMismatch + } + if uniffi_liveview_native_core_checksum_constructor_livesocket_connect() != 39686 { + return InitializationResult.apiChecksumMismatch + } + if uniffi_liveview_native_core_checksum_constructor_livesocket_new() != 4894 { + 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 diff --git a/crates/core/liveview-native-core-swift/Sources/LiveViewNativeCore/PhoenixChannelsClient.swift b/crates/core/liveview-native-core-swift/Sources/LiveViewNativeCore/PhoenixChannelsClient.swift new file mode 100644 index 00000000..998319a3 --- /dev/null +++ b/crates/core/liveview-native-core-swift/Sources/LiveViewNativeCore/PhoenixChannelsClient.swift @@ -0,0 +1,6259 @@ +// 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(PhoenixChannelsClientFFI) + import PhoenixChannelsClientFFI +#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_phoenix_channels_client_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_phoenix_channels_client_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 to 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 { + let neverThrow: ((RustBuffer) throws -> Never)? = nil + return try makeRustCall(callback, errorHandler: neverThrow) +} + +private func rustCallWithError( + _ errorHandler: @escaping (RustBuffer) throws -> E, + _ callback: (UnsafeMutablePointer) -> T +) throws -> T { + try makeRustCall(callback, errorHandler: errorHandler) +} + +private func makeRustCall( + _ callback: (UnsafeMutablePointer) -> T, + errorHandler: ((RustBuffer) throws -> E)? +) 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 -> E)? +) 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 FfiConverterUInt8: FfiConverterPrimitive { + typealias FfiType = UInt8 + typealias SwiftType = UInt8 + + public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> UInt8 { + return try lift(readInt(&buf)) + } + + public static func write(_ value: UInt8, into buf: inout [UInt8]) { + writeInt(&buf, lower(value)) + } +} + +private struct FfiConverterUInt16: FfiConverterPrimitive { + typealias FfiType = UInt16 + typealias SwiftType = UInt16 + + public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> UInt16 { + return try lift(readInt(&buf)) + } + + public static func write(_ value: SwiftType, into buf: inout [UInt8]) { + writeInt(&buf, lower(value)) + } +} + +private struct FfiConverterUInt64: FfiConverterPrimitive { + typealias FfiType = UInt64 + typealias SwiftType = UInt64 + + public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> UInt64 { + return try lift(readInt(&buf)) + } + + public static func write(_ value: SwiftType, into buf: inout [UInt8]) { + writeInt(&buf, lower(value)) + } +} + +private struct FfiConverterInt64: FfiConverterPrimitive { + typealias FfiType = Int64 + typealias SwiftType = Int64 + + public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> Int64 { + return try lift(readInt(&buf)) + } + + public static func write(_ value: Int64, into buf: inout [UInt8]) { + writeInt(&buf, lower(value)) + } +} + +private struct FfiConverterDouble: FfiConverterPrimitive { + typealias FfiType = Double + typealias SwiftType = Double + + public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> Double { + return try lift(readDouble(&buf)) + } + + public static func write(_ value: Double, into buf: inout [UInt8]) { + writeDouble(&buf, lower(value)) + } +} + +private struct FfiConverterBool: FfiConverter { + typealias FfiType = Int8 + typealias SwiftType = Bool + + public static func lift(_ value: Int8) throws -> Bool { + return value != 0 + } + + public static func lower(_ value: Bool) -> Int8 { + return value ? 1 : 0 + } + + public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> Bool { + return try lift(readInt(&buf)) + } + + public static func write(_ value: Bool, 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) + } +} + +private struct FfiConverterData: FfiConverterRustBuffer { + typealias SwiftType = Data + + public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> Data { + let len: Int32 = try readInt(&buf) + return try Data(readBytes(&buf, count: Int(len))) + } + + public static func write(_ value: Data, into buf: inout [UInt8]) { + let len = Int32(value.count) + writeInt(&buf, len) + writeBytes(&buf, value) + } +} + +private struct FfiConverterTimestamp: FfiConverterRustBuffer { + typealias SwiftType = Date + + public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> Date { + let seconds: Int64 = try readInt(&buf) + let nanoseconds: UInt32 = try readInt(&buf) + if seconds >= 0 { + let delta = Double(seconds) + (Double(nanoseconds) / 1.0e9) + return Date(timeIntervalSince1970: delta) + } else { + let delta = Double(seconds) - (Double(nanoseconds) / 1.0e9) + return Date(timeIntervalSince1970: delta) + } + } + + public static func write(_ value: Date, into buf: inout [UInt8]) { + var delta = value.timeIntervalSince1970 + var sign: Int64 = 1 + if delta < 0 { + // The nanoseconds portion of the epoch offset must always be + // positive, to simplify the calculation we will use the absolute + // value of the offset. + sign = -1 + delta = -delta + } + if delta.rounded(.down) > Double(Int64.max) { + fatalError("Timestamp overflow, exceeds max bounds supported by Uniffi") + } + let seconds = Int64(delta) + let nanoseconds = UInt32((delta - Double(seconds)) * 1.0e9) + writeInt(&buf, sign * seconds) + writeInt(&buf, nanoseconds) + } +} + +private struct FfiConverterDuration: FfiConverterRustBuffer { + typealias SwiftType = TimeInterval + + public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> TimeInterval { + let seconds: UInt64 = try readInt(&buf) + let nanoseconds: UInt32 = try readInt(&buf) + return Double(seconds) + (Double(nanoseconds) / 1.0e9) + } + + public static func write(_ value: TimeInterval, into buf: inout [UInt8]) { + if value.rounded(.down) > Double(Int64.max) { + fatalError("Duration overflow, exceeds max bounds supported by Uniffi") + } + + if value < 0 { + fatalError("Invalid duration, must be non-negative") + } + + let seconds = UInt64(value) + let nanoseconds = UInt32((value - Double(seconds)) * 1.0e9) + writeInt(&buf, seconds) + writeInt(&buf, nanoseconds) + } +} + +/** + * A [Channel] is created with [Socket::channel](crate::Socket::channel) + * + * It represents a unique connection to the topic, and as a result, you may join + * the same topic many times, each time receiving a new, unique `Channel` instance. + * + * To leave a topic/channel, you can either await the result of `Channel::leave`, or + * drop the channel. Once all references to a specific `Channel` are dropped, if it + * hasn't yet left its channel, this is + * f sending messages to the channel: + * + * * [Channel::call] to send a message and await a reply from the server + * * [Channel::cast] to send a message and ignore any replies + + */ +public protocol ChannelProtocol: AnyObject { + /** + * Like `send`, except it takes a configurable `timeout` for awaiting the reply. + * + * If `timeout` is None, it is equivalent to `send`, and waits forever. + * If `timeout` is Some(Duration), then waiting for the reply will stop after the duration expires, + * and a `SendError::Timeout` will be produced. If the reply is received before that occurs, then + * the reply payload will be returned. + */ + func call(event: Event, payload: Payload, timeout: TimeInterval) async throws -> Payload + + /** + * Sends `event` with `payload` to this channel, and returns `Ok` if successful. + * + * This function does not wait for any reply, if you need the reply, then use `send` or `send_with_timeout`. + */ + func cast(event: Event, payload: Payload) async throws + + /** + * Broadcasts [EventPayload] sent from server. + */ + func events() -> Events + + /** + * Join [Channel::topic] with [Channel::payload] within `timeout`. + */ + func join(timeout: TimeInterval) async throws -> Payload + + /** + * Leaves this channel + */ + func leave() async throws + + /** + * Propagates panic from async task. + */ + func listenerShutdown() async throws + + /** + * Returns the payload sent to the channel when joined + */ + func payload() -> Payload + + /** + * Propagates panic from async task. + */ + func shutdown() async throws + + /** + * The current [ChannelStatus]. + * + * Use [Channel::statuses] to receive changes to the status. + */ + func status() -> ChannelStatus + + /** + * Broadcasts [Channel::status] changes. + * + * Use [Channel::status] to see the current status. + */ + func statuses() -> ChannelStatuses + + /** + * Returns the topic this channel is connected to + */ + func topic() -> Topic +} + +/** + * A [Channel] is created with [Socket::channel](crate::Socket::channel) + * + * It represents a unique connection to the topic, and as a result, you may join + * the same topic many times, each time receiving a new, unique `Channel` instance. + * + * To leave a topic/channel, you can either await the result of `Channel::leave`, or + * drop the channel. Once all references to a specific `Channel` are dropped, if it + * hasn't yet left its channel, this is + * f sending messages to the channel: + * + * * [Channel::call] to send a message and await a reply from the server + * * [Channel::cast] to send a message and ignore any replies + + */ +open class Channel: + ChannelProtocol +{ + 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_phoenix_channels_client_fn_clone_channel(self.pointer, $0) } + } + + // No primary constructor declared for this class. + + deinit { + guard let pointer = pointer else { + return + } + + try! rustCall { uniffi_phoenix_channels_client_fn_free_channel(pointer, $0) } + } + + /** + * Like `send`, except it takes a configurable `timeout` for awaiting the reply. + * + * If `timeout` is None, it is equivalent to `send`, and waits forever. + * If `timeout` is Some(Duration), then waiting for the reply will stop after the duration expires, + * and a `SendError::Timeout` will be produced. If the reply is received before that occurs, then + * the reply payload will be returned. + */ + open func call(event: Event, payload: Payload, timeout: TimeInterval) async throws -> Payload { + return + try await uniffiRustCallAsync( + rustFutureFunc: { + uniffi_phoenix_channels_client_fn_method_channel_call( + self.uniffiClonePointer(), + FfiConverterTypeEvent.lower(event), FfiConverterTypePayload.lower(payload), FfiConverterDuration.lower(timeout) + ) + }, + pollFunc: ffi_phoenix_channels_client_rust_future_poll_rust_buffer, + completeFunc: ffi_phoenix_channels_client_rust_future_complete_rust_buffer, + freeFunc: ffi_phoenix_channels_client_rust_future_free_rust_buffer, + liftFunc: FfiConverterTypePayload.lift, + errorHandler: FfiConverterTypeCallError.lift + ) + } + + /** + * Sends `event` with `payload` to this channel, and returns `Ok` if successful. + * + * This function does not wait for any reply, if you need the reply, then use `send` or `send_with_timeout`. + */ + open func cast(event: Event, payload: Payload) async throws { + return + try await uniffiRustCallAsync( + rustFutureFunc: { + uniffi_phoenix_channels_client_fn_method_channel_cast( + self.uniffiClonePointer(), + FfiConverterTypeEvent.lower(event), FfiConverterTypePayload.lower(payload) + ) + }, + pollFunc: ffi_phoenix_channels_client_rust_future_poll_void, + completeFunc: ffi_phoenix_channels_client_rust_future_complete_void, + freeFunc: ffi_phoenix_channels_client_rust_future_free_void, + liftFunc: { $0 }, + errorHandler: FfiConverterTypeCastError.lift + ) + } + + /** + * Broadcasts [EventPayload] sent from server. + */ + open func events() -> Events { + return try! FfiConverterTypeEvents.lift(try! rustCall { + uniffi_phoenix_channels_client_fn_method_channel_events(self.uniffiClonePointer(), $0) + }) + } + + /** + * Join [Channel::topic] with [Channel::payload] within `timeout`. + */ + open func join(timeout: TimeInterval) async throws -> Payload { + return + try await uniffiRustCallAsync( + rustFutureFunc: { + uniffi_phoenix_channels_client_fn_method_channel_join( + self.uniffiClonePointer(), + FfiConverterDuration.lower(timeout) + ) + }, + pollFunc: ffi_phoenix_channels_client_rust_future_poll_rust_buffer, + completeFunc: ffi_phoenix_channels_client_rust_future_complete_rust_buffer, + freeFunc: ffi_phoenix_channels_client_rust_future_free_rust_buffer, + liftFunc: FfiConverterTypePayload.lift, + errorHandler: FfiConverterTypeChannelJoinError.lift + ) + } + + /** + * Leaves this channel + */ + open func leave() async throws { + return + try await uniffiRustCallAsync( + rustFutureFunc: { + uniffi_phoenix_channels_client_fn_method_channel_leave( + self.uniffiClonePointer() + ) + }, + pollFunc: ffi_phoenix_channels_client_rust_future_poll_void, + completeFunc: ffi_phoenix_channels_client_rust_future_complete_void, + freeFunc: ffi_phoenix_channels_client_rust_future_free_void, + liftFunc: { $0 }, + errorHandler: FfiConverterTypeLeaveError.lift + ) + } + + /** + * Propagates panic from async task. + */ + open func listenerShutdown() async throws { + return + try await uniffiRustCallAsync( + rustFutureFunc: { + uniffi_phoenix_channels_client_fn_method_channel_listener_shutdown( + self.uniffiClonePointer() + ) + }, + pollFunc: ffi_phoenix_channels_client_rust_future_poll_void, + completeFunc: ffi_phoenix_channels_client_rust_future_complete_void, + freeFunc: ffi_phoenix_channels_client_rust_future_free_void, + liftFunc: { $0 }, + errorHandler: FfiConverterTypeChannelShutdownError.lift + ) + } + + /** + * Returns the payload sent to the channel when joined + */ + open func payload() -> Payload { + return try! FfiConverterTypePayload.lift(try! rustCall { + uniffi_phoenix_channels_client_fn_method_channel_payload(self.uniffiClonePointer(), $0) + }) + } + + /** + * Propagates panic from async task. + */ + open func shutdown() async throws { + return + try await uniffiRustCallAsync( + rustFutureFunc: { + uniffi_phoenix_channels_client_fn_method_channel_shutdown( + self.uniffiClonePointer() + ) + }, + pollFunc: ffi_phoenix_channels_client_rust_future_poll_void, + completeFunc: ffi_phoenix_channels_client_rust_future_complete_void, + freeFunc: ffi_phoenix_channels_client_rust_future_free_void, + liftFunc: { $0 }, + errorHandler: FfiConverterTypeChannelShutdownError.lift + ) + } + + /** + * The current [ChannelStatus]. + * + * Use [Channel::statuses] to receive changes to the status. + */ + open func status() -> ChannelStatus { + return try! FfiConverterTypeChannelStatus.lift(try! rustCall { + uniffi_phoenix_channels_client_fn_method_channel_status(self.uniffiClonePointer(), $0) + }) + } + + /** + * Broadcasts [Channel::status] changes. + * + * Use [Channel::status] to see the current status. + */ + open func statuses() -> ChannelStatuses { + return try! FfiConverterTypeChannelStatuses.lift(try! rustCall { + uniffi_phoenix_channels_client_fn_method_channel_statuses(self.uniffiClonePointer(), $0) + }) + } + + /** + * Returns the topic this channel is connected to + */ + open func topic() -> Topic { + return try! FfiConverterTypeTopic.lift(try! rustCall { + uniffi_phoenix_channels_client_fn_method_channel_topic(self.uniffiClonePointer(), $0) + }) + } +} + +public struct FfiConverterTypeChannel: FfiConverter { + typealias FfiType = UnsafeMutableRawPointer + typealias SwiftType = Channel + + public static func lift(_ pointer: UnsafeMutableRawPointer) throws -> Channel { + return Channel(unsafeFromRawPointer: pointer) + } + + public static func lower(_ value: Channel) -> UnsafeMutableRawPointer { + return value.uniffiClonePointer() + } + + public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> Channel { + 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: Channel, 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 FfiConverterTypeChannel_lift(_ pointer: UnsafeMutableRawPointer) throws -> Channel { + return try FfiConverterTypeChannel.lift(pointer) +} + +public func FfiConverterTypeChannel_lower(_ value: Channel) -> UnsafeMutableRawPointer { + return FfiConverterTypeChannel.lower(value) +} + +/** + * Waits for [ChannelStatus] changes from the [Channel](crate::Channel). + */ +public protocol ChannelStatusesProtocol: AnyObject { + /** + * Wait for next [ChannelStatus] when the [Channel::status](super::Channel::status) changes. + */ + func status() async throws -> ChannelStatus +} + +/** + * Waits for [ChannelStatus] changes from the [Channel](crate::Channel). + */ +open class ChannelStatuses: + ChannelStatusesProtocol +{ + 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_phoenix_channels_client_fn_clone_channelstatuses(self.pointer, $0) } + } + + // No primary constructor declared for this class. + + deinit { + guard let pointer = pointer else { + return + } + + try! rustCall { uniffi_phoenix_channels_client_fn_free_channelstatuses(pointer, $0) } + } + + /** + * Wait for next [ChannelStatus] when the [Channel::status](super::Channel::status) changes. + */ + open func status() async throws -> ChannelStatus { + return + try await uniffiRustCallAsync( + rustFutureFunc: { + uniffi_phoenix_channels_client_fn_method_channelstatuses_status( + self.uniffiClonePointer() + ) + }, + pollFunc: ffi_phoenix_channels_client_rust_future_poll_rust_buffer, + completeFunc: ffi_phoenix_channels_client_rust_future_complete_rust_buffer, + freeFunc: ffi_phoenix_channels_client_rust_future_free_rust_buffer, + liftFunc: FfiConverterTypeChannelStatus.lift, + errorHandler: FfiConverterTypeStatusesError.lift + ) + } +} + +public struct FfiConverterTypeChannelStatuses: FfiConverter { + typealias FfiType = UnsafeMutableRawPointer + typealias SwiftType = ChannelStatuses + + public static func lift(_ pointer: UnsafeMutableRawPointer) throws -> ChannelStatuses { + return ChannelStatuses(unsafeFromRawPointer: pointer) + } + + public static func lower(_ value: ChannelStatuses) -> UnsafeMutableRawPointer { + return value.uniffiClonePointer() + } + + public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> ChannelStatuses { + 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: ChannelStatuses, 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 FfiConverterTypeChannelStatuses_lift(_ pointer: UnsafeMutableRawPointer) throws -> ChannelStatuses { + return try FfiConverterTypeChannelStatuses.lift(pointer) +} + +public func FfiConverterTypeChannelStatuses_lower(_ value: ChannelStatuses) -> UnsafeMutableRawPointer { + return FfiConverterTypeChannelStatuses.lower(value) +} + +/** + * Waits for [EventPayload]s sent from the server. + */ +public protocol EventsProtocol: AnyObject { + /** + * Wait for next [EventPayload] sent from the server. + */ + func event() async throws -> EventPayload +} + +/** + * Waits for [EventPayload]s sent from the server. + */ +open class Events: + EventsProtocol +{ + 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_phoenix_channels_client_fn_clone_events(self.pointer, $0) } + } + + // No primary constructor declared for this class. + + deinit { + guard let pointer = pointer else { + return + } + + try! rustCall { uniffi_phoenix_channels_client_fn_free_events(pointer, $0) } + } + + /** + * Wait for next [EventPayload] sent from the server. + */ + open func event() async throws -> EventPayload { + return + try await uniffiRustCallAsync( + rustFutureFunc: { + uniffi_phoenix_channels_client_fn_method_events_event( + self.uniffiClonePointer() + ) + }, + pollFunc: ffi_phoenix_channels_client_rust_future_poll_rust_buffer, + completeFunc: ffi_phoenix_channels_client_rust_future_complete_rust_buffer, + freeFunc: ffi_phoenix_channels_client_rust_future_free_rust_buffer, + liftFunc: FfiConverterTypeEventPayload.lift, + errorHandler: FfiConverterTypeEventsError.lift + ) + } +} + +public struct FfiConverterTypeEvents: FfiConverter { + typealias FfiType = UnsafeMutableRawPointer + typealias SwiftType = Events + + public static func lift(_ pointer: UnsafeMutableRawPointer) throws -> Events { + return Events(unsafeFromRawPointer: pointer) + } + + public static func lower(_ value: Events) -> UnsafeMutableRawPointer { + return value.uniffiClonePointer() + } + + public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> Events { + 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: Events, 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 FfiConverterTypeEvents_lift(_ pointer: UnsafeMutableRawPointer) throws -> Events { + return try FfiConverterTypeEvents.lift(pointer) +} + +public func FfiConverterTypeEvents_lower(_ value: Events) -> UnsafeMutableRawPointer { + return FfiConverterTypeEvents.lower(value) +} + +/** + * A [`Socket`] manages the underlying WebSocket connection used to talk to Phoenix. + * + * It acts as the primary interface (along with [`Channel`]) for working with Phoenix Channels. + * + * When a client is created, it is disconnected, and must be explicitly connected via [`Self::connect`]. + * Once connected, a worker task is spawned that acts as the broker for messages being sent or + * received over the socket. + * + * Once connected, the more useful [`Channel`] instance can be obtained via [`Self::channel`]. Most functionality + * related to channels is exposed there. + */ +public protocol SocketProtocol: AnyObject { + /** + * Creates a new, unjoined Phoenix Channel + */ + func channel(topic: Topic, payload: Payload?) async throws -> Channel + + /** + * Connects this client to the configured Phoenix Channels endpoint + * + * This function must be called before using the client to join channels, etc. + * + * A join handle to the socket worker is returned, we can use this to wait until the worker + * exits to ensure graceful termination. Otherwise, when the handle is dropped, it detaches the + * worker from the task runtime (though it will continue to run in the background) + */ + func connect(timeout: TimeInterval) async throws + + /** + * Disconnect the client, regardless of any outstanding channel references + * + * Connected channels will return `ChannelError::Closed` when next used. + * + * New channels will need to be obtained from this client after `connect` is + * called again. + */ + func disconnect() async throws + + /** + * Propagates panic from async task. + */ + func shutdown() async throws + + /** + * The current [SocketStatus]. + * + * Use [Socket::status] to receive changes to the status. + */ + func status() -> SocketStatus + + /** + * Broadcasts [Socket::status] changes. + * + * Use [Socket::status] to see the current status. + */ + func statuses() -> SocketStatuses + + /** + * The `url` passed to [Socket::spawn] + */ + func url() -> Url +} + +/** + * A [`Socket`] manages the underlying WebSocket connection used to talk to Phoenix. + * + * It acts as the primary interface (along with [`Channel`]) for working with Phoenix Channels. + * + * When a client is created, it is disconnected, and must be explicitly connected via [`Self::connect`]. + * Once connected, a worker task is spawned that acts as the broker for messages being sent or + * received over the socket. + * + * Once connected, the more useful [`Channel`] instance can be obtained via [`Self::channel`]. Most functionality + * related to channels is exposed there. + */ +open class Socket: + SocketProtocol +{ + 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_phoenix_channels_client_fn_clone_socket(self.pointer, $0) } + } + + // No primary constructor declared for this class. + + deinit { + guard let pointer = pointer else { + return + } + + try! rustCall { uniffi_phoenix_channels_client_fn_free_socket(pointer, $0) } + } + + /** + * Spawns a new [Socket] that must be [Socket::connect]ed. + */ + public static func spawn(url: Url, cookies: [String]?) throws -> Socket { + return try FfiConverterTypeSocket.lift(rustCallWithError(FfiConverterTypeSpawnError.lift) { + uniffi_phoenix_channels_client_fn_constructor_socket_spawn( + FfiConverterTypeUrl.lower(url), + FfiConverterOptionSequenceString.lower(cookies), $0 + ) + }) + } + + /** + * Creates a new, unjoined Phoenix Channel + */ + open func channel(topic: Topic, payload: Payload?) async throws -> Channel { + return + try await uniffiRustCallAsync( + rustFutureFunc: { + uniffi_phoenix_channels_client_fn_method_socket_channel( + self.uniffiClonePointer(), + FfiConverterTypeTopic.lower(topic), FfiConverterOptionTypePayload.lower(payload) + ) + }, + pollFunc: ffi_phoenix_channels_client_rust_future_poll_pointer, + completeFunc: ffi_phoenix_channels_client_rust_future_complete_pointer, + freeFunc: ffi_phoenix_channels_client_rust_future_free_pointer, + liftFunc: FfiConverterTypeChannel.lift, + errorHandler: FfiConverterTypeSocketChannelError.lift + ) + } + + /** + * Connects this client to the configured Phoenix Channels endpoint + * + * This function must be called before using the client to join channels, etc. + * + * A join handle to the socket worker is returned, we can use this to wait until the worker + * exits to ensure graceful termination. Otherwise, when the handle is dropped, it detaches the + * worker from the task runtime (though it will continue to run in the background) + */ + open func connect(timeout: TimeInterval) async throws { + return + try await uniffiRustCallAsync( + rustFutureFunc: { + uniffi_phoenix_channels_client_fn_method_socket_connect( + self.uniffiClonePointer(), + FfiConverterDuration.lower(timeout) + ) + }, + pollFunc: ffi_phoenix_channels_client_rust_future_poll_void, + completeFunc: ffi_phoenix_channels_client_rust_future_complete_void, + freeFunc: ffi_phoenix_channels_client_rust_future_free_void, + liftFunc: { $0 }, + errorHandler: FfiConverterTypeConnectError.lift + ) + } + + /** + * Disconnect the client, regardless of any outstanding channel references + * + * Connected channels will return `ChannelError::Closed` when next used. + * + * New channels will need to be obtained from this client after `connect` is + * called again. + */ + open func disconnect() async throws { + return + try await uniffiRustCallAsync( + rustFutureFunc: { + uniffi_phoenix_channels_client_fn_method_socket_disconnect( + self.uniffiClonePointer() + ) + }, + pollFunc: ffi_phoenix_channels_client_rust_future_poll_void, + completeFunc: ffi_phoenix_channels_client_rust_future_complete_void, + freeFunc: ffi_phoenix_channels_client_rust_future_free_void, + liftFunc: { $0 }, + errorHandler: FfiConverterTypeDisconnectError.lift + ) + } + + /** + * Propagates panic from async task. + */ + open func shutdown() async throws { + return + try await uniffiRustCallAsync( + rustFutureFunc: { + uniffi_phoenix_channels_client_fn_method_socket_shutdown( + self.uniffiClonePointer() + ) + }, + pollFunc: ffi_phoenix_channels_client_rust_future_poll_void, + completeFunc: ffi_phoenix_channels_client_rust_future_complete_void, + freeFunc: ffi_phoenix_channels_client_rust_future_free_void, + liftFunc: { $0 }, + errorHandler: FfiConverterTypeSocketShutdownError.lift + ) + } + + /** + * The current [SocketStatus]. + * + * Use [Socket::status] to receive changes to the status. + */ + open func status() -> SocketStatus { + return try! FfiConverterTypeSocketStatus.lift(try! rustCall { + uniffi_phoenix_channels_client_fn_method_socket_status(self.uniffiClonePointer(), $0) + }) + } + + /** + * Broadcasts [Socket::status] changes. + * + * Use [Socket::status] to see the current status. + */ + open func statuses() -> SocketStatuses { + return try! FfiConverterTypeSocketStatuses.lift(try! rustCall { + uniffi_phoenix_channels_client_fn_method_socket_statuses(self.uniffiClonePointer(), $0) + }) + } + + /** + * The `url` passed to [Socket::spawn] + */ + open func url() -> Url { + return try! FfiConverterTypeUrl.lift(try! rustCall { + uniffi_phoenix_channels_client_fn_method_socket_url(self.uniffiClonePointer(), $0) + }) + } +} + +public struct FfiConverterTypeSocket: FfiConverter { + typealias FfiType = UnsafeMutableRawPointer + typealias SwiftType = Socket + + public static func lift(_ pointer: UnsafeMutableRawPointer) throws -> Socket { + return Socket(unsafeFromRawPointer: pointer) + } + + public static func lower(_ value: Socket) -> UnsafeMutableRawPointer { + return value.uniffiClonePointer() + } + + public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> Socket { + 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: Socket, 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 FfiConverterTypeSocket_lift(_ pointer: UnsafeMutableRawPointer) throws -> Socket { + return try FfiConverterTypeSocket.lift(pointer) +} + +public func FfiConverterTypeSocket_lower(_ value: Socket) -> UnsafeMutableRawPointer { + return FfiConverterTypeSocket.lower(value) +} + +/** + * A wrapper anound `observable_status::Statuses` because `uniffi` does not support generics + */ +public protocol SocketStatusesProtocol: AnyObject {} + +/** + * A wrapper anound `observable_status::Statuses` because `uniffi` does not support generics + */ +open class SocketStatuses: + SocketStatusesProtocol +{ + 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_phoenix_channels_client_fn_clone_socketstatuses(self.pointer, $0) } + } + + // No primary constructor declared for this class. + + deinit { + guard let pointer = pointer else { + return + } + + try! rustCall { uniffi_phoenix_channels_client_fn_free_socketstatuses(pointer, $0) } + } +} + +public struct FfiConverterTypeSocketStatuses: FfiConverter { + typealias FfiType = UnsafeMutableRawPointer + typealias SwiftType = SocketStatuses + + public static func lift(_ pointer: UnsafeMutableRawPointer) throws -> SocketStatuses { + return SocketStatuses(unsafeFromRawPointer: pointer) + } + + public static func lower(_ value: SocketStatuses) -> UnsafeMutableRawPointer { + return value.uniffiClonePointer() + } + + public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> SocketStatuses { + 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: SocketStatuses, 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 FfiConverterTypeSocketStatuses_lift(_ pointer: UnsafeMutableRawPointer) throws -> SocketStatuses { + return try FfiConverterTypeSocketStatuses.lift(pointer) +} + +public func FfiConverterTypeSocketStatuses_lower(_ value: SocketStatuses) -> UnsafeMutableRawPointer { + return FfiConverterTypeSocketStatuses.lower(value) +} + +/** + * A [Channel](crate::Channel) topic. + */ +public protocol TopicProtocol: AnyObject {} + +/** + * A [Channel](crate::Channel) topic. + */ +open class Topic: + TopicProtocol +{ + 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_phoenix_channels_client_fn_clone_topic(self.pointer, $0) } + } + + // No primary constructor declared for this class. + + deinit { + guard let pointer = pointer else { + return + } + + try! rustCall { uniffi_phoenix_channels_client_fn_free_topic(pointer, $0) } + } + + /** + * Create [Topic] from string. + */ + public static func fromString(topic: String) -> Topic { + return try! FfiConverterTypeTopic.lift(try! rustCall { + uniffi_phoenix_channels_client_fn_constructor_topic_from_string( + FfiConverterString.lower(topic), $0 + ) + }) + } +} + +public struct FfiConverterTypeTopic: FfiConverter { + typealias FfiType = UnsafeMutableRawPointer + typealias SwiftType = Topic + + public static func lift(_ pointer: UnsafeMutableRawPointer) throws -> Topic { + return Topic(unsafeFromRawPointer: pointer) + } + + public static func lower(_ value: Topic) -> UnsafeMutableRawPointer { + return value.uniffiClonePointer() + } + + public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> Topic { + 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: Topic, 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 FfiConverterTypeTopic_lift(_ pointer: UnsafeMutableRawPointer) throws -> Topic { + return try FfiConverterTypeTopic.lift(pointer) +} + +public func FfiConverterTypeTopic_lower(_ value: Topic) -> UnsafeMutableRawPointer { + return FfiConverterTypeTopic.lower(value) +} + +/** + * [tokio_tungstenite::tungstenite::protocol::frame::CloseFrame], but with `uniffi::support` + * A struct representing the close command. + */ +public struct CloseFrame { + /** + * The reason as a code. + */ + public var code: TungsteniteCloseCode + /** + * The reason as text string. + */ + public var reason: String + + // Default memberwise initializers are never public by default, so we + // declare one manually. + public init( + /** + * The reason as a code. + */ code: TungsteniteCloseCode, + /** + * The reason as text string. + */ reason: String + ) { + self.code = code + self.reason = reason + } +} + +extension CloseFrame: Equatable, Hashable { + public static func == (lhs: CloseFrame, rhs: CloseFrame) -> Bool { + if lhs.code != rhs.code { + return false + } + if lhs.reason != rhs.reason { + return false + } + return true + } + + public func hash(into hasher: inout Hasher) { + hasher.combine(code) + hasher.combine(reason) + } +} + +public struct FfiConverterTypeCloseFrame: FfiConverterRustBuffer { + public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> CloseFrame { + return + try CloseFrame( + code: FfiConverterTypeTungsteniteCloseCode.read(from: &buf), + reason: FfiConverterString.read(from: &buf) + ) + } + + public static func write(_ value: CloseFrame, into buf: inout [UInt8]) { + FfiConverterTypeTungsteniteCloseCode.write(value.code, into: &buf) + FfiConverterString.write(value.reason, into: &buf) + } +} + +public func FfiConverterTypeCloseFrame_lift(_ buf: RustBuffer) throws -> CloseFrame { + return try FfiConverterTypeCloseFrame.lift(buf) +} + +public func FfiConverterTypeCloseFrame_lower(_ value: CloseFrame) -> RustBuffer { + return FfiConverterTypeCloseFrame.lower(value) +} + +/** + * The [EventPayload::event] sent by the server along with the [EventPayload::payload] for that + * [EventPayload::event]. + */ +public struct EventPayload { + /** + * The [Event] name. + */ + public var event: Event + /** + * The data sent for the [EventPayload::event]. + */ + public var payload: Payload + + // Default memberwise initializers are never public by default, so we + // declare one manually. + public init( + /** + * The [Event] name. + */ event: Event, + /** + * The data sent for the [EventPayload::event]. + */ payload: Payload + ) { + self.event = event + self.payload = payload + } +} + +extension EventPayload: Equatable, Hashable { + public static func == (lhs: EventPayload, rhs: EventPayload) -> Bool { + if lhs.event != rhs.event { + return false + } + if lhs.payload != rhs.payload { + return false + } + return true + } + + public func hash(into hasher: inout Hasher) { + hasher.combine(event) + hasher.combine(payload) + } +} + +public struct FfiConverterTypeEventPayload: FfiConverterRustBuffer { + public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> EventPayload { + return + try EventPayload( + event: FfiConverterTypeEvent.read(from: &buf), + payload: FfiConverterTypePayload.read(from: &buf) + ) + } + + public static func write(_ value: EventPayload, into buf: inout [UInt8]) { + FfiConverterTypeEvent.write(value.event, into: &buf) + FfiConverterTypePayload.write(value.payload, into: &buf) + } +} + +public func FfiConverterTypeEventPayload_lift(_ buf: RustBuffer) throws -> EventPayload { + return try FfiConverterTypeEventPayload.lift(buf) +} + +public func FfiConverterTypeEventPayload_lower(_ value: EventPayload) -> RustBuffer { + return FfiConverterTypeEventPayload.lower(value) +} + +/** + * [tokio_tungstenite::tungstenite::protocol::frame::Frame], but with `uniffi` support. + * A struct representing a WebSocket frame. + */ +public struct Frame { + public var header: FrameHeader + public var payload: Data + + // Default memberwise initializers are never public by default, so we + // declare one manually. + public init(header: FrameHeader, payload: Data) { + self.header = header + self.payload = payload + } +} + +extension Frame: Equatable, Hashable { + public static func == (lhs: Frame, rhs: Frame) -> Bool { + if lhs.header != rhs.header { + return false + } + if lhs.payload != rhs.payload { + return false + } + return true + } + + public func hash(into hasher: inout Hasher) { + hasher.combine(header) + hasher.combine(payload) + } +} + +public struct FfiConverterTypeFrame: FfiConverterRustBuffer { + public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> Frame { + return + try Frame( + header: FfiConverterTypeFrameHeader.read(from: &buf), + payload: FfiConverterData.read(from: &buf) + ) + } + + public static func write(_ value: Frame, into buf: inout [UInt8]) { + FfiConverterTypeFrameHeader.write(value.header, into: &buf) + FfiConverterData.write(value.payload, into: &buf) + } +} + +public func FfiConverterTypeFrame_lift(_ buf: RustBuffer) throws -> Frame { + return try FfiConverterTypeFrame.lift(buf) +} + +public func FfiConverterTypeFrame_lower(_ value: Frame) -> RustBuffer { + return FfiConverterTypeFrame.lower(value) +} + +/** + * [tokio_tungstenite::tungstenite::protocol::frame::FrameHeader], but with `uniffi` support. + * A struct representing a WebSocket frame header. + */ +public struct FrameHeader { + /** + * Indicates that the frame is the last one of a possibly fragmented message. + */ + public var isFinal: Bool + /** + * Reserved for protocol extensions. + */ + public var rsv1: Bool + /** + * Reserved for protocol extensions. + */ + public var rsv2: Bool + /** + * Reserved for protocol extensions. + */ + public var rsv3: Bool + /** + * WebSocket protocol opcode. + */ + public var opcode: TungsteniteOpCode + /** + * A frame mask, if any. + */ + public var mask: Data? + + // Default memberwise initializers are never public by default, so we + // declare one manually. + public init( + /** + * Indicates that the frame is the last one of a possibly fragmented message. + */ isFinal: Bool, + /** + * Reserved for protocol extensions. + */ rsv1: Bool, + /** + * Reserved for protocol extensions. + */ rsv2: Bool, + /** + * Reserved for protocol extensions. + */ rsv3: Bool, + /** + * WebSocket protocol opcode. + */ opcode: TungsteniteOpCode, + /** + * A frame mask, if any. + */ mask: Data? + ) { + self.isFinal = isFinal + self.rsv1 = rsv1 + self.rsv2 = rsv2 + self.rsv3 = rsv3 + self.opcode = opcode + self.mask = mask + } +} + +extension FrameHeader: Equatable, Hashable { + public static func == (lhs: FrameHeader, rhs: FrameHeader) -> Bool { + if lhs.isFinal != rhs.isFinal { + return false + } + if lhs.rsv1 != rhs.rsv1 { + return false + } + if lhs.rsv2 != rhs.rsv2 { + return false + } + if lhs.rsv3 != rhs.rsv3 { + return false + } + if lhs.opcode != rhs.opcode { + return false + } + if lhs.mask != rhs.mask { + return false + } + return true + } + + public func hash(into hasher: inout Hasher) { + hasher.combine(isFinal) + hasher.combine(rsv1) + hasher.combine(rsv2) + hasher.combine(rsv3) + hasher.combine(opcode) + hasher.combine(mask) + } +} + +public struct FfiConverterTypeFrameHeader: FfiConverterRustBuffer { + public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> FrameHeader { + return + try FrameHeader( + isFinal: FfiConverterBool.read(from: &buf), + rsv1: FfiConverterBool.read(from: &buf), + rsv2: FfiConverterBool.read(from: &buf), + rsv3: FfiConverterBool.read(from: &buf), + opcode: FfiConverterTypeTungsteniteOpCode.read(from: &buf), + mask: FfiConverterOptionData.read(from: &buf) + ) + } + + public static func write(_ value: FrameHeader, into buf: inout [UInt8]) { + FfiConverterBool.write(value.isFinal, into: &buf) + FfiConverterBool.write(value.rsv1, into: &buf) + FfiConverterBool.write(value.rsv2, into: &buf) + FfiConverterBool.write(value.rsv3, into: &buf) + FfiConverterTypeTungsteniteOpCode.write(value.opcode, into: &buf) + FfiConverterOptionData.write(value.mask, into: &buf) + } +} + +public func FfiConverterTypeFrameHeader_lift(_ buf: RustBuffer) throws -> FrameHeader { + return try FfiConverterTypeFrameHeader.lift(buf) +} + +public func FfiConverterTypeFrameHeader_lower(_ value: FrameHeader) -> RustBuffer { + return FfiConverterTypeFrameHeader.lower(value) +} + +/** + * [http::response::Response], but without the generics that `uniffi` does not support and with `uniffi` support + */ +public struct Response { + public var statusCode: UInt16 + public var headers: [String: [String]] + public var body: Data? + + // Default memberwise initializers are never public by default, so we + // declare one manually. + public init(statusCode: UInt16, headers: [String: [String]], body: Data?) { + self.statusCode = statusCode + self.headers = headers + self.body = body + } +} + +extension Response: Equatable, Hashable { + public static func == (lhs: Response, rhs: Response) -> Bool { + if lhs.statusCode != rhs.statusCode { + return false + } + if lhs.headers != rhs.headers { + return false + } + if lhs.body != rhs.body { + return false + } + return true + } + + public func hash(into hasher: inout Hasher) { + hasher.combine(statusCode) + hasher.combine(headers) + hasher.combine(body) + } +} + +public struct FfiConverterTypeResponse: FfiConverterRustBuffer { + public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> Response { + return + try Response( + statusCode: FfiConverterUInt16.read(from: &buf), + headers: FfiConverterDictionaryStringSequenceString.read(from: &buf), + body: FfiConverterOptionData.read(from: &buf) + ) + } + + public static func write(_ value: Response, into buf: inout [UInt8]) { + FfiConverterUInt16.write(value.statusCode, into: &buf) + FfiConverterDictionaryStringSequenceString.write(value.headers, into: &buf) + FfiConverterOptionData.write(value.body, into: &buf) + } +} + +public func FfiConverterTypeResponse_lift(_ buf: RustBuffer) throws -> Response { + return try FfiConverterTypeResponse.lift(buf) +} + +public func FfiConverterTypeResponse_lower(_ value: Response) -> RustBuffer { + return FfiConverterTypeResponse.lower(value) +} + +/** + * Errors when calling [Channel::call]. + */ +public enum CallError { + /** + * The async task for the [Channel] was already joined by another call, so the [Result] or + * panic from the async task can't be reported here. + */ + case Shutdown + /** + * Error from [Socket::shutdown](crate::Socket::shutdown) or from the server itself that caused + * the [Socket](crate::Socket) to shutdown. + */ + case SocketShutdown( + /** + * Error from [Socket::shutdown](crate::Socket::shutdown) or from the server itself that + * caused the [Socket](crate::Socket) to shutdown. + */ socketShutdownError: SocketShutdownError + ) + /** + * Timeout passed to [Channel::call] has expired. + */ + case Timeout + /** + * Error from [Channel]'s [Socket](crate::Socket)'s underlying + * [tokio_tungstenite::tungstenite::protocol::WebSocket]. + */ + case WebSocket( + /** + * Error from [Channel]'s [Socket](crate::Socket)'s underlying + * [tokio_tungstenite::tungstenite::protocol::WebSocket]. + */ webSocketError: WebSocketError + ) + /** + * [Socket::disconnect](crate::Socket::disconnect) called after [Channel::call] while waiting + * for a reply from the server. + */ + case SocketDisconnected + /** + * An error was returned from the server in reply to [Channel::call]'s `event` and `payload`. + */ + case Reply( + /** + * Error response from the server. + */ reply: Payload + ) +} + +public struct FfiConverterTypeCallError: FfiConverterRustBuffer { + typealias SwiftType = CallError + + public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> CallError { + let variant: Int32 = try readInt(&buf) + switch variant { + case 1: return .Shutdown + case 2: return try .SocketShutdown( + socketShutdownError: FfiConverterTypeSocketShutdownError.read(from: &buf) + ) + case 3: return .Timeout + case 4: return try .WebSocket( + webSocketError: FfiConverterTypeWebSocketError.read(from: &buf) + ) + case 5: return .SocketDisconnected + case 6: return try .Reply( + reply: FfiConverterTypePayload.read(from: &buf) + ) + default: throw UniffiInternalError.unexpectedEnumCase + } + } + + public static func write(_ value: CallError, into buf: inout [UInt8]) { + switch value { + case .Shutdown: + writeInt(&buf, Int32(1)) + + case let .SocketShutdown(socketShutdownError): + writeInt(&buf, Int32(2)) + FfiConverterTypeSocketShutdownError.write(socketShutdownError, into: &buf) + + case .Timeout: + writeInt(&buf, Int32(3)) + + case let .WebSocket(webSocketError): + writeInt(&buf, Int32(4)) + FfiConverterTypeWebSocketError.write(webSocketError, into: &buf) + + case .SocketDisconnected: + writeInt(&buf, Int32(5)) + + case let .Reply(reply): + writeInt(&buf, Int32(6)) + FfiConverterTypePayload.write(reply, into: &buf) + } + } +} + +extension CallError: Equatable, Hashable {} + +extension CallError: Foundation.LocalizedError { + public var errorDescription: String? { + String(reflecting: self) + } +} + +/** + * [tungstenite::error::CapacityError], but with `uniffi` support. + * Indicates the specific type/cause of a capacity error. + */ +public enum CapacityError { + /** + * Too many headers provided (see [`httparse::Error::TooManyHeaders`]). + */ + case TooManyHeaders + /** + * Received header is too long. + * Message is bigger than the maximum allowed size. + */ + case MessageTooLong( + /** + * The size of the message. + */ size: UInt64, + /** + * The maximum allowed message size. + */ maxSize: UInt64 + ) +} + +public struct FfiConverterTypeCapacityError: FfiConverterRustBuffer { + typealias SwiftType = CapacityError + + public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> CapacityError { + let variant: Int32 = try readInt(&buf) + switch variant { + case 1: return .TooManyHeaders + + case 2: return try .MessageTooLong( + size: FfiConverterUInt64.read(from: &buf), + maxSize: FfiConverterUInt64.read(from: &buf) + ) + + default: throw UniffiInternalError.unexpectedEnumCase + } + } + + public static func write(_ value: CapacityError, into buf: inout [UInt8]) { + switch value { + case .TooManyHeaders: + writeInt(&buf, Int32(1)) + + case let .MessageTooLong(size, maxSize): + writeInt(&buf, Int32(2)) + FfiConverterUInt64.write(size, into: &buf) + FfiConverterUInt64.write(maxSize, into: &buf) + } + } +} + +extension CapacityError: Equatable, Hashable {} + +extension CapacityError: Foundation.LocalizedError { + public var errorDescription: String? { + String(reflecting: self) + } +} + +/** + * Errors when calling [Channel::cast]. + */ +public enum CastError { + /** + * The async task for the [Channel] was already joined by another call, so the [Result] or + * panic from the async task can't be reported here. + */ + case Shutdown + /** + * The async task for the [Socket] was already joined by another call, so the [Result] or panic + * from the async task can't be reported here. + */ + case SocketShutdown + /** + * [tokio_tungstenite::tungstenite::error::UrlError] with the `url` passed to [Socket::spawn]. This can include + * incorrect scheme ([tokio_tungstenite::tungstenite::error::UrlError::UnsupportedUrlScheme]). + */ + case Url(urlError: String + ) + /** + * HTTP error response from server. + */ + case Http(response: Response + ) + /** + * HTTP format error. + */ + case HttpFormat(error: HttpError + ) +} + +public struct FfiConverterTypeCastError: FfiConverterRustBuffer { + typealias SwiftType = CastError + + public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> CastError { + let variant: Int32 = try readInt(&buf) + switch variant { + case 1: return .Shutdown + case 2: return .SocketShutdown + case 3: return try .Url( + urlError: FfiConverterString.read(from: &buf) + ) + case 4: return try .Http( + response: FfiConverterTypeResponse.read(from: &buf) + ) + case 5: return try .HttpFormat( + error: FfiConverterTypeHttpError.read(from: &buf) + ) + default: throw UniffiInternalError.unexpectedEnumCase + } + } + + public static func write(_ value: CastError, into buf: inout [UInt8]) { + switch value { + case .Shutdown: + writeInt(&buf, Int32(1)) + + case .SocketShutdown: + writeInt(&buf, Int32(2)) + + case let .Url(urlError): + writeInt(&buf, Int32(3)) + FfiConverterString.write(urlError, into: &buf) + + case let .Http(response): + writeInt(&buf, Int32(4)) + FfiConverterTypeResponse.write(response, into: &buf) + + case let .HttpFormat(error): + writeInt(&buf, Int32(5)) + FfiConverterTypeHttpError.write(error, into: &buf) + } + } +} + +extension CastError: Equatable, Hashable {} + +extension CastError: Foundation.LocalizedError { + public var errorDescription: String? { + String(reflecting: self) + } +} + +/** + * Errors returned by [Channel] functions. + */ +public enum ChannelError { + /** + * Errors when calling [Channel::join]. + */ + case Join( + /** + * Errors when calling [Channel::join]. + */ join: ChannelJoinError + ) + /** + * Errors when calling [Channel::cast]. + */ + case Cast( + /** + * Errors when calling [Channel::cast]. + */ cast: CastError + ) + /** + * Errors when calling [Channel::call]. + */ + case Call( + /** + * Errors when calling [Channel::call]. + */ call: CallError + ) + /** + * Errors when calling [Channel::leave]. + */ + case Leave( + /** + * Errors when calling [Channel::leave]. + */ leave: LeaveError + ) + /** + * Errors when calling [Channel::shutdown]. + */ + case Shutdown( + /** + * Errors when calling [Channel::shutdown]. + */ shutdown: ChannelShutdownError + ) +} + +public struct FfiConverterTypeChannelError: FfiConverterRustBuffer { + typealias SwiftType = ChannelError + + public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> ChannelError { + let variant: Int32 = try readInt(&buf) + switch variant { + case 1: return try .Join( + join: FfiConverterTypeChannelJoinError.read(from: &buf) + ) + case 2: return try .Cast( + cast: FfiConverterTypeCastError.read(from: &buf) + ) + case 3: return try .Call( + call: FfiConverterTypeCallError.read(from: &buf) + ) + case 4: return try .Leave( + leave: FfiConverterTypeLeaveError.read(from: &buf) + ) + case 5: return try .Shutdown( + shutdown: FfiConverterTypeChannelShutdownError.read(from: &buf) + ) + default: throw UniffiInternalError.unexpectedEnumCase + } + } + + public static func write(_ value: ChannelError, into buf: inout [UInt8]) { + switch value { + case let .Join(join): + writeInt(&buf, Int32(1)) + FfiConverterTypeChannelJoinError.write(join, into: &buf) + + case let .Cast(cast): + writeInt(&buf, Int32(2)) + FfiConverterTypeCastError.write(cast, into: &buf) + + case let .Call(call): + writeInt(&buf, Int32(3)) + FfiConverterTypeCallError.write(call, into: &buf) + + case let .Leave(leave): + writeInt(&buf, Int32(4)) + FfiConverterTypeLeaveError.write(leave, into: &buf) + + case let .Shutdown(shutdown): + writeInt(&buf, Int32(5)) + FfiConverterTypeChannelShutdownError.write(shutdown, into: &buf) + } + } +} + +extension ChannelError: Equatable, Hashable {} + +extension ChannelError: Foundation.LocalizedError { + public var errorDescription: String? { + String(reflecting: self) + } +} + +/** + * Errors when calling [Channel::join]. + */ +public enum ChannelJoinError { + /** + * Timeout joining channel + */ + case Timeout + /** + * [Channel] shutting down because [Channel::shutdown] was called. + */ + case ShuttingDown + /** + * The async task was already joined by another call, so the [Result] or panic from the async + * task can't be reported here. + */ + case Shutdown + /** + * The [Socket](crate::Socket) the channel is on shutdown + */ + case SocketShutdown( + /** + * The error that shutdown the [Socket](crate::Socket) + */ socketShutdownError: SocketShutdownError + ) + /** + * The [Socket](crate::Socket) was disconnected after [Channel::join] was called while waiting + * for a response from the server. + */ + case SocketDisconnected + /** + * [Channel::leave] was called while awaiting a response from the server to a previous + * [Channel::join] + */ + case LeavingWhileJoining + /** + * The [Channel] is currently waiting `until` [SystemTime] to rejoin to not overload the + * server, so can't honor the explicit [Channel::join]. + */ + case WaitingToRejoin( + /** + * When the [Channel] will rejoin. + */ until: Date + ) + /** + * The [Channel::payload] was rejected when attempting to [Channel::join] or automatically + * rejoin [Channel::topic]. + */ + case Rejected( + /** + * Rejection server sent when attempting to join the [Channel]. + */ rejection: Payload + ) +} + +public struct FfiConverterTypeChannelJoinError: FfiConverterRustBuffer { + typealias SwiftType = ChannelJoinError + + public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> ChannelJoinError { + let variant: Int32 = try readInt(&buf) + switch variant { + case 1: return .Timeout + case 2: return .ShuttingDown + case 3: return .Shutdown + case 4: return try .SocketShutdown( + socketShutdownError: FfiConverterTypeSocketShutdownError.read(from: &buf) + ) + case 5: return .SocketDisconnected + case 6: return .LeavingWhileJoining + case 7: return try .WaitingToRejoin( + until: FfiConverterTimestamp.read(from: &buf) + ) + case 8: return try .Rejected( + rejection: FfiConverterTypePayload.read(from: &buf) + ) + default: throw UniffiInternalError.unexpectedEnumCase + } + } + + public static func write(_ value: ChannelJoinError, into buf: inout [UInt8]) { + switch value { + case .Timeout: + writeInt(&buf, Int32(1)) + + case .ShuttingDown: + writeInt(&buf, Int32(2)) + + case .Shutdown: + writeInt(&buf, Int32(3)) + + case let .SocketShutdown(socketShutdownError): + writeInt(&buf, Int32(4)) + FfiConverterTypeSocketShutdownError.write(socketShutdownError, into: &buf) + + case .SocketDisconnected: + writeInt(&buf, Int32(5)) + + case .LeavingWhileJoining: + writeInt(&buf, Int32(6)) + + case let .WaitingToRejoin(until): + writeInt(&buf, Int32(7)) + FfiConverterTimestamp.write(until, into: &buf) + + case let .Rejected(rejection): + writeInt(&buf, Int32(8)) + FfiConverterTypePayload.write(rejection, into: &buf) + } + } +} + +extension ChannelJoinError: Equatable, Hashable {} + +extension ChannelJoinError: Foundation.LocalizedError { + public var errorDescription: String? { + String(reflecting: self) + } +} + +public enum ChannelShutdownError { + case SocketShutdown + case AlreadyJoined +} + +public struct FfiConverterTypeChannelShutdownError: FfiConverterRustBuffer { + typealias SwiftType = ChannelShutdownError + + public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> ChannelShutdownError { + let variant: Int32 = try readInt(&buf) + switch variant { + case 1: return .SocketShutdown + + case 2: return .AlreadyJoined + + default: throw UniffiInternalError.unexpectedEnumCase + } + } + + public static func write(_ value: ChannelShutdownError, into buf: inout [UInt8]) { + switch value { + case .SocketShutdown: + writeInt(&buf, Int32(1)) + + case .AlreadyJoined: + writeInt(&buf, Int32(2)) + } + } +} + +extension ChannelShutdownError: Equatable, Hashable {} + +extension ChannelShutdownError: Foundation.LocalizedError { + public var errorDescription: String? { + String(reflecting: self) + } +} + +// Note that we don't yet support `indirect` for enums. +// See https://github.com/mozilla/uniffi-rs/issues/396 for further discussion. +/** + * The status of the [Channel]. + */ + +public enum ChannelStatus { + /** + * [Channel] is waiting for the [Socket](crate::Socket) to + * [Socket::connect](crate::Socket::connect) or automatically reconnect. + */ + case waitingForSocketToConnect + /** + * [Socket::status](crate::Socket::status) is + * [SocketStatus::Connected](crate::SocketStatus::Connected) and [Channel] is waiting for + * [Channel::join] to be called. + */ + case waitingToJoin + /** + * [Channel::join] was called and awaiting response from server. + */ + case joining + /** + * [Channel::join] was called previously, but the [Socket](crate::Socket) was disconnected and + * reconnected. + */ + case waitingToRejoin( + /** + * When the [Channel] will automatically [Channel::join]. + */ until: Date + ) + /** + * [Channel::join] was called and the server responded that the [Channel::topic] was joined + * using [Channel::payload]. + */ + case joined + /** + * [Channel::leave] was called and awaiting response from server. + */ + case leaving + /** + * [Channel::leave] was called and the server responded that the [Channel::topic] was left. + */ + case left + /** + * [Channel::shutdown] was called, but the async task hasn't exited yet. + */ + case shuttingDown + /** + * The async task has exited. + */ + case shutDown +} + +public struct FfiConverterTypeChannelStatus: FfiConverterRustBuffer { + typealias SwiftType = ChannelStatus + + public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> ChannelStatus { + let variant: Int32 = try readInt(&buf) + switch variant { + case 1: return .waitingForSocketToConnect + + case 2: return .waitingToJoin + + case 3: return .joining + + case 4: return try .waitingToRejoin(until: FfiConverterTimestamp.read(from: &buf) + ) + + case 5: return .joined + + case 6: return .leaving + + case 7: return .left + + case 8: return .shuttingDown + + case 9: return .shutDown + + default: throw UniffiInternalError.unexpectedEnumCase + } + } + + public static func write(_ value: ChannelStatus, into buf: inout [UInt8]) { + switch value { + case .waitingForSocketToConnect: + writeInt(&buf, Int32(1)) + + case .waitingToJoin: + writeInt(&buf, Int32(2)) + + case .joining: + writeInt(&buf, Int32(3)) + + case let .waitingToRejoin(until): + writeInt(&buf, Int32(4)) + FfiConverterTimestamp.write(until, into: &buf) + + case .joined: + writeInt(&buf, Int32(5)) + + case .leaving: + writeInt(&buf, Int32(6)) + + case .left: + writeInt(&buf, Int32(7)) + + case .shuttingDown: + writeInt(&buf, Int32(8)) + + case .shutDown: + writeInt(&buf, Int32(9)) + } + } +} + +public func FfiConverterTypeChannelStatus_lift(_ buf: RustBuffer) throws -> ChannelStatus { + return try FfiConverterTypeChannelStatus.lift(buf) +} + +public func FfiConverterTypeChannelStatus_lower(_ value: ChannelStatus) -> RustBuffer { + return FfiConverterTypeChannelStatus.lower(value) +} + +extension ChannelStatus: Equatable, Hashable {} + +/** + * Errors when calling [Channel::join](super::Channel::join). + */ +public enum ChannelStatusJoinError { + /** + * The [Channel::payload](super::Channel::payload) was rejected when attempting to + * [Channel::join](super::Channel::join) or automatically rejoin + * [Channel::topic](super::Channel::topic). + */ + case Rejected( + /** + * Error response from the serrve. + */ response: Payload + ) +} + +public struct FfiConverterTypeChannelStatusJoinError: FfiConverterRustBuffer { + typealias SwiftType = ChannelStatusJoinError + + public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> ChannelStatusJoinError { + let variant: Int32 = try readInt(&buf) + switch variant { + case 1: return try .Rejected( + response: FfiConverterTypePayload.read(from: &buf) + ) + + default: throw UniffiInternalError.unexpectedEnumCase + } + } + + public static func write(_ value: ChannelStatusJoinError, into buf: inout [UInt8]) { + switch value { + case let .Rejected(response): + writeInt(&buf, Int32(1)) + FfiConverterTypePayload.write(response, into: &buf) + } + } +} + +extension ChannelStatusJoinError: Equatable, Hashable {} + +extension ChannelStatusJoinError: Foundation.LocalizedError { + public var errorDescription: String? { + String(reflecting: self) + } +} + +/** + * Errors from [Socket::connect]. + */ +public enum ConnectError { + /** + * Server did not respond before timeout passed to [Socket::connect] expired. + */ + case Timeout(message: String) + + /** + * Error from the underlying + * [tokio_tungstenite::tungstenite::protocol::WebSocket]. + */ + case WebSocket(message: String) + + /** + * [Socket] shutting down because [Socket::shutdown] was called. + */ + case ShuttingDown(message: String) + + /** + * Error from [Socket::shutdown] or from the server itself that caused the [Socket] to shutdown. + */ + case Shutdown(message: String) + + /** + * The [Socket] is currently waiting until [Instant] to reconnect to not overload the server, + * so can't honor the explicit [Socket::connect]. + */ + case WaitingToReconnect(message: String) + + /** + * These are TLS errors. + */ + case Tls(message: String) +} + +public struct FfiConverterTypeConnectError: FfiConverterRustBuffer { + typealias SwiftType = ConnectError + + public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> ConnectError { + let variant: Int32 = try readInt(&buf) + switch variant { + case 1: return try .Timeout( + message: FfiConverterString.read(from: &buf) + ) + + case 2: return try .WebSocket( + message: FfiConverterString.read(from: &buf) + ) + + case 3: return try .ShuttingDown( + message: FfiConverterString.read(from: &buf) + ) + + case 4: return try .Shutdown( + message: FfiConverterString.read(from: &buf) + ) + + case 5: return try .WaitingToReconnect( + message: FfiConverterString.read(from: &buf) + ) + + case 6: return try .Tls( + message: FfiConverterString.read(from: &buf) + ) + + default: throw UniffiInternalError.unexpectedEnumCase + } + } + + public static func write(_ value: ConnectError, into buf: inout [UInt8]) { + switch value { + case .Timeout(_ /* message is ignored*/ ): + writeInt(&buf, Int32(1)) + case .WebSocket(_ /* message is ignored*/ ): + writeInt(&buf, Int32(2)) + case .ShuttingDown(_ /* message is ignored*/ ): + writeInt(&buf, Int32(3)) + case .Shutdown(_ /* message is ignored*/ ): + writeInt(&buf, Int32(4)) + case .WaitingToReconnect(_ /* message is ignored*/ ): + writeInt(&buf, Int32(5)) + case .Tls(_ /* message is ignored*/ ): + writeInt(&buf, Int32(6)) + } + } +} + +extension ConnectError: Equatable, Hashable {} + +extension ConnectError: Foundation.LocalizedError { + public var errorDescription: String? { + String(reflecting: self) + } +} + +/** + * Error when calling [Socket::disconnect] + */ +public enum DisconnectError { + case Shutdown(shutdownError: SocketShutdownError + ) +} + +public struct FfiConverterTypeDisconnectError: FfiConverterRustBuffer { + typealias SwiftType = DisconnectError + + public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> DisconnectError { + let variant: Int32 = try readInt(&buf) + switch variant { + case 1: return try .Shutdown( + shutdownError: FfiConverterTypeSocketShutdownError.read(from: &buf) + ) + + default: throw UniffiInternalError.unexpectedEnumCase + } + } + + public static func write(_ value: DisconnectError, into buf: inout [UInt8]) { + switch value { + case let .Shutdown(shutdownError): + writeInt(&buf, Int32(1)) + FfiConverterTypeSocketShutdownError.write(shutdownError, into: &buf) + } + } +} + +extension DisconnectError: Equatable, Hashable {} + +extension DisconnectError: Foundation.LocalizedError { + public var errorDescription: String? { + String(reflecting: self) + } +} + +// Note that we don't yet support `indirect` for enums. +// See https://github.com/mozilla/uniffi-rs/issues/396 for further discussion. +/** + * This is a strongly typed wrapper around the event associated with a `Message`. + * + * We discriminate between special Phoenix events and user-defined events, as they have slightly + * different semantics. Generally speaking, Phoenix events are not exposed to users, and are not + * permitted to be sent by them either. + */ + +public enum Event { + /** + * Represents one of the built-in Phoenix channel events, e.g. join + */ + case phoenix( + /** + * The built-in event name + */ phoenix: PhoenixEvent + ) + /** + * Represents a user-defined event + */ + case user( + /** + * The user-defined event name + */ user: String + ) +} + +public struct FfiConverterTypeEvent: FfiConverterRustBuffer { + typealias SwiftType = Event + + public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> Event { + let variant: Int32 = try readInt(&buf) + switch variant { + case 1: return try .phoenix(phoenix: FfiConverterTypePhoenixEvent.read(from: &buf) + ) + + case 2: return try .user(user: FfiConverterString.read(from: &buf) + ) + + default: throw UniffiInternalError.unexpectedEnumCase + } + } + + public static func write(_ value: Event, into buf: inout [UInt8]) { + switch value { + case let .phoenix(phoenix): + writeInt(&buf, Int32(1)) + FfiConverterTypePhoenixEvent.write(phoenix, into: &buf) + + case let .user(user): + writeInt(&buf, Int32(2)) + FfiConverterString.write(user, into: &buf) + } + } +} + +public func FfiConverterTypeEvent_lift(_ buf: RustBuffer) throws -> Event { + return try FfiConverterTypeEvent.lift(buf) +} + +public func FfiConverterTypeEvent_lower(_ value: Event) -> RustBuffer { + return FfiConverterTypeEvent.lower(value) +} + +extension Event: Equatable, Hashable {} + +/** + * Errors when calling [Events::event]. + */ +public enum EventsError { + /** + * There are no more events because the [Channel] shutdown. + */ + case NoMoreEvents + /** + * [Events::event] wasn't called often enough and some [EventPayload] won't be sent to not + * block the other receivers or the sender. Call [Events::event] to catch up and get the next + * [EventPayload]. + */ + case MissedEvents( + /** + * How many [EventPayload] were missed. + */ missedEventCount: UInt64 + ) +} + +public struct FfiConverterTypeEventsError: FfiConverterRustBuffer { + typealias SwiftType = EventsError + + public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> EventsError { + let variant: Int32 = try readInt(&buf) + switch variant { + case 1: return .NoMoreEvents + + case 2: return try .MissedEvents( + missedEventCount: FfiConverterUInt64.read(from: &buf) + ) + + default: throw UniffiInternalError.unexpectedEnumCase + } + } + + public static func write(_ value: EventsError, into buf: inout [UInt8]) { + switch value { + case .NoMoreEvents: + writeInt(&buf, Int32(1)) + + case let .MissedEvents(missedEventCount): + writeInt(&buf, Int32(2)) + FfiConverterUInt64.write(missedEventCount, into: &buf) + } + } +} + +extension EventsError: Equatable, Hashable {} + +extension EventsError: Foundation.LocalizedError { + public var errorDescription: String? { + String(reflecting: self) + } +} + +/** + * [httparse::Error], but with `uniffi` support + * An error in parsing. + */ +public enum HttParseError { + /** + * Invalid byte in header name. + */ + case HeaderName + /** + * Invalid byte in header value. + */ + case HeaderValue + /** + * Invalid byte in new line. + */ + case NewLine + /** + * Invalid byte in Response status. + */ + case Status + /** + * Invalid byte where token is required. + */ + case Token + /** + * Parsed more headers than provided buffer can contain. + */ + case TooManyHeaders + /** + * Invalid byte in HTTP version. + */ + case Version +} + +public struct FfiConverterTypeHTTParseError: FfiConverterRustBuffer { + typealias SwiftType = HttParseError + + public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> HttParseError { + let variant: Int32 = try readInt(&buf) + switch variant { + case 1: return .HeaderName + case 2: return .HeaderValue + case 3: return .NewLine + case 4: return .Status + case 5: return .Token + case 6: return .TooManyHeaders + case 7: return .Version + default: throw UniffiInternalError.unexpectedEnumCase + } + } + + public static func write(_ value: HttParseError, into buf: inout [UInt8]) { + switch value { + case .HeaderName: + writeInt(&buf, Int32(1)) + + case .HeaderValue: + writeInt(&buf, Int32(2)) + + case .NewLine: + writeInt(&buf, Int32(3)) + + case .Status: + writeInt(&buf, Int32(4)) + + case .Token: + writeInt(&buf, Int32(5)) + + case .TooManyHeaders: + writeInt(&buf, Int32(6)) + + case .Version: + writeInt(&buf, Int32(7)) + } + } +} + +extension HttParseError: Equatable, Hashable {} + +extension HttParseError: Foundation.LocalizedError { + public var errorDescription: String? { + String(reflecting: self) + } +} + +/** + * [http::error::Error], but with `uniffi` support + */ +public enum HttpError { + case StatusCode + case Method + case Uri(invalidUri: String + ) + case UriParts(invalidUri: String + ) + case HeaderName + case HeaderValue +} + +public struct FfiConverterTypeHttpError: FfiConverterRustBuffer { + typealias SwiftType = HttpError + + public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> HttpError { + let variant: Int32 = try readInt(&buf) + switch variant { + case 1: return .StatusCode + case 2: return .Method + case 3: return try .Uri( + invalidUri: FfiConverterString.read(from: &buf) + ) + case 4: return try .UriParts( + invalidUri: FfiConverterString.read(from: &buf) + ) + case 5: return .HeaderName + case 6: return .HeaderValue + default: throw UniffiInternalError.unexpectedEnumCase + } + } + + public static func write(_ value: HttpError, into buf: inout [UInt8]) { + switch value { + case .StatusCode: + writeInt(&buf, Int32(1)) + + case .Method: + writeInt(&buf, Int32(2)) + + case let .Uri(invalidUri): + writeInt(&buf, Int32(3)) + FfiConverterString.write(invalidUri, into: &buf) + + case let .UriParts(invalidUri): + writeInt(&buf, Int32(4)) + FfiConverterString.write(invalidUri, into: &buf) + + case .HeaderName: + writeInt(&buf, Int32(5)) + + case .HeaderValue: + writeInt(&buf, Int32(6)) + } + } +} + +extension HttpError: Equatable, Hashable {} + +extension HttpError: Foundation.LocalizedError { + public var errorDescription: String? { + String(reflecting: self) + } +} + +public enum InvalidUri { + case InvalidChar + case InvalidScheme + case InvalidAuthority + case InvalidPort + case InvalidFormat + case SchemeMissing + case AuthorityMissing + case PathAndQueryMissing + case TooLong + case Empty + case SchemeTooLong +} + +public struct FfiConverterTypeInvalidUri: FfiConverterRustBuffer { + typealias SwiftType = InvalidUri + + public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> InvalidUri { + let variant: Int32 = try readInt(&buf) + switch variant { + case 1: return .InvalidChar + case 2: return .InvalidScheme + case 3: return .InvalidAuthority + case 4: return .InvalidPort + case 5: return .InvalidFormat + case 6: return .SchemeMissing + case 7: return .AuthorityMissing + case 8: return .PathAndQueryMissing + case 9: return .TooLong + case 10: return .Empty + case 11: return .SchemeTooLong + default: throw UniffiInternalError.unexpectedEnumCase + } + } + + public static func write(_ value: InvalidUri, into buf: inout [UInt8]) { + switch value { + case .InvalidChar: + writeInt(&buf, Int32(1)) + + case .InvalidScheme: + writeInt(&buf, Int32(2)) + + case .InvalidAuthority: + writeInt(&buf, Int32(3)) + + case .InvalidPort: + writeInt(&buf, Int32(4)) + + case .InvalidFormat: + writeInt(&buf, Int32(5)) + + case .SchemeMissing: + writeInt(&buf, Int32(6)) + + case .AuthorityMissing: + writeInt(&buf, Int32(7)) + + case .PathAndQueryMissing: + writeInt(&buf, Int32(8)) + + case .TooLong: + writeInt(&buf, Int32(9)) + + case .Empty: + writeInt(&buf, Int32(10)) + + case .SchemeTooLong: + writeInt(&buf, Int32(11)) + } + } +} + +extension InvalidUri: Equatable, Hashable {} + +extension InvalidUri: Foundation.LocalizedError { + public var errorDescription: String? { + String(reflecting: self) + } +} + +/** + * [std::io::Error] and [std::io::ErrorKind], but with `uniffi` support. + */ +public enum IoError { + /** + * An entity was not found. + */ + case NotFound + /** + * Permission Denied for this operation. + */ + case PermissionDenied + /** + * The connection was refused. + */ + case ConnectionRefused + /** + * The connection was reset by server. + */ + case ConnectionReset + /** + * The host is not reachable. + */ + case HostUnreachable + /** + * The network for the host is not reachable. + */ + case NetworkUnreachable + /** + * The connection was aborted by the remote server. + */ + case ConnectionAborted + /** + * The network operation failed because it is not connected yet. + */ + case NotConnected + /** + * A socket address is already in use elsewhere. + */ + case AddrInUse + /** + * A nonexistent interface was requested or the requested address was not + * local. + */ + case AddrNotAvailable + /** + * The system's networking is down. + */ + case NetworkDown + /** + * The operation failed because a pipe was closed. + */ + case BrokenPipe + /** + * An entity already exists. + */ + case AlreadyExists + /** + * The operation needs to block to complete, but the blocking operation was + * requested to not occur. + */ + case WouldBlock + /** + * A filesystem object is, unexpectedly, not a directory. + */ + case NotADirectory + /** + * The filesystem object is, unexpectedly, a directory. + */ + case IsADirectory + /** + * A non-empty directory was specified when a empty directory was expected. + */ + case DirectoryNotEmpty + /** + * The filesystem is read-only when a write operation was attempted. + */ + case ReadOnlyFilesystem + /** + * Loop in the filesystem or IO subsystem; often, too many levels of symbolic links. + * + * There was a loop (or excessively long chain) resolving a filesystem object + * or file IO object. + */ + case FilesystemLoop + /** + * Stale network file handle. + */ + case StaleNetworkFileHandle + /** + * A parameter was incorrect. + */ + case InvalidInput + /** + * Data not valid for the operation were encountered. + + */ + case InvalidData + /** + * The I/O operation's timeout expired. + */ + case TimedOut + /** + * An error returned when an operation could not be completed because a + * call to [`write`] returned [`Ok(0)`]. + + */ + case WriteZero + /** + * The underlying storage is full. + */ + case StorageFull + /** + * Seek on unseekable file. + */ + case NotSeekable + /** + * Filesystem quota was exceeded. + */ + case FilesystemQuotaExceeded + /** + * File larger than allowed or supported. + */ + case FileTooLarge + /** + * Resource is busy. + */ + case ResourceBusy + /** + * Executable file is busy. + */ + case ExecutableFileBusy + /** + * Deadlock (avoided). + */ + case Deadlock + /** + * Cross-device or cross-filesystem (hard) link or rename. + */ + case CrossesDevices + /** + * Too many (hard) links to the same filesystem object. + * + * The filesystem does not support making so many hardlinks to the same file. + */ + case TooManyLinks + /** + * A filename was invalid. + * + * This error can also cause if it exceeded the filename length limit. + */ + case InvalidFilename + /** + * Program argument list too long. + * + * When trying to run an external program, a system or process limit on the size of the + * arguments would have been exceeded. + */ + case ArgumentListTooLong + /** + * This operation was interrupted. + * + * Interrupted operations can typically be retried. + */ + case Interrupted + /** + * This operation is unsupported on this platform. + * + * This means that the operation can never succeed. + */ + case Unsupported + /** + * An error returned when an operation could not be completed because an + * "end of file" was reached prematurely. + * + * This typically means that an operation could only succeed if it read a + * particular number of bytes but only a smaller number of bytes could be + * read. + */ + case UnexpectedEof + /** + * An operation could not be completed, because it failed + * to allocate enough memory. + */ + case OutOfMemory + /** + * A custom error that does not fall under any other I/O error kind. + * + * This can be used to construct your own [`IoError`]s that do not match any + * [`ErrorKind`]. + * + * This [`ErrorKind`] is not used by the standard library. + * + * Errors from the standard library that do not fall under any of the I/O + * error kinds cannot be `match`ed on, and will only match a wildcard (`_`) pattern. + * New [`ErrorKind`]s might be added in the future for some of those. + */ + case Other + /** + * Any I/O error from the standard library that's not part of this list. + * + * Errors that are `Uncategorized` now may move to a different or a new + * [`ErrorKind`] variant in the future. It is not recommended to match + * an error against `Uncategorized`; use a wildcard match (`_`) instead. + */ + case Uncategorized +} + +public struct FfiConverterTypeIoError: FfiConverterRustBuffer { + typealias SwiftType = IoError + + public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> IoError { + let variant: Int32 = try readInt(&buf) + switch variant { + case 1: return .NotFound + case 2: return .PermissionDenied + case 3: return .ConnectionRefused + case 4: return .ConnectionReset + case 5: return .HostUnreachable + case 6: return .NetworkUnreachable + case 7: return .ConnectionAborted + case 8: return .NotConnected + case 9: return .AddrInUse + case 10: return .AddrNotAvailable + case 11: return .NetworkDown + case 12: return .BrokenPipe + case 13: return .AlreadyExists + case 14: return .WouldBlock + case 15: return .NotADirectory + case 16: return .IsADirectory + case 17: return .DirectoryNotEmpty + case 18: return .ReadOnlyFilesystem + case 19: return .FilesystemLoop + case 20: return .StaleNetworkFileHandle + case 21: return .InvalidInput + case 22: return .InvalidData + case 23: return .TimedOut + case 24: return .WriteZero + case 25: return .StorageFull + case 26: return .NotSeekable + case 27: return .FilesystemQuotaExceeded + case 28: return .FileTooLarge + case 29: return .ResourceBusy + case 30: return .ExecutableFileBusy + case 31: return .Deadlock + case 32: return .CrossesDevices + case 33: return .TooManyLinks + case 34: return .InvalidFilename + case 35: return .ArgumentListTooLong + case 36: return .Interrupted + case 37: return .Unsupported + case 38: return .UnexpectedEof + case 39: return .OutOfMemory + case 40: return .Other + case 41: return .Uncategorized + default: throw UniffiInternalError.unexpectedEnumCase + } + } + + public static func write(_ value: IoError, into buf: inout [UInt8]) { + switch value { + case .NotFound: + writeInt(&buf, Int32(1)) + + case .PermissionDenied: + writeInt(&buf, Int32(2)) + + case .ConnectionRefused: + writeInt(&buf, Int32(3)) + + case .ConnectionReset: + writeInt(&buf, Int32(4)) + + case .HostUnreachable: + writeInt(&buf, Int32(5)) + + case .NetworkUnreachable: + writeInt(&buf, Int32(6)) + + case .ConnectionAborted: + writeInt(&buf, Int32(7)) + + case .NotConnected: + writeInt(&buf, Int32(8)) + + case .AddrInUse: + writeInt(&buf, Int32(9)) + + case .AddrNotAvailable: + writeInt(&buf, Int32(10)) + + case .NetworkDown: + writeInt(&buf, Int32(11)) + + case .BrokenPipe: + writeInt(&buf, Int32(12)) + + case .AlreadyExists: + writeInt(&buf, Int32(13)) + + case .WouldBlock: + writeInt(&buf, Int32(14)) + + case .NotADirectory: + writeInt(&buf, Int32(15)) + + case .IsADirectory: + writeInt(&buf, Int32(16)) + + case .DirectoryNotEmpty: + writeInt(&buf, Int32(17)) + + case .ReadOnlyFilesystem: + writeInt(&buf, Int32(18)) + + case .FilesystemLoop: + writeInt(&buf, Int32(19)) + + case .StaleNetworkFileHandle: + writeInt(&buf, Int32(20)) + + case .InvalidInput: + writeInt(&buf, Int32(21)) + + case .InvalidData: + writeInt(&buf, Int32(22)) + + case .TimedOut: + writeInt(&buf, Int32(23)) + + case .WriteZero: + writeInt(&buf, Int32(24)) + + case .StorageFull: + writeInt(&buf, Int32(25)) + + case .NotSeekable: + writeInt(&buf, Int32(26)) + + case .FilesystemQuotaExceeded: + writeInt(&buf, Int32(27)) + + case .FileTooLarge: + writeInt(&buf, Int32(28)) + + case .ResourceBusy: + writeInt(&buf, Int32(29)) + + case .ExecutableFileBusy: + writeInt(&buf, Int32(30)) + + case .Deadlock: + writeInt(&buf, Int32(31)) + + case .CrossesDevices: + writeInt(&buf, Int32(32)) + + case .TooManyLinks: + writeInt(&buf, Int32(33)) + + case .InvalidFilename: + writeInt(&buf, Int32(34)) + + case .ArgumentListTooLong: + writeInt(&buf, Int32(35)) + + case .Interrupted: + writeInt(&buf, Int32(36)) + + case .Unsupported: + writeInt(&buf, Int32(37)) + + case .UnexpectedEof: + writeInt(&buf, Int32(38)) + + case .OutOfMemory: + writeInt(&buf, Int32(39)) + + case .Other: + writeInt(&buf, Int32(40)) + + case .Uncategorized: + writeInt(&buf, Int32(41)) + } + } +} + +extension IoError: Equatable, Hashable {} + +extension IoError: Foundation.LocalizedError { + public var errorDescription: String? { + String(reflecting: self) + } +} + +// Note that we don't yet support `indirect` for enums. +// See https://github.com/mozilla/uniffi-rs/issues/396 for further discussion. +/** + * Replicates [serde_json::Value], but with `uniffi` support. + */ + +public enum Json { + /** + * JSON `null` + */ + case null + /** + * JSON `true` or `false` + */ + case bool( + /** + * The boolean + */ bool: Bool + ) + /** + * JSON integer or float + */ + case numb( + /** + * The integer or float + */ number: Number + ) + /** + * JSON string + */ + case str( + /** + * The string + */ string: String + ) + /** + * JSON array of JSON + */ + case array( + /** + * The array + */ array: [Json] + ) + /** + * JSON object + */ + case object( + /** + * The object + */ object: [String: Json] + ) +} + +public struct FfiConverterTypeJSON: FfiConverterRustBuffer { + typealias SwiftType = Json + + public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> Json { + let variant: Int32 = try readInt(&buf) + switch variant { + case 1: return .null + + case 2: return try .bool(bool: FfiConverterBool.read(from: &buf) + ) + + case 3: return try .numb(number: FfiConverterTypeNumber.read(from: &buf) + ) + + case 4: return try .str(string: FfiConverterString.read(from: &buf) + ) + + case 5: return try .array(array: FfiConverterSequenceTypeJSON.read(from: &buf) + ) + + case 6: return try .object(object: FfiConverterDictionaryStringTypeJSON.read(from: &buf) + ) + + default: throw UniffiInternalError.unexpectedEnumCase + } + } + + public static func write(_ value: Json, into buf: inout [UInt8]) { + switch value { + case .null: + writeInt(&buf, Int32(1)) + + case let .bool(bool): + writeInt(&buf, Int32(2)) + FfiConverterBool.write(bool, into: &buf) + + case let .numb(number): + writeInt(&buf, Int32(3)) + FfiConverterTypeNumber.write(number, into: &buf) + + case let .str(string): + writeInt(&buf, Int32(4)) + FfiConverterString.write(string, into: &buf) + + case let .array(array): + writeInt(&buf, Int32(5)) + FfiConverterSequenceTypeJSON.write(array, into: &buf) + + case let .object(object): + writeInt(&buf, Int32(6)) + FfiConverterDictionaryStringTypeJSON.write(object, into: &buf) + } + } +} + +public func FfiConverterTypeJSON_lift(_ buf: RustBuffer) throws -> Json { + return try FfiConverterTypeJSON.lift(buf) +} + +public func FfiConverterTypeJSON_lower(_ value: Json) -> RustBuffer { + return FfiConverterTypeJSON.lower(value) +} + +extension Json: Equatable, Hashable {} + +/** + * Error from [JSON::deserialize] + */ +public enum JsonDeserializationError { + /** + * There was error reading from the underlying IO device after reading `column` of `line`. + */ + case Io( + /** + * The line that was being read before the `io_error` occurred. + */ line: UInt64, + /** + * The column on `line` that was being read before the `io_error` occurred. + */ column: UInt64, + /** + * The underlying [IoError] that occurred on `line` at `column`. + */ ioError: IoError + ) + /** + * There was a JSON syntax error at `line` on `column`. + */ + case Syntax( + /** + * The line where the syntax error occurred. + */ line: UInt64, + /** + * The column on `line` where the syntax error occurred. + */ column: UInt64 + ) + /** + * The data such as a string or number could not be converted from JSON at `line` on `column`. + */ + case Data( + /** + * The line where the invalid string or number occurred. + */ line: UInt64, + /** + * The column on `line` where the invalid string or number occurred. + */ column: UInt64 + ) + /** + * The EOF was reached at `line` on `column` while still parsing a JSON structure. + */ + case Eof( + /** + * The last line that was read before the premature End-Of-File. + */ line: UInt64, + /** + * The last column on `line` that was read before the premature End-Of-File. + */ column: UInt64 + ) +} + +public struct FfiConverterTypeJSONDeserializationError: FfiConverterRustBuffer { + typealias SwiftType = JsonDeserializationError + + public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> JsonDeserializationError { + let variant: Int32 = try readInt(&buf) + switch variant { + case 1: return try .Io( + line: FfiConverterUInt64.read(from: &buf), + column: FfiConverterUInt64.read(from: &buf), + ioError: FfiConverterTypeIoError.read(from: &buf) + ) + case 2: return try .Syntax( + line: FfiConverterUInt64.read(from: &buf), + column: FfiConverterUInt64.read(from: &buf) + ) + case 3: return try .Data( + line: FfiConverterUInt64.read(from: &buf), + column: FfiConverterUInt64.read(from: &buf) + ) + case 4: return try .Eof( + line: FfiConverterUInt64.read(from: &buf), + column: FfiConverterUInt64.read(from: &buf) + ) + default: throw UniffiInternalError.unexpectedEnumCase + } + } + + public static func write(_ value: JsonDeserializationError, into buf: inout [UInt8]) { + switch value { + case let .Io(line, column, ioError): + writeInt(&buf, Int32(1)) + FfiConverterUInt64.write(line, into: &buf) + FfiConverterUInt64.write(column, into: &buf) + FfiConverterTypeIoError.write(ioError, into: &buf) + + case let .Syntax(line, column): + writeInt(&buf, Int32(2)) + FfiConverterUInt64.write(line, into: &buf) + FfiConverterUInt64.write(column, into: &buf) + + case let .Data(line, column): + writeInt(&buf, Int32(3)) + FfiConverterUInt64.write(line, into: &buf) + FfiConverterUInt64.write(column, into: &buf) + + case let .Eof(line, column): + writeInt(&buf, Int32(4)) + FfiConverterUInt64.write(line, into: &buf) + FfiConverterUInt64.write(column, into: &buf) + } + } +} + +extension JsonDeserializationError: Equatable, Hashable {} + +extension JsonDeserializationError: Foundation.LocalizedError { + public var errorDescription: String? { + String(reflecting: self) + } +} + +/** + * Errors for when leaving a channel fails. + */ +public enum LeaveError { + /** + * The leave operation timeout. + */ + case Timeout + /** + * The channel was shutting down when the client was leaving the channel. + */ + case ShuttingDown + /** + * The channel was shutting down when the client was leaving the channel. + */ + case Shutdown + /** + * The channel already shut down when the client was leaving the channel. + */ + case SocketShutdown( + /** + * The shut down error + */ socketShutdownError: SocketShutdownError + ) + /** + * There was a websocket error when the client was leaving the channel. + */ + case WebSocket( + /** + * The specific websocket error for this shutdown. + */ webSocketError: WebSocketError + ) + /** + * The server rejected the clients request to leave the channel. + */ + case Rejected( + /** + * Response from the server of why the leave was rejected + */ rejection: Payload + ) + /** + * A join was initiated before the server could respond if leave was successful + */ + case JoinBeforeLeft + /** + * There was a URL error when leaving the channel. + */ + case Url( + /** + * The url error itself. + */ urlError: String + ) + /** + * There was an HTTP error when leaving the cheannel. + */ + case Http( + /** + * The http response for the error. + */ response: Response + ) + /** + * HTTP format error. + */ + case HttpFormat( + /** + * The http error. + */ error: HttpError + ) +} + +public struct FfiConverterTypeLeaveError: FfiConverterRustBuffer { + typealias SwiftType = LeaveError + + public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> LeaveError { + let variant: Int32 = try readInt(&buf) + switch variant { + case 1: return .Timeout + case 2: return .ShuttingDown + case 3: return .Shutdown + case 4: return try .SocketShutdown( + socketShutdownError: FfiConverterTypeSocketShutdownError.read(from: &buf) + ) + case 5: return try .WebSocket( + webSocketError: FfiConverterTypeWebSocketError.read(from: &buf) + ) + case 6: return try .Rejected( + rejection: FfiConverterTypePayload.read(from: &buf) + ) + case 7: return .JoinBeforeLeft + case 8: return try .Url( + urlError: FfiConverterString.read(from: &buf) + ) + case 9: return try .Http( + response: FfiConverterTypeResponse.read(from: &buf) + ) + case 10: return try .HttpFormat( + error: FfiConverterTypeHttpError.read(from: &buf) + ) + default: throw UniffiInternalError.unexpectedEnumCase + } + } + + public static func write(_ value: LeaveError, into buf: inout [UInt8]) { + switch value { + case .Timeout: + writeInt(&buf, Int32(1)) + + case .ShuttingDown: + writeInt(&buf, Int32(2)) + + case .Shutdown: + writeInt(&buf, Int32(3)) + + case let .SocketShutdown(socketShutdownError): + writeInt(&buf, Int32(4)) + FfiConverterTypeSocketShutdownError.write(socketShutdownError, into: &buf) + + case let .WebSocket(webSocketError): + writeInt(&buf, Int32(5)) + FfiConverterTypeWebSocketError.write(webSocketError, into: &buf) + + case let .Rejected(rejection): + writeInt(&buf, Int32(6)) + FfiConverterTypePayload.write(rejection, into: &buf) + + case .JoinBeforeLeft: + writeInt(&buf, Int32(7)) + + case let .Url(urlError): + writeInt(&buf, Int32(8)) + FfiConverterString.write(urlError, into: &buf) + + case let .Http(response): + writeInt(&buf, Int32(9)) + FfiConverterTypeResponse.write(response, into: &buf) + + case let .HttpFormat(error): + writeInt(&buf, Int32(10)) + FfiConverterTypeHttpError.write(error, into: &buf) + } + } +} + +extension LeaveError: Equatable, Hashable {} + +extension LeaveError: Foundation.LocalizedError { + public var errorDescription: String? { + String(reflecting: self) + } +} + +// Note that we don't yet support `indirect` for enums. +// See https://github.com/mozilla/uniffi-rs/issues/396 for further discussion. +/** + * Replicates [serde_json::Number] but with `uniffi` support. + */ + +public enum Number { + /** + * Positive number + */ + case posInt( + /** + * Positive number + */ pos: UInt64 + ) + /** + * Negative number + */ + case negInt( + /** + * Negative number + */ neg: Int64 + ) + /** + * Float + */ + case float( + /** + * Float + */ float: Double + ) +} + +public struct FfiConverterTypeNumber: FfiConverterRustBuffer { + typealias SwiftType = Number + + public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> Number { + let variant: Int32 = try readInt(&buf) + switch variant { + case 1: return try .posInt(pos: FfiConverterUInt64.read(from: &buf) + ) + + case 2: return try .negInt(neg: FfiConverterInt64.read(from: &buf) + ) + + case 3: return try .float(float: FfiConverterDouble.read(from: &buf) + ) + + default: throw UniffiInternalError.unexpectedEnumCase + } + } + + public static func write(_ value: Number, into buf: inout [UInt8]) { + switch value { + case let .posInt(pos): + writeInt(&buf, Int32(1)) + FfiConverterUInt64.write(pos, into: &buf) + + case let .negInt(neg): + writeInt(&buf, Int32(2)) + FfiConverterInt64.write(neg, into: &buf) + + case let .float(float): + writeInt(&buf, Int32(3)) + FfiConverterDouble.write(float, into: &buf) + } + } +} + +public func FfiConverterTypeNumber_lift(_ buf: RustBuffer) throws -> Number { + return try FfiConverterTypeNumber.lift(buf) +} + +public func FfiConverterTypeNumber_lower(_ value: Number) -> RustBuffer { + return FfiConverterTypeNumber.lower(value) +} + +extension Number: Equatable, Hashable {} + +// Note that we don't yet support `indirect` for enums. +// See https://github.com/mozilla/uniffi-rs/issues/396 for further discussion. +/** + * Contains the response payload sent to/received from Phoenix + */ + +public enum Payload { + /** + * A JSON payload + */ + case jsonPayload( + /** + * The JSON payload + */ json: Json + ) + /** + * A binary payload + */ + case binary( + /** + * The bytes of the binary payload. + */ bytes: Data + ) +} + +public struct FfiConverterTypePayload: FfiConverterRustBuffer { + typealias SwiftType = Payload + + public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> Payload { + let variant: Int32 = try readInt(&buf) + switch variant { + case 1: return try .jsonPayload(json: FfiConverterTypeJSON.read(from: &buf) + ) + + case 2: return try .binary(bytes: FfiConverterData.read(from: &buf) + ) + + default: throw UniffiInternalError.unexpectedEnumCase + } + } + + public static func write(_ value: Payload, into buf: inout [UInt8]) { + switch value { + case let .jsonPayload(json): + writeInt(&buf, Int32(1)) + FfiConverterTypeJSON.write(json, into: &buf) + + case let .binary(bytes): + writeInt(&buf, Int32(2)) + FfiConverterData.write(bytes, into: &buf) + } + } +} + +public func FfiConverterTypePayload_lift(_ buf: RustBuffer) throws -> Payload { + return try FfiConverterTypePayload.lift(buf) +} + +public func FfiConverterTypePayload_lower(_ value: Payload) -> RustBuffer { + return FfiConverterTypePayload.lower(value) +} + +extension Payload: Equatable, Hashable {} + +/** + * All errors that can be produced by this library. + */ +public enum PhoenixError { + /** + * Timeout elapsed + */ + case Elapsed + /** + * Error when parsing URL + */ + case UrlParse( + /** + * Error parsing URL + */ urlParse: UrlParseError + ) + /** + * An error from any function on [Socket](crate::Socket). + */ + case Socket( + /** + * Error from any function on [Socket](crate::Socket). + */ socket: SocketError + ) + /** + * An error from any function on [Channel](crate::Channel). + */ + case Channel( + /** + * An error from any function on [Channel](crate::Channel). + */ channel: ChannelError + ) + /** + * An error from calling `status` on [Channel::statuses](crate::Channel::statuses) or + * [Socket::statuses](crate::Socket::statuses). + */ + case Statuses( + /** + * An error from calling `status` on [Channel::statuses](crate::Channel::statuses) or + * [Socket::statuses](crate::Socket::statuses). + */ statuses: StatusesError + ) +} + +public struct FfiConverterTypePhoenixError: FfiConverterRustBuffer { + typealias SwiftType = PhoenixError + + public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> PhoenixError { + let variant: Int32 = try readInt(&buf) + switch variant { + case 1: return .Elapsed + case 2: return try .UrlParse( + urlParse: FfiConverterTypeURLParseError.read(from: &buf) + ) + case 3: return try .Socket( + socket: FfiConverterTypeSocketError.read(from: &buf) + ) + case 4: return try .Channel( + channel: FfiConverterTypeChannelError.read(from: &buf) + ) + case 5: return try .Statuses( + statuses: FfiConverterTypeStatusesError.read(from: &buf) + ) + default: throw UniffiInternalError.unexpectedEnumCase + } + } + + public static func write(_ value: PhoenixError, into buf: inout [UInt8]) { + switch value { + case .Elapsed: + writeInt(&buf, Int32(1)) + + case let .UrlParse(urlParse): + writeInt(&buf, Int32(2)) + FfiConverterTypeURLParseError.write(urlParse, into: &buf) + + case let .Socket(socket): + writeInt(&buf, Int32(3)) + FfiConverterTypeSocketError.write(socket, into: &buf) + + case let .Channel(channel): + writeInt(&buf, Int32(4)) + FfiConverterTypeChannelError.write(channel, into: &buf) + + case let .Statuses(statuses): + writeInt(&buf, Int32(5)) + FfiConverterTypeStatusesError.write(statuses, into: &buf) + } + } +} + +extension PhoenixError: Equatable, Hashable {} + +extension PhoenixError: Foundation.LocalizedError { + public var errorDescription: String? { + String(reflecting: self) + } +} + +// Note that we don't yet support `indirect` for enums. +// See https://github.com/mozilla/uniffi-rs/issues/396 for further discussion. +/** + * Represents special events related to management of Phoenix channels. + */ + +public enum PhoenixEvent { + /** + * Used when sending a message to join a channel + */ + case join + /** + * Used when sending a message to leave a channel + */ + case leave + /** + * Sent/received when a channel is closed + */ + case close + /** + * Sent/received with replies + */ + case reply + /** + * Sent by the server when an error occurs + */ + case error + /** + * Sent/received as a keepalive for the underlying socket + */ + case heartbeat +} + +public struct FfiConverterTypePhoenixEvent: FfiConverterRustBuffer { + typealias SwiftType = PhoenixEvent + + public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> PhoenixEvent { + let variant: Int32 = try readInt(&buf) + switch variant { + case 1: return .join + + case 2: return .leave + + case 3: return .close + + case 4: return .reply + + case 5: return .error + + case 6: return .heartbeat + + default: throw UniffiInternalError.unexpectedEnumCase + } + } + + public static func write(_ value: PhoenixEvent, into buf: inout [UInt8]) { + switch value { + case .join: + writeInt(&buf, Int32(1)) + + case .leave: + writeInt(&buf, Int32(2)) + + case .close: + writeInt(&buf, Int32(3)) + + case .reply: + writeInt(&buf, Int32(4)) + + case .error: + writeInt(&buf, Int32(5)) + + case .heartbeat: + writeInt(&buf, Int32(6)) + } + } +} + +public func FfiConverterTypePhoenixEvent_lift(_ buf: RustBuffer) throws -> PhoenixEvent { + return try FfiConverterTypePhoenixEvent.lift(buf) +} + +public func FfiConverterTypePhoenixEvent_lower(_ value: PhoenixEvent) -> RustBuffer { + return FfiConverterTypePhoenixEvent.lower(value) +} + +extension PhoenixEvent: Equatable, Hashable {} + +/** + * [tokio_tungstenite::tungstenite::error::ProtocolError], but with `uniffi` support. + * Indicates the specific type/cause of a protocol error. + */ +public enum ProtocolError { + /** + * Use of the wrong HTTP method (the WebSocket protocol requires the GET method be used). + */ + case WrongHttpMethod + /** + * Wrong HTTP version used (the WebSocket protocol requires version 1.1 or higher). + */ + case WrongHttpVersion + /** + * Missing `Connection: upgrade` HTTP header. + */ + case MissingConnectionUpgradeHeader + /** + * Missing `Upgrade: websocket` HTTP header. + */ + case MissingUpgradeWebSocketHeader + /** + * Missing `Sec-WebSocket-Version: 13` HTTP header. + */ + case MissingSecWebSocketVersionHeader + /** + * Missing `Sec-WebSocket-Key` HTTP header. + */ + case MissingSecWebSocketKey + /** + * The `Sec-WebSocket-Accept` header is either not present or does not specify the correct key value. + */ + case SecWebSocketAcceptKeyMismatch + /** + * Garbage data encountered after client request. + */ + case JunkAfterRequest + /** + * Custom responses must be unsuccessful. + */ + case CustomResponseSuccessful + /** + * Invalid header is passed. Or the header is missing in the request. Or not present at all. Check the request that you pass. + */ + case InvalidHeader(header: String + ) + /** + * No more data while still performing handshake. + */ + case HandshakeIncomplete + /** + * Wrapper around a [`httparse::Error`] value. + */ + case HttparseError(httparseError: HttParseError + ) + /** + * Not allowed to send after having sent a closing frame. + */ + case SendAfterClosing + /** + * Remote sent data after sending a closing frame. + */ + case ReceivedAfterClosing + /** + * Reserved bits in frame header are non-zero. + */ + case NonZeroReservedBits + /** + * The server must close the connection when an unmasked frame is received. + */ + case UnmaskedFrameFromClient + /** + * The client must close the connection when a masked frame is received. + */ + case MaskedFrameFromServer + /** + * Control frames must not be fragmented. + */ + case FragmentedControlFrame + /** + * Control frames must have a payload of 125 bytes or less. + */ + case ControlFrameTooBig + /** + * Type of control frame not recognised. + */ + case UnknownControlFrameType(controlFrameType: UInt8 + ) + /** + * Type of data frame not recognised. + */ + case UnknownDataFrameType(dataFrameType: UInt8 + ) + /** + * Received a continue frame despite there being nothing to continue. + */ + case UnexpectedContinueFrame + /** + * Received data while waiting for more fragments. + */ + case ExpectedFragment(data: TungsteniteData + ) + /** + * Connection closed without performing the closing handshake. + */ + case ResetWithoutClosingHandshake + /** + * Encountered an invalid opcode. + */ + case InvalidOpcode(opcode: UInt8 + ) + /** + * The payload for the closing frame is invalid. + */ + case InvalidCloseSequence + /** + * The server sent a subprotocol to a client handshake request but none was requested + */ + case ServerSentSubProtocolNoneRequested + /** + * The server sent an invalid subprotocol to a client handhshake request + */ + case InvalidSubProtocol + /** + * The server sent no subprotocol to a client handshake request that requested one or more + * subprotocols + */ + case NoSubProtocol +} + +public struct FfiConverterTypeProtocolError: FfiConverterRustBuffer { + typealias SwiftType = ProtocolError + + public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> ProtocolError { + let variant: Int32 = try readInt(&buf) + switch variant { + case 1: return .WrongHttpMethod + case 2: return .WrongHttpVersion + case 3: return .MissingConnectionUpgradeHeader + case 4: return .MissingUpgradeWebSocketHeader + case 5: return .MissingSecWebSocketVersionHeader + case 6: return .MissingSecWebSocketKey + case 7: return .SecWebSocketAcceptKeyMismatch + case 8: return .JunkAfterRequest + case 9: return .CustomResponseSuccessful + case 10: return try .InvalidHeader( + header: FfiConverterString.read(from: &buf) + ) + case 11: return .HandshakeIncomplete + case 12: return try .HttparseError( + httparseError: FfiConverterTypeHTTParseError.read(from: &buf) + ) + case 13: return .SendAfterClosing + case 14: return .ReceivedAfterClosing + case 15: return .NonZeroReservedBits + case 16: return .UnmaskedFrameFromClient + case 17: return .MaskedFrameFromServer + case 18: return .FragmentedControlFrame + case 19: return .ControlFrameTooBig + case 20: return try .UnknownControlFrameType( + controlFrameType: FfiConverterUInt8.read(from: &buf) + ) + case 21: return try .UnknownDataFrameType( + dataFrameType: FfiConverterUInt8.read(from: &buf) + ) + case 22: return .UnexpectedContinueFrame + case 23: return try .ExpectedFragment( + data: FfiConverterTypeTungsteniteData.read(from: &buf) + ) + case 24: return .ResetWithoutClosingHandshake + case 25: return try .InvalidOpcode( + opcode: FfiConverterUInt8.read(from: &buf) + ) + case 26: return .InvalidCloseSequence + case 27: return .ServerSentSubProtocolNoneRequested + case 28: return .InvalidSubProtocol + case 29: return .NoSubProtocol + default: throw UniffiInternalError.unexpectedEnumCase + } + } + + public static func write(_ value: ProtocolError, into buf: inout [UInt8]) { + switch value { + case .WrongHttpMethod: + writeInt(&buf, Int32(1)) + + case .WrongHttpVersion: + writeInt(&buf, Int32(2)) + + case .MissingConnectionUpgradeHeader: + writeInt(&buf, Int32(3)) + + case .MissingUpgradeWebSocketHeader: + writeInt(&buf, Int32(4)) + + case .MissingSecWebSocketVersionHeader: + writeInt(&buf, Int32(5)) + + case .MissingSecWebSocketKey: + writeInt(&buf, Int32(6)) + + case .SecWebSocketAcceptKeyMismatch: + writeInt(&buf, Int32(7)) + + case .JunkAfterRequest: + writeInt(&buf, Int32(8)) + + case .CustomResponseSuccessful: + writeInt(&buf, Int32(9)) + + case let .InvalidHeader(header): + writeInt(&buf, Int32(10)) + FfiConverterString.write(header, into: &buf) + + case .HandshakeIncomplete: + writeInt(&buf, Int32(11)) + + case let .HttparseError(httparseError): + writeInt(&buf, Int32(12)) + FfiConverterTypeHTTParseError.write(httparseError, into: &buf) + + case .SendAfterClosing: + writeInt(&buf, Int32(13)) + + case .ReceivedAfterClosing: + writeInt(&buf, Int32(14)) + + case .NonZeroReservedBits: + writeInt(&buf, Int32(15)) + + case .UnmaskedFrameFromClient: + writeInt(&buf, Int32(16)) + + case .MaskedFrameFromServer: + writeInt(&buf, Int32(17)) + + case .FragmentedControlFrame: + writeInt(&buf, Int32(18)) + + case .ControlFrameTooBig: + writeInt(&buf, Int32(19)) + + case let .UnknownControlFrameType(controlFrameType): + writeInt(&buf, Int32(20)) + FfiConverterUInt8.write(controlFrameType, into: &buf) + + case let .UnknownDataFrameType(dataFrameType): + writeInt(&buf, Int32(21)) + FfiConverterUInt8.write(dataFrameType, into: &buf) + + case .UnexpectedContinueFrame: + writeInt(&buf, Int32(22)) + + case let .ExpectedFragment(data): + writeInt(&buf, Int32(23)) + FfiConverterTypeTungsteniteData.write(data, into: &buf) + + case .ResetWithoutClosingHandshake: + writeInt(&buf, Int32(24)) + + case let .InvalidOpcode(opcode): + writeInt(&buf, Int32(25)) + FfiConverterUInt8.write(opcode, into: &buf) + + case .InvalidCloseSequence: + writeInt(&buf, Int32(26)) + + case .ServerSentSubProtocolNoneRequested: + writeInt(&buf, Int32(27)) + + case .InvalidSubProtocol: + writeInt(&buf, Int32(28)) + + case .NoSubProtocol: + writeInt(&buf, Int32(29)) + } + } +} + +extension ProtocolError: Equatable, Hashable {} + +extension ProtocolError: Foundation.LocalizedError { + public var errorDescription: String? { + String(reflecting: self) + } +} + +/** + * Errors when calling [Socket::channel] + */ +public enum SocketChannelError { + /** + * The shutdown error for this SocketChannelError + */ + case Shutdown( + /** + * The shutdown error for this shutdown + */ shutdownError: SocketShutdownError + ) +} + +public struct FfiConverterTypeSocketChannelError: FfiConverterRustBuffer { + typealias SwiftType = SocketChannelError + + public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> SocketChannelError { + let variant: Int32 = try readInt(&buf) + switch variant { + case 1: return try .Shutdown( + shutdownError: FfiConverterTypeSocketShutdownError.read(from: &buf) + ) + + default: throw UniffiInternalError.unexpectedEnumCase + } + } + + public static func write(_ value: SocketChannelError, into buf: inout [UInt8]) { + switch value { + case let .Shutdown(shutdownError): + writeInt(&buf, Int32(1)) + FfiConverterTypeSocketShutdownError.write(shutdownError, into: &buf) + } + } +} + +extension SocketChannelError: Equatable, Hashable {} + +extension SocketChannelError: Foundation.LocalizedError { + public var errorDescription: String? { + String(reflecting: self) + } +} + +/** + * Errors when calling [Socket] functions. + */ +public enum SocketError { + /** + * Error when calling [Socket::spawn]. + */ + case Spawn( + /** + * Represents errors that occur from [`Socket::spawn`] + */ spawnError: SpawnError + ) + /** + * Error when calling [Socket::connect]. + */ + case Connect( + /** + * Errors from [Socket::connect]. + */ connectError: ConnectError + ) + /** + * Error when calling [Socket::channel]. + */ + case Channel( + /** + * Errors when calling [Socket::channel] + */ channelError: SocketChannelError + ) + /** + * Error when calling [Socket::disconnect]. + */ + case Disconnect( + /** + * Error when calling [Socket::disconnect] + */ disconnectError: DisconnectError + ) + /** + * Error when calling [Socket::shutdown]. + */ + case Shutdown( + /** + * Error from [Socket::shutdown] or from the server itself that caused the [Socket] to shutdown. + */ shutdownError: SocketShutdownError + ) +} + +public struct FfiConverterTypeSocketError: FfiConverterRustBuffer { + typealias SwiftType = SocketError + + public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> SocketError { + let variant: Int32 = try readInt(&buf) + switch variant { + case 1: return try .Spawn( + spawnError: FfiConverterTypeSpawnError.read(from: &buf) + ) + case 2: return try .Connect( + connectError: FfiConverterTypeConnectError.read(from: &buf) + ) + case 3: return try .Channel( + channelError: FfiConverterTypeSocketChannelError.read(from: &buf) + ) + case 4: return try .Disconnect( + disconnectError: FfiConverterTypeDisconnectError.read(from: &buf) + ) + case 5: return try .Shutdown( + shutdownError: FfiConverterTypeSocketShutdownError.read(from: &buf) + ) + default: throw UniffiInternalError.unexpectedEnumCase + } + } + + public static func write(_ value: SocketError, into buf: inout [UInt8]) { + switch value { + case let .Spawn(spawnError): + writeInt(&buf, Int32(1)) + FfiConverterTypeSpawnError.write(spawnError, into: &buf) + + case let .Connect(connectError): + writeInt(&buf, Int32(2)) + FfiConverterTypeConnectError.write(connectError, into: &buf) + + case let .Channel(channelError): + writeInt(&buf, Int32(3)) + FfiConverterTypeSocketChannelError.write(channelError, into: &buf) + + case let .Disconnect(disconnectError): + writeInt(&buf, Int32(4)) + FfiConverterTypeDisconnectError.write(disconnectError, into: &buf) + + case let .Shutdown(shutdownError): + writeInt(&buf, Int32(5)) + FfiConverterTypeSocketShutdownError.write(shutdownError, into: &buf) + } + } +} + +extension SocketError: Equatable, Hashable {} + +extension SocketError: Foundation.LocalizedError { + public var errorDescription: String? { + String(reflecting: self) + } +} + +/** + * Error from [Socket::shutdown] or from the server itself that caused the [Socket] to shutdown. + */ +public enum SocketShutdownError { + /** + * The async task was already joined by another call, so the [Result] or panic from the async + * task can't be reported here. + */ + case AlreadyJoined + /** + * [CVE-2023-43669](https://nvd.nist.gov/vuln/detail/CVE-2023-43669) attack attempt + */ + case AttackAttempt + /** + * Invalid URL. + */ + case Url(urlError: String + ) + /** + * HTTP error. + */ + case Http(response: Response + ) + /** + * HTTP format error. + */ + case HttpFormat(error: HttpError + ) +} + +public struct FfiConverterTypeSocketShutdownError: FfiConverterRustBuffer { + typealias SwiftType = SocketShutdownError + + public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> SocketShutdownError { + let variant: Int32 = try readInt(&buf) + switch variant { + case 1: return .AlreadyJoined + case 2: return .AttackAttempt + case 3: return try .Url( + urlError: FfiConverterString.read(from: &buf) + ) + case 4: return try .Http( + response: FfiConverterTypeResponse.read(from: &buf) + ) + case 5: return try .HttpFormat( + error: FfiConverterTypeHttpError.read(from: &buf) + ) + default: throw UniffiInternalError.unexpectedEnumCase + } + } + + public static func write(_ value: SocketShutdownError, into buf: inout [UInt8]) { + switch value { + case .AlreadyJoined: + writeInt(&buf, Int32(1)) + + case .AttackAttempt: + writeInt(&buf, Int32(2)) + + case let .Url(urlError): + writeInt(&buf, Int32(3)) + FfiConverterString.write(urlError, into: &buf) + + case let .Http(response): + writeInt(&buf, Int32(4)) + FfiConverterTypeResponse.write(response, into: &buf) + + case let .HttpFormat(error): + writeInt(&buf, Int32(5)) + FfiConverterTypeHttpError.write(error, into: &buf) + } + } +} + +extension SocketShutdownError: Equatable, Hashable {} + +extension SocketShutdownError: Foundation.LocalizedError { + public var errorDescription: String? { + String(reflecting: self) + } +} + +// Note that we don't yet support `indirect` for enums. +// See https://github.com/mozilla/uniffi-rs/issues/396 for further discussion. +/** + * The status of the [Socket]. + */ + +public enum SocketStatus { + /** + * [Socket::connect] has never been called. + */ + case neverConnected + /** + * [Socket::connect] was called and server responded the socket is connected. + */ + case connected + /** + * [Socket::connect] was called previously, but the [Socket] was disconnected by the server and + * [Socket] needs to wait to reconnect. + */ + case waitingToReconnect( + /** + * When the [Socket] will automatically [Socket::connect] next. + */ until: Date + ) + /** + * [Socket::disconnect] was called and the server responded that the socket as disconnected. + */ + case disconnected + /** + * [Socket::shutdown] was called, but the async task hasn't exited yet. + */ + case shuttingDown + /** + * The async task has exited. + */ + case shutDown +} + +public struct FfiConverterTypeSocketStatus: FfiConverterRustBuffer { + typealias SwiftType = SocketStatus + + public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> SocketStatus { + let variant: Int32 = try readInt(&buf) + switch variant { + case 1: return .neverConnected + + case 2: return .connected + + case 3: return try .waitingToReconnect(until: FfiConverterTimestamp.read(from: &buf) + ) + + case 4: return .disconnected + + case 5: return .shuttingDown + + case 6: return .shutDown + + default: throw UniffiInternalError.unexpectedEnumCase + } + } + + public static func write(_ value: SocketStatus, into buf: inout [UInt8]) { + switch value { + case .neverConnected: + writeInt(&buf, Int32(1)) + + case .connected: + writeInt(&buf, Int32(2)) + + case let .waitingToReconnect(until): + writeInt(&buf, Int32(3)) + FfiConverterTimestamp.write(until, into: &buf) + + case .disconnected: + writeInt(&buf, Int32(4)) + + case .shuttingDown: + writeInt(&buf, Int32(5)) + + case .shutDown: + writeInt(&buf, Int32(6)) + } + } +} + +public func FfiConverterTypeSocketStatus_lift(_ buf: RustBuffer) throws -> SocketStatus { + return try FfiConverterTypeSocketStatus.lift(buf) +} + +public func FfiConverterTypeSocketStatus_lower(_ value: SocketStatus) -> RustBuffer { + return FfiConverterTypeSocketStatus.lower(value) +} + +extension SocketStatus: Equatable, Hashable {} + +/** + * Represents errors that occur from [`Socket::spawn`] + */ +public enum SpawnError { + /** + * Occurs when the configured url's scheme is not ws or wss. + */ + case UnsupportedScheme(message: String) +} + +public struct FfiConverterTypeSpawnError: FfiConverterRustBuffer { + typealias SwiftType = SpawnError + + public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> SpawnError { + let variant: Int32 = try readInt(&buf) + switch variant { + case 1: return try .UnsupportedScheme( + message: FfiConverterString.read(from: &buf) + ) + + default: throw UniffiInternalError.unexpectedEnumCase + } + } + + public static func write(_ value: SpawnError, into buf: inout [UInt8]) { + switch value { + case .UnsupportedScheme(_ /* message is ignored*/ ): + writeInt(&buf, Int32(1)) + } + } +} + +extension SpawnError: Equatable, Hashable {} + +extension SpawnError: Foundation.LocalizedError { + public var errorDescription: String? { + String(reflecting: self) + } +} + +/** + * Wraps [tokio::sync::broadcast::error::RecvError] to add `uniffi` support and names specific to + * [ChannelStatuses](crate::ChannelStatuses). + */ +public enum StatusesError { + /** + * No more statuses + */ + case NoMoreStatuses + /** + * Missed statuses, jump to the next status + */ + case MissedStatuses( + /** + * Number of missed statuses. + */ missedStatusCount: UInt64 + ) + /** + * Failed to join a Channel (due to rejection). + */ + case ChannelStatusJoin( + /** + * The join Error + */ joinError: ChannelStatusJoinError + ) + /** + * An error with WebSockets + */ + case WebSocket( + /** + * The websocket error + */ websocketError: WebSocketError + ) +} + +public struct FfiConverterTypeStatusesError: FfiConverterRustBuffer { + typealias SwiftType = StatusesError + + public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> StatusesError { + let variant: Int32 = try readInt(&buf) + switch variant { + case 1: return .NoMoreStatuses + case 2: return try .MissedStatuses( + missedStatusCount: FfiConverterUInt64.read(from: &buf) + ) + case 3: return try .ChannelStatusJoin( + joinError: FfiConverterTypeChannelStatusJoinError.read(from: &buf) + ) + case 4: return try .WebSocket( + websocketError: FfiConverterTypeWebSocketError.read(from: &buf) + ) + default: throw UniffiInternalError.unexpectedEnumCase + } + } + + public static func write(_ value: StatusesError, into buf: inout [UInt8]) { + switch value { + case .NoMoreStatuses: + writeInt(&buf, Int32(1)) + + case let .MissedStatuses(missedStatusCount): + writeInt(&buf, Int32(2)) + FfiConverterUInt64.write(missedStatusCount, into: &buf) + + case let .ChannelStatusJoin(joinError): + writeInt(&buf, Int32(3)) + FfiConverterTypeChannelStatusJoinError.write(joinError, into: &buf) + + case let .WebSocket(websocketError): + writeInt(&buf, Int32(4)) + FfiConverterTypeWebSocketError.write(websocketError, into: &buf) + } + } +} + +extension StatusesError: Equatable, Hashable {} + +extension StatusesError: Foundation.LocalizedError { + public var errorDescription: String? { + String(reflecting: self) + } +} + +// Note that we don't yet support `indirect` for enums. +// See https://github.com/mozilla/uniffi-rs/issues/396 for further discussion. +/** + * [tokio_tungstenite::tungstenite::protocol::frame::coding::CloseCode], but with `uniffi::support` + * Status code used to indicate why an endpoint is closing the WebSocket connection. + */ + +public enum TungsteniteCloseCode { + /** + * Indicates a normal closure, meaning that the purpose for + * which the connection was established has been fulfilled. + */ + case normal + /** + * Indicates that an endpoint is "going away", such as a server + * going down or a browser having navigated away from a page. + */ + case away + /** + * Indicates that an endpoint is terminating the connection due + * to a protocol error. + */ + case `protocol` + /** + * Indicates that an endpoint is terminating the connection + * because it has received a type of data it cannot accept (e.g., an + * endpoint that understands only text data MAY send this if it + * receives a binary message). + */ + case unsupported + /** + * Indicates that no status code was included in a closing frame. This + * close code makes it possible to use a single method, `on_close` to + * handle even cases where no close code was provided. + */ + case status + /** + * Indicates an abnormal closure. If the abnormal closure was due to an + * error, this close code will not be used. Instead, the `on_error` method + * of the handler will be called with the error. However, if the connection + * is simply dropped, without an error, this close code will be sent to the + * handler. + */ + case abnormal + /** + * Indicates that an endpoint is terminating the connection + * because it has received data within a message that was not + * consistent with the type of the message (e.g., non-UTF-8 \[RFC3629\] + * data within a text message). + */ + case invalid + /** + * Indicates that an endpoint is terminating the connection + * because it has received a message that violates its policy. This + * is a generic status code that can be returned when there is no + * other more suitable status code (e.g., Unsupported or Size) or if there + * is a need to hide specific details about the policy. + */ + case policy + /** + * Indicates that an endpoint is terminating the connection + * because it has received a message that is too big for it to + * process. + */ + case size + /** + * Indicates that an endpoint (client) is terminating the + * connection because it has expected the server to negotiate one or + * more extension, but the server didn't return them in the response + * message of the WebSocket handshake. The list of extensions that + * are needed should be given as the reason for closing. + * Note that this status code is not used by the server, because it + * can fail the WebSocket handshake instead. + */ + case `extension` + /** + * Indicates that a server is terminating the connection because + * it encountered an unexpected condition that prevented it from + * fulfilling the request. + */ + case error + /** + * Indicates that the server is restarting. A client may choose to reconnect, + * and if it does, it should use a randomized delay of 5-30 seconds between attempts. + */ + case restart + /** + * Indicates that the server is overloaded and the client should either connect + * to a different IP (when multiple targets exist), or reconnect to the same IP + * when a user has performed an action. + */ + case again + case tls + case reserved(code: UInt16 + ) + case iana(code: UInt16 + ) + case library(code: UInt16 + ) + case bad(code: UInt16 + ) +} + +public struct FfiConverterTypeTungsteniteCloseCode: FfiConverterRustBuffer { + typealias SwiftType = TungsteniteCloseCode + + public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> TungsteniteCloseCode { + let variant: Int32 = try readInt(&buf) + switch variant { + case 1: return .normal + + case 2: return .away + + case 3: return .protocol + + case 4: return .unsupported + + case 5: return .status + + case 6: return .abnormal + + case 7: return .invalid + + case 8: return .policy + + case 9: return .size + + case 10: return .extension + + case 11: return .error + + case 12: return .restart + + case 13: return .again + + case 14: return .tls + + case 15: return try .reserved(code: FfiConverterUInt16.read(from: &buf) + ) + + case 16: return try .iana(code: FfiConverterUInt16.read(from: &buf) + ) + + case 17: return try .library(code: FfiConverterUInt16.read(from: &buf) + ) + + case 18: return try .bad(code: FfiConverterUInt16.read(from: &buf) + ) + + default: throw UniffiInternalError.unexpectedEnumCase + } + } + + public static func write(_ value: TungsteniteCloseCode, into buf: inout [UInt8]) { + switch value { + case .normal: + writeInt(&buf, Int32(1)) + + case .away: + writeInt(&buf, Int32(2)) + + case .protocol: + writeInt(&buf, Int32(3)) + + case .unsupported: + writeInt(&buf, Int32(4)) + + case .status: + writeInt(&buf, Int32(5)) + + case .abnormal: + writeInt(&buf, Int32(6)) + + case .invalid: + writeInt(&buf, Int32(7)) + + case .policy: + writeInt(&buf, Int32(8)) + + case .size: + writeInt(&buf, Int32(9)) + + case .extension: + writeInt(&buf, Int32(10)) + + case .error: + writeInt(&buf, Int32(11)) + + case .restart: + writeInt(&buf, Int32(12)) + + case .again: + writeInt(&buf, Int32(13)) + + case .tls: + writeInt(&buf, Int32(14)) + + case let .reserved(code): + writeInt(&buf, Int32(15)) + FfiConverterUInt16.write(code, into: &buf) + + case let .iana(code): + writeInt(&buf, Int32(16)) + FfiConverterUInt16.write(code, into: &buf) + + case let .library(code): + writeInt(&buf, Int32(17)) + FfiConverterUInt16.write(code, into: &buf) + + case let .bad(code): + writeInt(&buf, Int32(18)) + FfiConverterUInt16.write(code, into: &buf) + } + } +} + +public func FfiConverterTypeTungsteniteCloseCode_lift(_ buf: RustBuffer) throws -> TungsteniteCloseCode { + return try FfiConverterTypeTungsteniteCloseCode.lift(buf) +} + +public func FfiConverterTypeTungsteniteCloseCode_lower(_ value: TungsteniteCloseCode) -> RustBuffer { + return FfiConverterTypeTungsteniteCloseCode.lower(value) +} + +extension TungsteniteCloseCode: Equatable, Hashable {} + +// Note that we don't yet support `indirect` for enums. +// See https://github.com/mozilla/uniffi-rs/issues/396 for further discussion. +/** + * [tokio_tungstenite::tungstenite::protocol::frame::coding::Control], but with `uniffi` support. + * Control opcodes as in RFC 6455 + */ + +public enum TungsteniteControl { + /** + * 0x8 denotes a connection close + */ + case close + /** + * 0x9 denotes a ping + */ + case ping + /** + * 0xa denotes a pong + */ + case pong + /** + * 0xb-f are reserved for further control frames + */ + case reserved(bit: UInt8 + ) +} + +public struct FfiConverterTypeTungsteniteControl: FfiConverterRustBuffer { + typealias SwiftType = TungsteniteControl + + public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> TungsteniteControl { + let variant: Int32 = try readInt(&buf) + switch variant { + case 1: return .close + + case 2: return .ping + + case 3: return .pong + + case 4: return try .reserved(bit: FfiConverterUInt8.read(from: &buf) + ) + + default: throw UniffiInternalError.unexpectedEnumCase + } + } + + public static func write(_ value: TungsteniteControl, into buf: inout [UInt8]) { + switch value { + case .close: + writeInt(&buf, Int32(1)) + + case .ping: + writeInt(&buf, Int32(2)) + + case .pong: + writeInt(&buf, Int32(3)) + + case let .reserved(bit): + writeInt(&buf, Int32(4)) + FfiConverterUInt8.write(bit, into: &buf) + } + } +} + +public func FfiConverterTypeTungsteniteControl_lift(_ buf: RustBuffer) throws -> TungsteniteControl { + return try FfiConverterTypeTungsteniteControl.lift(buf) +} + +public func FfiConverterTypeTungsteniteControl_lower(_ value: TungsteniteControl) -> RustBuffer { + return FfiConverterTypeTungsteniteControl.lower(value) +} + +extension TungsteniteControl: Equatable, Hashable {} + +// Note that we don't yet support `indirect` for enums. +// See https://github.com/mozilla/uniffi-rs/issues/396 for further discussion. +/** + * [tokio_tungstenite::tungstenite::protocol::frame::coding::Data], but with `uniffi` support. + * Data opcodes as in RFC 6455 + */ + +public enum TungsteniteData { + /** + * 0x0 denotes a continuation frame + */ + case `continue` + /** + * 0x1 denotes a text frame + */ + case text + /** + * 0x2 denotes a binary frame + */ + case binary + /** + * 0x3-7 are reserved for further non-control frames + */ + case reserved(bits: UInt8 + ) +} + +public struct FfiConverterTypeTungsteniteData: FfiConverterRustBuffer { + typealias SwiftType = TungsteniteData + + public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> TungsteniteData { + let variant: Int32 = try readInt(&buf) + switch variant { + case 1: return .continue + + case 2: return .text + + case 3: return .binary + + case 4: return try .reserved(bits: FfiConverterUInt8.read(from: &buf) + ) + + default: throw UniffiInternalError.unexpectedEnumCase + } + } + + public static func write(_ value: TungsteniteData, into buf: inout [UInt8]) { + switch value { + case .continue: + writeInt(&buf, Int32(1)) + + case .text: + writeInt(&buf, Int32(2)) + + case .binary: + writeInt(&buf, Int32(3)) + + case let .reserved(bits): + writeInt(&buf, Int32(4)) + FfiConverterUInt8.write(bits, into: &buf) + } + } +} + +public func FfiConverterTypeTungsteniteData_lift(_ buf: RustBuffer) throws -> TungsteniteData { + return try FfiConverterTypeTungsteniteData.lift(buf) +} + +public func FfiConverterTypeTungsteniteData_lower(_ value: TungsteniteData) -> RustBuffer { + return FfiConverterTypeTungsteniteData.lower(value) +} + +extension TungsteniteData: Equatable, Hashable {} + +// Note that we don't yet support `indirect` for enums. +// See https://github.com/mozilla/uniffi-rs/issues/396 for further discussion. +/** + * [tokio_tungstenite::tungstenite::protocol::frame::coding::OpCode], but with `uniffi` support + * WebSocket message opcode as in RFC 6455. + */ + +public enum TungsteniteOpCode { + /** + * Data (text or binary). + */ + case data(data: TungsteniteData + ) + /** + * Control message (close, ping, pong). + */ + case control(control: TungsteniteControl + ) +} + +public struct FfiConverterTypeTungsteniteOpCode: FfiConverterRustBuffer { + typealias SwiftType = TungsteniteOpCode + + public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> TungsteniteOpCode { + let variant: Int32 = try readInt(&buf) + switch variant { + case 1: return try .data(data: FfiConverterTypeTungsteniteData.read(from: &buf) + ) + + case 2: return try .control(control: FfiConverterTypeTungsteniteControl.read(from: &buf) + ) + + default: throw UniffiInternalError.unexpectedEnumCase + } + } + + public static func write(_ value: TungsteniteOpCode, into buf: inout [UInt8]) { + switch value { + case let .data(data): + writeInt(&buf, Int32(1)) + FfiConverterTypeTungsteniteData.write(data, into: &buf) + + case let .control(control): + writeInt(&buf, Int32(2)) + FfiConverterTypeTungsteniteControl.write(control, into: &buf) + } + } +} + +public func FfiConverterTypeTungsteniteOpCode_lift(_ buf: RustBuffer) throws -> TungsteniteOpCode { + return try FfiConverterTypeTungsteniteOpCode.lift(buf) +} + +public func FfiConverterTypeTungsteniteOpCode_lower(_ value: TungsteniteOpCode) -> RustBuffer { + return FfiConverterTypeTungsteniteOpCode.lower(value) +} + +extension TungsteniteOpCode: Equatable, Hashable {} + +/** + * A uniffi supported wrapper around [uniffi::Error]. + */ +public enum UrlParseError { + /** + * Empty host + */ + case EmptyHost + /** + * Invalid international domain + */ + case IdnaError + /** + * Invalid port number + */ + case InvalidPort + /** + * Invalid ipv4 address. + */ + case InvalidIpv4Address + /** + * Invalid ipv6 address. + */ + case InvalidIpv6Address + /** + * Invalid domain character + */ + case InvalidDomainCharacter + /** + * Relative URL without a base + */ + case RelativeUrlWithoutBase + /** + * Relative URL with a cannot-be-a-base base" + */ + case RelativeUrlWithCannotBeABaseBase + /** + * A cannot-be-a-base URL doesn’t have a host to set + */ + case SetHostOnCannotBeABaseUrl + /** + * URLs more than 4 GB are not supported + */ + case Overflow +} + +public struct FfiConverterTypeURLParseError: FfiConverterRustBuffer { + typealias SwiftType = UrlParseError + + public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> UrlParseError { + let variant: Int32 = try readInt(&buf) + switch variant { + case 1: return .EmptyHost + case 2: return .IdnaError + case 3: return .InvalidPort + case 4: return .InvalidIpv4Address + case 5: return .InvalidIpv6Address + case 6: return .InvalidDomainCharacter + case 7: return .RelativeUrlWithoutBase + case 8: return .RelativeUrlWithCannotBeABaseBase + case 9: return .SetHostOnCannotBeABaseUrl + case 10: return .Overflow + default: throw UniffiInternalError.unexpectedEnumCase + } + } + + public static func write(_ value: UrlParseError, into buf: inout [UInt8]) { + switch value { + case .EmptyHost: + writeInt(&buf, Int32(1)) + + case .IdnaError: + writeInt(&buf, Int32(2)) + + case .InvalidPort: + writeInt(&buf, Int32(3)) + + case .InvalidIpv4Address: + writeInt(&buf, Int32(4)) + + case .InvalidIpv6Address: + writeInt(&buf, Int32(5)) + + case .InvalidDomainCharacter: + writeInt(&buf, Int32(6)) + + case .RelativeUrlWithoutBase: + writeInt(&buf, Int32(7)) + + case .RelativeUrlWithCannotBeABaseBase: + writeInt(&buf, Int32(8)) + + case .SetHostOnCannotBeABaseUrl: + writeInt(&buf, Int32(9)) + + case .Overflow: + writeInt(&buf, Int32(10)) + } + } +} + +extension UrlParseError: Equatable, Hashable {} + +extension UrlParseError: Foundation.LocalizedError { + public var errorDescription: String? { + String(reflecting: self) + } +} + +/** + * [tokio_tungstenite::tungstenite::error::Error], but with `uniffi` support + */ +public enum WebSocketError { + /** + * WebSocket connection closed normally. This informs you of the close. + * It's not an error as such and nothing wrong happened. + * + * This is returned as soon as the close handshake is finished (we have both sent and + * received a close frame) on the server end and as soon as the server has closed the + * underlying connection if this endpoint is a client. + * + * Thus when you receive this, it is safe to drop the underlying connection. + * + * Receiving this error means that the WebSocket object is not usable anymore and the + * only meaningful action with it is dropping it. + */ + case ConnectionClosed + /** + * Trying to work with already closed connection. + * + * Trying to read or write after receiving `ConnectionClosed` causes this. + * + * As opposed to `ConnectionClosed`, this indicates your code tries to operate on the + * connection when it really shouldn't anymore, so this really indicates a programmer + * error on your part. + */ + case AlreadyClosed + /** + * Input-output error. Apart from WouldBlock, these are generally errors with the + * underlying connection and you should probably consider them fatal. + */ + case Io( + /** + * Input-output error. Apart from WouldBlock, these are generally errors with the + * underlying connection and you should probably consider them fatal. + */ ioError: IoError + ) + /** + * TLS error. + */ + case Tls( + /** + * TLS error + */ tlsError: String + ) + /** + * - When reading: buffer capacity exhausted. + * - When writing: your message is bigger than the configured max message size + * (64MB by default). + */ + case Capacity( + /** + * When there are too many headers or the message is too long + */ capacityError: CapacityError + ) + /** + * Protocol violation. + */ + case Protocol( + /** + * Protocol violation + */ protocolError: ProtocolError + ) + /** + * Message write buffer is full. + */ + case WriteBufferFull( + /** + * The [WebSocketMessage] that could not fit in the write buffer. It should be resent + * later or the error needs to propagate up. + */ msg: WebSocketMessage + ) + /** + * UTF coding error. + */ + case Utf8 + /** + * [CVE-2023-43669](https://nvd.nist.gov/vuln/detail/CVE-2023-43669) attack attempt + */ + case AttackAttempt + /** + * Invalid URL. + */ + case Url( + /** + * The URL error as a string + */ urlError: String + ) + /** + * HTTP error. + */ + case Http( + /** + * Error response from the server. + */ response: Response + ) + /** + * HTTP format error. + */ + case HttpFormat( + /** + * HTTP format error. + */ error: HttpError + ) +} + +public struct FfiConverterTypeWebSocketError: FfiConverterRustBuffer { + typealias SwiftType = WebSocketError + + public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> WebSocketError { + let variant: Int32 = try readInt(&buf) + switch variant { + case 1: return .ConnectionClosed + case 2: return .AlreadyClosed + case 3: return try .Io( + ioError: FfiConverterTypeIoError.read(from: &buf) + ) + case 4: return try .Tls( + tlsError: FfiConverterString.read(from: &buf) + ) + case 5: return try .Capacity( + capacityError: FfiConverterTypeCapacityError.read(from: &buf) + ) + case 6: return try .Protocol( + protocolError: FfiConverterTypeProtocolError.read(from: &buf) + ) + case 7: return try .WriteBufferFull( + msg: FfiConverterTypeWebSocketMessage.read(from: &buf) + ) + case 8: return .Utf8 + case 9: return .AttackAttempt + case 10: return try .Url( + urlError: FfiConverterString.read(from: &buf) + ) + case 11: return try .Http( + response: FfiConverterTypeResponse.read(from: &buf) + ) + case 12: return try .HttpFormat( + error: FfiConverterTypeHttpError.read(from: &buf) + ) + default: throw UniffiInternalError.unexpectedEnumCase + } + } + + public static func write(_ value: WebSocketError, into buf: inout [UInt8]) { + switch value { + case .ConnectionClosed: + writeInt(&buf, Int32(1)) + + case .AlreadyClosed: + writeInt(&buf, Int32(2)) + + case let .Io(ioError): + writeInt(&buf, Int32(3)) + FfiConverterTypeIoError.write(ioError, into: &buf) + + case let .Tls(tlsError): + writeInt(&buf, Int32(4)) + FfiConverterString.write(tlsError, into: &buf) + + case let .Capacity(capacityError): + writeInt(&buf, Int32(5)) + FfiConverterTypeCapacityError.write(capacityError, into: &buf) + + case let .Protocol(protocolError): + writeInt(&buf, Int32(6)) + FfiConverterTypeProtocolError.write(protocolError, into: &buf) + + case let .WriteBufferFull(msg): + writeInt(&buf, Int32(7)) + FfiConverterTypeWebSocketMessage.write(msg, into: &buf) + + case .Utf8: + writeInt(&buf, Int32(8)) + + case .AttackAttempt: + writeInt(&buf, Int32(9)) + + case let .Url(urlError): + writeInt(&buf, Int32(10)) + FfiConverterString.write(urlError, into: &buf) + + case let .Http(response): + writeInt(&buf, Int32(11)) + FfiConverterTypeResponse.write(response, into: &buf) + + case let .HttpFormat(error): + writeInt(&buf, Int32(12)) + FfiConverterTypeHttpError.write(error, into: &buf) + } + } +} + +extension WebSocketError: Equatable, Hashable {} + +extension WebSocketError: Foundation.LocalizedError { + public var errorDescription: String? { + String(reflecting: self) + } +} + +// Note that we don't yet support `indirect` for enums. +// See https://github.com/mozilla/uniffi-rs/issues/396 for further discussion. +/** + * [tokio_tungstenite::tungstenite::protocol::Message], but with `uniffi` support. + * An enum representing the various forms of a WebSocket message. + */ + +public enum WebSocketMessage { + /** + * A text WebSocket message + */ + case text( + /** + * The text of the message. + */ text: String + ) + /** + * A binary WebSocket message + */ + case binary( + /** + * The binary bytes of the message. + */ bytes: Data + ) + /** + * A ping message with the specified payload + * + * The payload here must have a length less than 125 bytes + */ + case ping( + /** + * The bytes that should be sent back in a [WebSocketMessage::Pong] message. + */ bytes: Data + ) + /** + * A pong message with the specified payload + * + * The payload here must have a length less than 125 bytes + */ + case pong( + /** + * The bytes sent back in reply to a [WebSocketMessage::Ping]. The `bytes` should match + * the last `WebSocketMessage::Pong` to count as an acknowledgement. + */ bytes: Data + ) + /** + * A close message with the optional close frame. + */ + case close( + /** + * The optional frame sent when the server closes the web socket. Includes the code and + * reason. + */ closeFrame: CloseFrame? + ) + /** + * Raw frame. Note, that you're not going to get this value while reading the message. + */ + case webSocketFrame( + /** + * A raw frame that hasn't been categorized into the other variants. + */ frame: Frame + ) +} + +public struct FfiConverterTypeWebSocketMessage: FfiConverterRustBuffer { + typealias SwiftType = WebSocketMessage + + public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> WebSocketMessage { + let variant: Int32 = try readInt(&buf) + switch variant { + case 1: return try .text(text: FfiConverterString.read(from: &buf) + ) + + case 2: return try .binary(bytes: FfiConverterData.read(from: &buf) + ) + + case 3: return try .ping(bytes: FfiConverterData.read(from: &buf) + ) + + case 4: return try .pong(bytes: FfiConverterData.read(from: &buf) + ) + + case 5: return try .close(closeFrame: FfiConverterOptionTypeCloseFrame.read(from: &buf) + ) + + case 6: return try .webSocketFrame(frame: FfiConverterTypeFrame.read(from: &buf) + ) + + default: throw UniffiInternalError.unexpectedEnumCase + } + } + + public static func write(_ value: WebSocketMessage, into buf: inout [UInt8]) { + switch value { + case let .text(text): + writeInt(&buf, Int32(1)) + FfiConverterString.write(text, into: &buf) + + case let .binary(bytes): + writeInt(&buf, Int32(2)) + FfiConverterData.write(bytes, into: &buf) + + case let .ping(bytes): + writeInt(&buf, Int32(3)) + FfiConverterData.write(bytes, into: &buf) + + case let .pong(bytes): + writeInt(&buf, Int32(4)) + FfiConverterData.write(bytes, into: &buf) + + case let .close(closeFrame): + writeInt(&buf, Int32(5)) + FfiConverterOptionTypeCloseFrame.write(closeFrame, into: &buf) + + case let .webSocketFrame(frame): + writeInt(&buf, Int32(6)) + FfiConverterTypeFrame.write(frame, into: &buf) + } + } +} + +public func FfiConverterTypeWebSocketMessage_lift(_ buf: RustBuffer) throws -> WebSocketMessage { + return try FfiConverterTypeWebSocketMessage.lift(buf) +} + +public func FfiConverterTypeWebSocketMessage_lower(_ value: WebSocketMessage) -> RustBuffer { + return FfiConverterTypeWebSocketMessage.lower(value) +} + +extension WebSocketMessage: Equatable, Hashable {} + +private struct FfiConverterOptionData: FfiConverterRustBuffer { + typealias SwiftType = Data? + + public static func write(_ value: SwiftType, into buf: inout [UInt8]) { + guard let value = value else { + writeInt(&buf, Int8(0)) + return + } + writeInt(&buf, Int8(1)) + FfiConverterData.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 FfiConverterData.read(from: &buf) + default: throw UniffiInternalError.unexpectedOptionalTag + } + } +} + +private struct FfiConverterOptionTypeCloseFrame: FfiConverterRustBuffer { + typealias SwiftType = CloseFrame? + + public static func write(_ value: SwiftType, into buf: inout [UInt8]) { + guard let value = value else { + writeInt(&buf, Int8(0)) + return + } + writeInt(&buf, Int8(1)) + FfiConverterTypeCloseFrame.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 FfiConverterTypeCloseFrame.read(from: &buf) + default: throw UniffiInternalError.unexpectedOptionalTag + } + } +} + +private struct FfiConverterOptionTypePayload: FfiConverterRustBuffer { + typealias SwiftType = Payload? + + public static func write(_ value: SwiftType, into buf: inout [UInt8]) { + guard let value = value else { + writeInt(&buf, Int8(0)) + return + } + writeInt(&buf, Int8(1)) + FfiConverterTypePayload.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 FfiConverterTypePayload.read(from: &buf) + default: throw UniffiInternalError.unexpectedOptionalTag + } + } +} + +private struct FfiConverterOptionSequenceString: 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)) + FfiConverterSequenceString.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 FfiConverterSequenceString.read(from: &buf) + default: throw UniffiInternalError.unexpectedOptionalTag + } + } +} + +private struct FfiConverterSequenceString: FfiConverterRustBuffer { + typealias SwiftType = [String] + + public static func write(_ value: [String], into buf: inout [UInt8]) { + let len = Int32(value.count) + writeInt(&buf, len) + for item in value { + FfiConverterString.write(item, into: &buf) + } + } + + public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> [String] { + let len: Int32 = try readInt(&buf) + var seq = [String]() + seq.reserveCapacity(Int(len)) + for _ in 0 ..< len { + try seq.append(FfiConverterString.read(from: &buf)) + } + return seq + } +} + +private struct FfiConverterSequenceTypeJSON: FfiConverterRustBuffer { + typealias SwiftType = [Json] + + public static func write(_ value: [Json], into buf: inout [UInt8]) { + let len = Int32(value.count) + writeInt(&buf, len) + for item in value { + FfiConverterTypeJSON.write(item, into: &buf) + } + } + + public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> [Json] { + let len: Int32 = try readInt(&buf) + var seq = [Json]() + seq.reserveCapacity(Int(len)) + for _ in 0 ..< len { + try seq.append(FfiConverterTypeJSON.read(from: &buf)) + } + return seq + } +} + +private struct FfiConverterDictionaryStringTypeJSON: FfiConverterRustBuffer { + public static func write(_ value: [String: Json], into buf: inout [UInt8]) { + let len = Int32(value.count) + writeInt(&buf, len) + for (key, value) in value { + FfiConverterString.write(key, into: &buf) + FfiConverterTypeJSON.write(value, into: &buf) + } + } + + public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> [String: Json] { + let len: Int32 = try readInt(&buf) + var dict = [String: Json]() + dict.reserveCapacity(Int(len)) + for _ in 0 ..< len { + let key = try FfiConverterString.read(from: &buf) + let value = try FfiConverterTypeJSON.read(from: &buf) + dict[key] = value + } + return dict + } +} + +private struct FfiConverterDictionaryStringSequenceString: FfiConverterRustBuffer { + public static func write(_ value: [String: [String]], into buf: inout [UInt8]) { + let len = Int32(value.count) + writeInt(&buf, len) + for (key, value) in value { + FfiConverterString.write(key, into: &buf) + FfiConverterSequenceString.write(value, into: &buf) + } + } + + public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> [String: [String]] { + let len: Int32 = try readInt(&buf) + var dict = [String: [String]]() + dict.reserveCapacity(Int(len)) + for _ in 0 ..< len { + let key = try FfiConverterString.read(from: &buf) + let value = try FfiConverterSequenceString.read(from: &buf) + dict[key] = value + } + return dict + } +} + +/** + * Typealias from the type name used in the UDL file to the custom type. This + * is needed because the UDL type name is used in function/method signatures. + */ +public typealias Url = URL + +public struct FfiConverterTypeUrl: FfiConverter { + public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> Url { + let builtinValue = try FfiConverterString.read(from: &buf) + return URL(string: builtinValue)! + } + + public static func write(_ value: Url, into buf: inout [UInt8]) { + let builtinValue = String(describing: value) + return FfiConverterString.write(builtinValue, into: &buf) + } + + public static func lift(_ value: RustBuffer) throws -> Url { + let builtinValue = try FfiConverterString.lift(value) + return URL(string: builtinValue)! + } + + public static func lower(_ value: Url) -> RustBuffer { + let builtinValue = String(describing: value) + return FfiConverterString.lower(builtinValue) + } +} + +public func FfiConverterTypeUrl_lift(_ value: RustBuffer) throws -> Url { + return try FfiConverterTypeUrl.lift(value) +} + +public func FfiConverterTypeUrl_lower(_ value: Url) -> RustBuffer { + return FfiConverterTypeUrl.lower(value) +} + +private let UNIFFI_RUST_FUTURE_POLL_READY: Int8 = 0 +private let UNIFFI_RUST_FUTURE_POLL_MAYBE_READY: Int8 = 1 + +private let uniffiContinuationHandleMap = UniffiHandleMap>() + +private func uniffiRustCallAsync( + rustFutureFunc: () -> UInt64, + pollFunc: (UInt64, @escaping UniffiRustFutureContinuationCallback, UInt64) -> Void, + completeFunc: (UInt64, UnsafeMutablePointer) -> F, + freeFunc: (UInt64) -> Void, + liftFunc: (F) throws -> T, + errorHandler: ((RustBuffer) throws -> Swift.Error)? +) async throws -> T { + // Make sure to call uniffiEnsureInitialized() since future creation doesn't have a + // RustCallStatus param, so doesn't use makeRustCall() + uniffiEnsureInitialized() + let rustFuture = rustFutureFunc() + defer { + freeFunc(rustFuture) + } + var pollResult: Int8 + repeat { + pollResult = await withUnsafeContinuation { + pollFunc( + rustFuture, + uniffiFutureContinuationCallback, + uniffiContinuationHandleMap.insert(obj: $0) + ) + } + } while pollResult != UNIFFI_RUST_FUTURE_POLL_READY + + return try liftFunc(makeRustCall( + { completeFunc(rustFuture, $0) }, + errorHandler: errorHandler + )) +} + +// Callback handlers for an async calls. These are invoked by Rust when the future is ready. They +// lift the return value or error and resume the suspended function. +private func uniffiFutureContinuationCallback(handle: UInt64, pollResult: Int8) { + if let continuation = try? uniffiContinuationHandleMap.remove(handle: handle) { + continuation.resume(returning: pollResult) + } else { + print("uniffiFutureContinuationCallback invalid handle") + } +} + +private enum InitializationResult { + case ok + case contractVersionMismatch + case apiChecksumMismatch +} + +// Use a global variable 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_phoenix_channels_client_uniffi_contract_version() + if bindings_contract_version != scaffolding_contract_version { + return InitializationResult.contractVersionMismatch + } + if uniffi_phoenix_channels_client_checksum_method_channel_call() != 57788 { + return InitializationResult.apiChecksumMismatch + } + if uniffi_phoenix_channels_client_checksum_method_channel_cast() != 701 { + return InitializationResult.apiChecksumMismatch + } + if uniffi_phoenix_channels_client_checksum_method_channel_events() != 27101 { + return InitializationResult.apiChecksumMismatch + } + if uniffi_phoenix_channels_client_checksum_method_channel_join() != 57628 { + return InitializationResult.apiChecksumMismatch + } + if uniffi_phoenix_channels_client_checksum_method_channel_leave() != 43457 { + return InitializationResult.apiChecksumMismatch + } + if uniffi_phoenix_channels_client_checksum_method_channel_listener_shutdown() != 3972 { + return InitializationResult.apiChecksumMismatch + } + if uniffi_phoenix_channels_client_checksum_method_channel_payload() != 14057 { + return InitializationResult.apiChecksumMismatch + } + if uniffi_phoenix_channels_client_checksum_method_channel_shutdown() != 21366 { + return InitializationResult.apiChecksumMismatch + } + if uniffi_phoenix_channels_client_checksum_method_channel_status() != 39920 { + return InitializationResult.apiChecksumMismatch + } + if uniffi_phoenix_channels_client_checksum_method_channel_statuses() != 46216 { + return InitializationResult.apiChecksumMismatch + } + if uniffi_phoenix_channels_client_checksum_method_channel_topic() != 32568 { + return InitializationResult.apiChecksumMismatch + } + if uniffi_phoenix_channels_client_checksum_method_channelstatuses_status() != 37032 { + return InitializationResult.apiChecksumMismatch + } + if uniffi_phoenix_channels_client_checksum_method_events_event() != 3693 { + return InitializationResult.apiChecksumMismatch + } + if uniffi_phoenix_channels_client_checksum_method_socket_channel() != 57669 { + return InitializationResult.apiChecksumMismatch + } + if uniffi_phoenix_channels_client_checksum_method_socket_connect() != 2761 { + return InitializationResult.apiChecksumMismatch + } + if uniffi_phoenix_channels_client_checksum_method_socket_disconnect() != 6328 { + return InitializationResult.apiChecksumMismatch + } + if uniffi_phoenix_channels_client_checksum_method_socket_shutdown() != 1005 { + return InitializationResult.apiChecksumMismatch + } + if uniffi_phoenix_channels_client_checksum_method_socket_status() != 52082 { + return InitializationResult.apiChecksumMismatch + } + if uniffi_phoenix_channels_client_checksum_method_socket_statuses() != 29743 { + return InitializationResult.apiChecksumMismatch + } + if uniffi_phoenix_channels_client_checksum_method_socket_url() != 48469 { + return InitializationResult.apiChecksumMismatch + } + if uniffi_phoenix_channels_client_checksum_constructor_socket_spawn() != 47379 { + return InitializationResult.apiChecksumMismatch + } + if uniffi_phoenix_channels_client_checksum_constructor_topic_from_string() != 28533 { + return InitializationResult.apiChecksumMismatch + } + + 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