// 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(cera_ffiFFI)
import cera_ffiFFI
#endif

fileprivate 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<UInt8>) -> RustBuffer {
        try! rustCall { ffi_cera_ffi_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_cera_ffi_rustbuffer_free(self, $0) }
    }
}

fileprivate extension ForeignBytes {
    init(bufferPointer: UnsafeBufferPointer<UInt8>) {
        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.

fileprivate extension Data {
    init(rustBuffer: RustBuffer) {
        self.init(
            bytesNoCopy: rustBuffer.data!,
            count: Int(rustBuffer.len),
            deallocator: .none
        )
    }
}

// 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

fileprivate 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.
fileprivate func readInt<T: FixedWidthInteger>(_ reader: inout (data: Data, offset: Data.Index)) throws -> T {
    let range = reader.offset..<reader.offset + MemoryLayout<T>.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
fileprivate func readBytes(_ reader: inout (data: Data, offset: Data.Index), count: Int) throws -> Array<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.
fileprivate func readFloat(_ reader: inout (data: Data, offset: Data.Index)) throws -> Float {
    return Float(bitPattern: try readInt(&reader))
}

// Reads a float at the current offset.
fileprivate func readDouble(_ reader: inout (data: Data, offset: Data.Index)) throws -> Double {
    return Double(bitPattern: try readInt(&reader))
}

// Indicates if the offset has reached the end of the buffer.
fileprivate 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.

fileprivate func createWriter() -> [UInt8] {
    return []
}

fileprivate func writeBytes<S>(_ 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!
fileprivate func writeInt<T: FixedWidthInteger>(_ writer: inout [UInt8], _ value: T) {
    var value = value.bigEndian
    withUnsafeBytes(of: &value) { writer.append(contentsOf: $0) }
}

fileprivate func writeFloat(_ writer: inout [UInt8], _ value: Float) {
    writeInt(&writer, value.bitPattern)
}

fileprivate 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.
fileprivate 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.
fileprivate protocol FfiConverterPrimitive: FfiConverter where FfiType == SwiftType { }

extension FfiConverterPrimitive {
#if swift(>=5.8)
    @_documentation(visibility: private)
#endif
    public static func lift(_ value: FfiType) throws -> SwiftType {
        return value
    }

#if swift(>=5.8)
    @_documentation(visibility: private)
#endif
    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.
fileprivate protocol FfiConverterRustBuffer: FfiConverter where FfiType == RustBuffer {}

extension FfiConverterRustBuffer {
#if swift(>=5.8)
    @_documentation(visibility: private)
#endif
    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
    }

#if swift(>=5.8)
    @_documentation(visibility: private)
#endif
    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.
fileprivate 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
        }
    }
}

fileprivate extension NSLock {
    func withLock<T>(f: () throws -> T) rethrows -> T {
        self.lock()
        defer { self.unlock() }
        return try f()
    }
}

fileprivate let CALL_SUCCESS: Int8 = 0
fileprivate let CALL_ERROR: Int8 = 1
fileprivate let CALL_UNEXPECTED_ERROR: Int8 = 2
fileprivate let CALL_CANCELLED: Int8 = 3

fileprivate extension RustCallStatus {
    init() {
        self.init(
            code: CALL_SUCCESS,
            errorBuf: RustBuffer.init(
                capacity: 0,
                len: 0,
                data: nil
            )
        )
    }
}

private func rustCall<T>(_ callback: (UnsafeMutablePointer<RustCallStatus>) -> T) throws -> T {
    let neverThrow: ((RustBuffer) throws -> Never)? = nil
    return try makeRustCall(callback, errorHandler: neverThrow)
}

private func rustCallWithError<T, E: Swift.Error>(
    _ errorHandler: @escaping (RustBuffer) throws -> E,
    _ callback: (UnsafeMutablePointer<RustCallStatus>) -> T) throws -> T {
    try makeRustCall(callback, errorHandler: errorHandler)
}

private func makeRustCall<T, E: Swift.Error>(
    _ callback: (UnsafeMutablePointer<RustCallStatus>) -> T,
    errorHandler: ((RustBuffer) throws -> E)?
) throws -> T {
    uniffiEnsureCeraFfiInitialized()
    var callStatus = RustCallStatus.init()
    let returnedVal = callback(&callStatus)
    try uniffiCheckCallStatus(callStatus: callStatus, errorHandler: errorHandler)
    return returnedVal
}

private func uniffiCheckCallStatus<E: Swift.Error>(
    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 UniffiInternalError.rustPanic(try 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<T>(
    callStatus: UnsafeMutablePointer<RustCallStatus>,
    makeCall: () throws -> T,
    writeReturn: (T) -> ()
) {
    do {
        try writeReturn(makeCall())
    } catch let error {
        callStatus.pointee.code = CALL_UNEXPECTED_ERROR
        callStatus.pointee.errorBuf = FfiConverterString.lower(String(describing: error))
    }
}

private func uniffiTraitInterfaceCallWithError<T, E>(
    callStatus: UnsafeMutablePointer<RustCallStatus>,
    makeCall: () throws -> T,
    writeReturn: (T) -> (),
    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))
    }
}
// Initial value and increment amount for handles. 
// These ensure that SWIFT handles always have the lowest bit set
fileprivate let UNIFFI_HANDLEMAP_INITIAL: UInt64 = 1
fileprivate let UNIFFI_HANDLEMAP_DELTA: UInt64 = 2

fileprivate final class UniffiHandleMap<T>: @unchecked Sendable {
    // All mutation happens with this lock held, which is why we implement @unchecked Sendable.
    private let lock = NSLock()
    private var map: [UInt64: T] = [:]
    private var currentHandle: UInt64 = UNIFFI_HANDLEMAP_INITIAL

    func insert(obj: T) -> UInt64 {
        lock.withLock {
            return doInsert(obj)
        }
    }

    // Low-level insert function, this assumes `lock` is held.
    private func doInsert(_ obj: T) -> UInt64 {
        let handle = currentHandle
        currentHandle += UNIFFI_HANDLEMAP_DELTA
        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
        }
    }

     func clone(handle: UInt64) throws -> UInt64 {
        try lock.withLock {
            guard let obj = map[handle] else {
                throw UniffiInternalError.unexpectedStaleHandle
            }
            return doInsert(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 {
        get {
            map.count
        }
    }
}


// Public interface members begin here.
// 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

#if swift(>=5.8)
@_documentation(visibility: private)
#endif
fileprivate struct FfiConverterUInt32: FfiConverterPrimitive {
    typealias FfiType = UInt32
    typealias SwiftType = UInt32

    public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> UInt32 {
        return try lift(readInt(&buf))
    }

    public static func write(_ value: SwiftType, into buf: inout [UInt8]) {
        writeInt(&buf, lower(value))
    }
}

#if swift(>=5.8)
@_documentation(visibility: private)
#endif
fileprivate 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))
    }
}

#if swift(>=5.8)
@_documentation(visibility: private)
#endif
fileprivate struct FfiConverterFloat: FfiConverterPrimitive {
    typealias FfiType = Float
    typealias SwiftType = Float

    public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> Float {
        return try lift(readFloat(&buf))
    }

    public static func write(_ value: Float, into buf: inout [UInt8]) {
        writeFloat(&buf, lower(value))
    }
}

#if swift(>=5.8)
@_documentation(visibility: private)
#endif
fileprivate 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))
    }
}

#if swift(>=5.8)
@_documentation(visibility: private)
#endif
fileprivate 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<UInt8>(start: value.data!, count: Int(value.len))
        // Use Swift's native UTF-8 decoder; `String(bytes:encoding:.utf8)` goes
        // through Foundation's NSString and silently strips a leading U+FEFF BOM.
        // Invalid UTF-8 substitutes U+FFFD instead of trapping (unreachable
        // given Rust's `String` invariant).
        return String(decoding: bytes, as: UTF8.self)
    }

    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)
        // See `lift` above for why we avoid Foundation's NSString-backed decoder here.
        return String(decoding: try readBytes(&buf, count: Int(len)), as: UTF8.self)
    }

    public static func write(_ value: String, into buf: inout [UInt8]) {
        let len = Int32(value.utf8.count)
        writeInt(&buf, len)
        writeBytes(&buf, value.utf8)
    }
}

#if swift(>=5.8)
@_documentation(visibility: private)
#endif
fileprivate 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 Data(try 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)
    }
}




/**
 * Remote model-bundle downloader + on-disk cache. Wraps
 * [`cera::bundle::BundleRepo`]; construct once per application with
 * a persistent `store_dir` and reuse across engine loads so the
 * HTTP client pool + downloaded-file cache are shared.
 *
 * On Android the `store_dir` should typically be
 * `Context.getFilesDir()` (persistent), not `getCacheDir()` (OS-
 * purgeable under storage pressure). On iOS / macOS, the app's
 * Application Support or a dedicated subdirectory under Documents
 * is a reasonable baseline.
 *
 * Cache layout mirrors the remote URL structure under
 * `<store_dir>/huggingface.co/<full path>`, so inspecting the
 * on-disk state with a file browser is straightforward and multiple
 * cera-powered apps on the same device can share the same cache
 * directory without conflicting.
 */
public protocol BundleRepoProtocol: AnyObject, Sendable {
    
    /**
     * Total bytes currently held in the cache. Returns `0` if the
     * `store_dir` doesn't exist yet (no downloads have run).
     * O(n) over the cache contents; for a multi-GB cache it's a
     * real walk, not a constant-time query — UIs surfacing the
     * value should run it off the main thread (e.g. via
     * `withContext(Dispatchers.IO)` on Kotlin or
     * `Task.detached` on Swift).
     *
     * Mobile apps use this to drive a "Storage: X MB used" line in
     * settings or to gate a "Clear cache" button on actual
     * non-zero usage.
     */
    func cacheSize() throws  -> UInt64
    
    /**
     * Wipe every file the repo has cached, leaving `store_dir`
     * itself in place so subsequent downloads land in the same
     * path. Idempotent — calling on an empty repo or non-existent
     * `store_dir` is a no-op success.
     *
     * Mobile apps trigger this from a "Clear downloaded models"
     * settings action. Caller is responsible for serializing
     * against in-flight downloads — typically trivial since the
     * action is user-driven.
     */
    func clearCache() throws 
    
    /**
     * The directory this repo caches bundles under. Matches what was
     * passed to [`BundleRepo::new`] / [`BundleRepo::with_progress`],
     * useful for log / telemetry.
     */
    func storeDir()  -> String
    
}
/**
 * Remote model-bundle downloader + on-disk cache. Wraps
 * [`cera::bundle::BundleRepo`]; construct once per application with
 * a persistent `store_dir` and reuse across engine loads so the
 * HTTP client pool + downloaded-file cache are shared.
 *
 * On Android the `store_dir` should typically be
 * `Context.getFilesDir()` (persistent), not `getCacheDir()` (OS-
 * purgeable under storage pressure). On iOS / macOS, the app's
 * Application Support or a dedicated subdirectory under Documents
 * is a reasonable baseline.
 *
 * Cache layout mirrors the remote URL structure under
 * `<store_dir>/huggingface.co/<full path>`, so inspecting the
 * on-disk state with a file browser is straightforward and multiple
 * cera-powered apps on the same device can share the same cache
 * directory without conflicting.
 */
open class BundleRepo: BundleRepoProtocol, @unchecked Sendable {
    fileprivate let handle: UInt64

    /// Used to instantiate a [FFIObject] without an actual handle, for fakes in tests, mostly.
#if swift(>=5.8)
    @_documentation(visibility: private)
#endif
    public struct NoHandle {
        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`.
#if swift(>=5.8)
    @_documentation(visibility: private)
#endif
    required public init(unsafeFromHandle handle: UInt64) {
        self.handle = handle
    }

    // This constructor can be used to instantiate a fake object.
    // - Parameter noHandle: 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 handle the FFI lower functions will crash.
#if swift(>=5.8)
    @_documentation(visibility: private)
#endif
    public init(noHandle: NoHandle) {
        self.handle = 0
    }

#if swift(>=5.8)
    @_documentation(visibility: private)
#endif
    public func uniffiCloneHandle() -> UInt64 {
        return try! rustCall { uniffi_cera_ffi_fn_clone_bundlerepo(self.handle, $0) }
    }
    /**
     * Create a new repo rooted at `store_dir`. The directory doesn't
     * need to exist yet — it's created on the first download. Pass
     * the same path to subsequent runs to reuse the cached bundles.
     */
public convenience init(storeDir: String) {
    let handle =
        try! rustCall() {
    uniffi_cera_ffi_fn_constructor_bundlerepo_new(
        FfiConverterString.lower(storeDir),$0
    )
}
    self.init(unsafeFromHandle: handle)
}

    deinit {
        if handle == 0 {
            // Mock objects have handle=0 don't try to free them
            return
        }

        try! rustCall { uniffi_cera_ffi_fn_free_bundlerepo(handle, $0) }
    }

    
    /**
     * Create a new repo rooted at `store_dir` with a foreign
     * [`DownloadProgressSink`] attached. The sink fires periodically
     * during cache-miss downloads (every ~256 KB written + once at
     * end-of-stream). Cache-hit resolves don't fire any callbacks.
     * The same sink receives events for every file the repo
     * downloads — distinguish per-file progress by the `url`
     * argument on each callback.
     *
     * Construction-time attachment (rather than per-call) matches
     * how mobile apps drive a single download-progress UI across
     * multiple files in one logical bundle (manifest + GGUF + …):
     * one repo, one sink, one progress bar. If you need to tear
     * down the sink mid-app-lifecycle, drop the repo + construct a
     * new one — Arc-based, so all in-flight calls finish on the
     * old sink and new calls go to the new one.
     */
public static func withProgress(storeDir: String, progress: DownloadProgressSink) -> BundleRepo  {
    return try!  FfiConverterTypeBundleRepo_lift(try! rustCall() {
    uniffi_cera_ffi_fn_constructor_bundlerepo_with_progress(
        FfiConverterString.lower(storeDir),
        FfiConverterTypeDownloadProgressSink_lower(progress),$0
    )
})
}
    

    
    /**
     * Total bytes currently held in the cache. Returns `0` if the
     * `store_dir` doesn't exist yet (no downloads have run).
     * O(n) over the cache contents; for a multi-GB cache it's a
     * real walk, not a constant-time query — UIs surfacing the
     * value should run it off the main thread (e.g. via
     * `withContext(Dispatchers.IO)` on Kotlin or
     * `Task.detached` on Swift).
     *
     * Mobile apps use this to drive a "Storage: X MB used" line in
     * settings or to gate a "Clear cache" button on actual
     * non-zero usage.
     */
open func cacheSize()throws  -> UInt64  {
    return try  FfiConverterUInt64.lift(try rustCallWithError(FfiConverterTypeFfiError_lift) {
    uniffi_cera_ffi_fn_method_bundlerepo_cache_size(
            self.uniffiCloneHandle(),$0
    )
})
}
    
    /**
     * Wipe every file the repo has cached, leaving `store_dir`
     * itself in place so subsequent downloads land in the same
     * path. Idempotent — calling on an empty repo or non-existent
     * `store_dir` is a no-op success.
     *
     * Mobile apps trigger this from a "Clear downloaded models"
     * settings action. Caller is responsible for serializing
     * against in-flight downloads — typically trivial since the
     * action is user-driven.
     */
open func clearCache()throws   {try rustCallWithError(FfiConverterTypeFfiError_lift) {
    uniffi_cera_ffi_fn_method_bundlerepo_clear_cache(
            self.uniffiCloneHandle(),$0
    )
}
}
    
    /**
     * The directory this repo caches bundles under. Matches what was
     * passed to [`BundleRepo::new`] / [`BundleRepo::with_progress`],
     * useful for log / telemetry.
     */
open func storeDir() -> String  {
    return try!  FfiConverterString.lift(try! rustCall() {
    uniffi_cera_ffi_fn_method_bundlerepo_store_dir(
            self.uniffiCloneHandle(),$0
    )
})
}
    

    
}


#if swift(>=5.8)
@_documentation(visibility: private)
#endif
public struct FfiConverterTypeBundleRepo: FfiConverter {
    typealias FfiType = UInt64
    typealias SwiftType = BundleRepo

    public static func lift(_ handle: UInt64) throws -> BundleRepo {
        return BundleRepo(unsafeFromHandle: handle)
    }

    public static func lower(_ value: BundleRepo) -> UInt64 {
        return value.uniffiCloneHandle()
    }

    public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> BundleRepo {
        let handle: UInt64 = try readInt(&buf)
        return try lift(handle)
    }

    public static func write(_ value: BundleRepo, into buf: inout [UInt8]) {
        writeInt(&buf, lower(value))
    }
}


#if swift(>=5.8)
@_documentation(visibility: private)
#endif
public func FfiConverterTypeBundleRepo_lift(_ handle: UInt64) throws -> BundleRepo {
    return try FfiConverterTypeBundleRepo.lift(handle)
}

#if swift(>=5.8)
@_documentation(visibility: private)
#endif
public func FfiConverterTypeBundleRepo_lower(_ value: BundleRepo) -> UInt64 {
    return FfiConverterTypeBundleRepo.lower(value)
}






/**
 * Owning handle to a loaded model. Mirrors [`cera::CeraEngine`];
 * `#[uniffi::Object]` requires `Arc<Self>` wrapping which matches how
 * the underlying engine is already used internally.
 */
public protocol CeraEngineProtocol: AnyObject, Sendable {
    
    /**
     * Render the model's chat template against a sequence of
     * `ChatMessage`s. `add_generation_prompt = true` appends the
     * model's "now it's the assistant's turn" suffix (typical when
     * driving an interactive chat); `false` produces a transcript
     * the model can keep continuing.
     *
     * Returns [`FfiError::Backend`] if the model has no chat
     * template (check [`CeraEngine::has_chat_template`] first) or
     * if the template fails to render against the supplied messages.
     */
    func applyChatTemplate(messages: [ChatMessage], addGenerationPrompt: Bool) throws  -> String
    
    /**
     * Beginning-of-sequence token ID, if the model has one.
     * LLaMA-family models typically do; some don't. Honor
     * [`ModelMetadata::add_bos_token`] when deciding whether to
     * prepend it manually to a prompt.
     */
    func bosToken()  -> UInt32?
    
    /**
     * What this model accepts as input / emits as output. Derived at
     * load time from the manifest's `inference_type`.
     */
    func capabilities()  -> ModalityCapabilities
    
    /**
     * Resolved context-window size (KV cache cap) the engine was
     * configured with. Mirrors the `context_size` field of the
     * [`EngineConfig`] passed to `from_path` / `from_bundle_id`,
     * with the `0` → `model.max_seq_len` defaulting already
     * applied so callers always see a meaningful number rather
     * than the internal `usize::MAX` sentinel.
     *
     * Note this is the **engine-level** requested cap, not a
     * per-session ceiling. cera core clamps the model's
     * `max_seq_len` at load time to `min(requested_context,
     * gguf_max_seq_len)` (see `cera/src/model/lfm2.rs`), so
     * [`Self::metadata`]`.max_seq_len` is already the effective
     * ceiling for any session built from this engine — `context_size`
     * is informational ("what cap did this engine load with?")
     * rather than a value callers should `min(...)` against.
     */
    func contextSize()  -> UInt64
    
    /**
     * Decode token IDs back to text. Out-of-vocab IDs are silently
     * skipped (omitted from the decoded output) — `BpeTokenizer::decode`
     * only appends bytes for IDs it has in `vocab.get(id)`. No
     * substitution glyph, no error. Callers that want to detect
     * invalid IDs should validate against `vocab_size()` first.
     */
    func decodeTokens(tokens: [UInt32])  -> String
    
    /**
     * Encode `text` into token IDs using the model's BPE tokenizer.
     * Empty input returns an empty vec.
     */
    func encodeText(text: String)  -> [UInt32]
    
    /**
     * End-of-sequence / end-of-text token ID, if the model has one.
     * Used as a default stop-token by the sampler; callers can also
     * pass it explicitly in [`GenerateOpts::stop_tokens`].
     */
    func eosToken()  -> UInt32?
    
    /**
     * `true` if the model's tokenizer carries a chat template (a
     * minijinja string from GGUF metadata). Foreign callers should
     * check this before calling [`CeraEngine::apply_chat_template`].
     */
    func hasChatTemplate()  -> Bool
    
    /**
     * `true` when `id` is registered as a control or user-defined
     * special token in the model's GGUF metadata
     * (`tokenizer.ggml.token_type` types `3` / `4`). Useful for
     * output filtering — e.g. dropping `<|im_end|>` from streamed
     * tokens before rendering them to a UI — and for token-class
     * classification in analysis tools.
     *
     * Out-of-range IDs (>= vocab size) and regular vocab tokens
     * both return `false`. Companion to [`Self::special_token_id`]
     * which goes the other direction (name → ID).
     */
    func isSpecialToken(id: UInt32)  -> Bool
    
    /**
     * Short summary of the loaded model (architecture, vocab size,
     * max context, etc.). Returns a `Clone` of the stored metadata.
     */
    func metadata()  -> ModelMetadata
    
    /**
     * Open a new [`Session`] sharing this engine's model + tokenizer
     * by `Arc` clone. The returned session outlives `&self`; the
     * engine keeps the shared state live for every session it hands
     * out. Cheap — no model load, just config + state allocation.
     */
    func newSession(config: SessionConfig)  -> Session
    
    /**
     * Look up a special token by name (e.g. `<|im_start|>`,
     * `<|im_end|>`, `<|tool_call|>`). Returns `None` if the token
     * isn't defined in the tokenizer's vocab.
     */
    func specialTokenId(name: String)  -> UInt32?
    
    /**
     * Transcribe mono `f32` PCM audio (normalized to roughly `[-1.0, 1.0]`) to text using the
     * model's trained `"Perform ASR."` chat mode. `sample_rate` must match the audio encoder's
     * expected rate (resample beforehand if needed). Requires an audio-capable bundle; a text-only
     * model returns an [`FfiError`] for unsupported modality.
     *
     * Blocking: runs a full prefill + greedy decode. Foreign async runtimes should wrap the call in
     * `spawn_blocking` / its equivalent.
     */
    func transcribe(pcm: [Float], sampleRate: UInt32) throws  -> String
    
    /**
     * Total vocabulary size — the number of distinct token IDs the
     * model can emit. Sourced from the model's config (matches
     * [`ModelMetadata::vocab_size`]) rather than the tokenizer's
     * own count: in healthy models they match, but the model's
     * config is the authoritative range for valid logit indices.
     */
    func vocabSize()  -> UInt32
    
}
/**
 * Owning handle to a loaded model. Mirrors [`cera::CeraEngine`];
 * `#[uniffi::Object]` requires `Arc<Self>` wrapping which matches how
 * the underlying engine is already used internally.
 */
open class CeraEngine: CeraEngineProtocol, @unchecked Sendable {
    fileprivate let handle: UInt64

    /// Used to instantiate a [FFIObject] without an actual handle, for fakes in tests, mostly.
#if swift(>=5.8)
    @_documentation(visibility: private)
#endif
    public struct NoHandle {
        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`.
#if swift(>=5.8)
    @_documentation(visibility: private)
#endif
    required public init(unsafeFromHandle handle: UInt64) {
        self.handle = handle
    }

    // This constructor can be used to instantiate a fake object.
    // - Parameter noHandle: 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 handle the FFI lower functions will crash.
#if swift(>=5.8)
    @_documentation(visibility: private)
#endif
    public init(noHandle: NoHandle) {
        self.handle = 0
    }

#if swift(>=5.8)
    @_documentation(visibility: private)
#endif
    public func uniffiCloneHandle() -> UInt64 {
        return try! rustCall { uniffi_cera_ffi_fn_clone_ceraengine(self.handle, $0) }
    }
    // No primary constructor declared for this class.

    deinit {
        if handle == 0 {
            // Mock objects have handle=0 don't try to free them
            return
        }

        try! rustCall { uniffi_cera_ffi_fn_free_ceraengine(handle, $0) }
    }

    
    /**
     * Load a model by LeapBundles ID + quantization selector, e.g.
     * `from_bundle_id("LFM2-1.2B-GGUF", "Q4_0", config)`. Resolves
     * to the matching `<bundle_id>/<quant>.json` manifest under
     * `huggingface.co/LiquidAI/LeapBundles` and downloads whatever
     * isn't already in `config.bundle_repo`'s on-disk cache.
     *
     * `config.bundle_repo` must be set; otherwise this returns an
     * [`FfiError::Backend`] telling the caller to construct a
     * [`BundleRepo`] and attach it. Idempotent across calls — the
     * repo's cache deduplicates subsequent downloads.
     *
     * Blocking: this call fetches over the network on first run +
     * opens / parses the GGUF. Foreign async runtimes should wrap
     * the call in `spawn_blocking` / its equivalent. (An async
     * counterpart matching `generate_async` could be added later;
     * not in this PR.)
     */
public static func fromBundleId(bundleId: String, quant: String, config: EngineConfig)throws  -> CeraEngine  {
    return try  FfiConverterTypeCeraEngine_lift(try rustCallWithError(FfiConverterTypeFfiError_lift) {
    uniffi_cera_ffi_fn_constructor_ceraengine_from_bundle_id(
        FfiConverterString.lower(bundleId),
        FfiConverterString.lower(quant),
        FfiConverterTypeEngineConfig_lower(config),$0
    )
})
}
    
    /**
     * Async variant of [`CeraEngine::from_bundle_id`] — offloads the
     * manifest + GGUF download and the engine construction onto a
     * tokio blocking worker so the caller's async context isn't
     * stalled. Foreign async runtimes (Kotlin coroutines, Swift
     * `async`, Python `asyncio`) `.await` it directly.
     *
     * `config.bundle_repo` must be set (same constraint as the sync
     * twin); construct a [`BundleRepo`] rooted at a persistent cache
     * directory and attach it to the config before calling.
     *
     * Cancellation semantics (weaker than [`Session::generate_async`]):
     * dropping the returned future drops the `AbortOnDrop` guard,
     * which calls `AbortHandle::abort` on the spawned task. That
     * cancels the task if it's still queued on tokio's blocking
     * pool, so a not-yet-started download never runs. But if the
     * task has started, abort is a no-op — the download is a
     * `reqwest::blocking` call with no cooperative cancel point,
     * and cera's engine-construction code (tokenizer build, model
     * load, KV alloc) also isn't interruptible. In that case the
     * task runs to completion and the engine is constructed then
     * dropped; the downloaded bundle stays cached, so the caller's
     * next attempt starts from that cache hit. Bandwidth isn't
     * wasted, it's just shifted.
     *
     * `JoinError` from a panicking blocking closure surfaces as
     * [`FfiError::Backend`] with a diagnostic prefix, same as
     * [`Session::generate_async`].
     */
public static func fromBundleIdAsync(bundleId: String, quant: String, config: EngineConfig)async throws  -> CeraEngine  {
    return
        try  await uniffiRustCallAsync(
            rustFutureFunc: {
                uniffi_cera_ffi_fn_constructor_ceraengine_from_bundle_id_async(FfiConverterString.lower(bundleId),FfiConverterString.lower(quant),FfiConverterTypeEngineConfig_lower(config)
                )
            },
            pollFunc: ffi_cera_ffi_rust_future_poll_u64,
            completeFunc: ffi_cera_ffi_rust_future_complete_u64,
            freeFunc: ffi_cera_ffi_rust_future_free_u64,
            liftFunc: FfiConverterTypeCeraEngine_lift,
            errorHandler: FfiConverterTypeFfiError_lift
        )
}
    
    /**
     * Load a model from a local filesystem path. Accepts the same
     * inputs as the native [`cera::CeraEngine::from_path`]: a bare
     * `.gguf`, a LeapBundles `.json` manifest, or a directory
     * containing exactly one `.json` manifest.
     *
     * If the manifest carries `http(s)://` URLs for its files,
     * `config.bundle_repo` must be set — otherwise those URLs fail
     * to resolve. For a pure-local workflow (bundle already on
     * disk) leave `bundle_repo = None`.
     */
public static func fromPath(path: String, config: EngineConfig)throws  -> CeraEngine  {
    return try  FfiConverterTypeCeraEngine_lift(try rustCallWithError(FfiConverterTypeFfiError_lift) {
    uniffi_cera_ffi_fn_constructor_ceraengine_from_path(
        FfiConverterString.lower(path),
        FfiConverterTypeEngineConfig_lower(config),$0
    )
})
}
    

    
    /**
     * Render the model's chat template against a sequence of
     * `ChatMessage`s. `add_generation_prompt = true` appends the
     * model's "now it's the assistant's turn" suffix (typical when
     * driving an interactive chat); `false` produces a transcript
     * the model can keep continuing.
     *
     * Returns [`FfiError::Backend`] if the model has no chat
     * template (check [`CeraEngine::has_chat_template`] first) or
     * if the template fails to render against the supplied messages.
     */
open func applyChatTemplate(messages: [ChatMessage], addGenerationPrompt: Bool)throws  -> String  {
    return try  FfiConverterString.lift(try rustCallWithError(FfiConverterTypeFfiError_lift) {
    uniffi_cera_ffi_fn_method_ceraengine_apply_chat_template(
            self.uniffiCloneHandle(),
        FfiConverterSequenceTypeChatMessage.lower(messages),
        FfiConverterBool.lower(addGenerationPrompt),$0
    )
})
}
    
    /**
     * Beginning-of-sequence token ID, if the model has one.
     * LLaMA-family models typically do; some don't. Honor
     * [`ModelMetadata::add_bos_token`] when deciding whether to
     * prepend it manually to a prompt.
     */
open func bosToken() -> UInt32?  {
    return try!  FfiConverterOptionUInt32.lift(try! rustCall() {
    uniffi_cera_ffi_fn_method_ceraengine_bos_token(
            self.uniffiCloneHandle(),$0
    )
})
}
    
    /**
     * What this model accepts as input / emits as output. Derived at
     * load time from the manifest's `inference_type`.
     */
open func capabilities() -> ModalityCapabilities  {
    return try!  FfiConverterTypeModalityCapabilities_lift(try! rustCall() {
    uniffi_cera_ffi_fn_method_ceraengine_capabilities(
            self.uniffiCloneHandle(),$0
    )
})
}
    
    /**
     * Resolved context-window size (KV cache cap) the engine was
     * configured with. Mirrors the `context_size` field of the
     * [`EngineConfig`] passed to `from_path` / `from_bundle_id`,
     * with the `0` → `model.max_seq_len` defaulting already
     * applied so callers always see a meaningful number rather
     * than the internal `usize::MAX` sentinel.
     *
     * Note this is the **engine-level** requested cap, not a
     * per-session ceiling. cera core clamps the model's
     * `max_seq_len` at load time to `min(requested_context,
     * gguf_max_seq_len)` (see `cera/src/model/lfm2.rs`), so
     * [`Self::metadata`]`.max_seq_len` is already the effective
     * ceiling for any session built from this engine — `context_size`
     * is informational ("what cap did this engine load with?")
     * rather than a value callers should `min(...)` against.
     */
open func contextSize() -> UInt64  {
    return try!  FfiConverterUInt64.lift(try! rustCall() {
    uniffi_cera_ffi_fn_method_ceraengine_context_size(
            self.uniffiCloneHandle(),$0
    )
})
}
    
    /**
     * Decode token IDs back to text. Out-of-vocab IDs are silently
     * skipped (omitted from the decoded output) — `BpeTokenizer::decode`
     * only appends bytes for IDs it has in `vocab.get(id)`. No
     * substitution glyph, no error. Callers that want to detect
     * invalid IDs should validate against `vocab_size()` first.
     */
open func decodeTokens(tokens: [UInt32]) -> String  {
    return try!  FfiConverterString.lift(try! rustCall() {
    uniffi_cera_ffi_fn_method_ceraengine_decode_tokens(
            self.uniffiCloneHandle(),
        FfiConverterSequenceUInt32.lower(tokens),$0
    )
})
}
    
    /**
     * Encode `text` into token IDs using the model's BPE tokenizer.
     * Empty input returns an empty vec.
     */
open func encodeText(text: String) -> [UInt32]  {
    return try!  FfiConverterSequenceUInt32.lift(try! rustCall() {
    uniffi_cera_ffi_fn_method_ceraengine_encode_text(
            self.uniffiCloneHandle(),
        FfiConverterString.lower(text),$0
    )
})
}
    
    /**
     * End-of-sequence / end-of-text token ID, if the model has one.
     * Used as a default stop-token by the sampler; callers can also
     * pass it explicitly in [`GenerateOpts::stop_tokens`].
     */
open func eosToken() -> UInt32?  {
    return try!  FfiConverterOptionUInt32.lift(try! rustCall() {
    uniffi_cera_ffi_fn_method_ceraengine_eos_token(
            self.uniffiCloneHandle(),$0
    )
})
}
    
    /**
     * `true` if the model's tokenizer carries a chat template (a
     * minijinja string from GGUF metadata). Foreign callers should
     * check this before calling [`CeraEngine::apply_chat_template`].
     */
open func hasChatTemplate() -> Bool  {
    return try!  FfiConverterBool.lift(try! rustCall() {
    uniffi_cera_ffi_fn_method_ceraengine_has_chat_template(
            self.uniffiCloneHandle(),$0
    )
})
}
    
    /**
     * `true` when `id` is registered as a control or user-defined
     * special token in the model's GGUF metadata
     * (`tokenizer.ggml.token_type` types `3` / `4`). Useful for
     * output filtering — e.g. dropping `<|im_end|>` from streamed
     * tokens before rendering them to a UI — and for token-class
     * classification in analysis tools.
     *
     * Out-of-range IDs (>= vocab size) and regular vocab tokens
     * both return `false`. Companion to [`Self::special_token_id`]
     * which goes the other direction (name → ID).
     */
open func isSpecialToken(id: UInt32) -> Bool  {
    return try!  FfiConverterBool.lift(try! rustCall() {
    uniffi_cera_ffi_fn_method_ceraengine_is_special_token(
            self.uniffiCloneHandle(),
        FfiConverterUInt32.lower(id),$0
    )
})
}
    
    /**
     * Short summary of the loaded model (architecture, vocab size,
     * max context, etc.). Returns a `Clone` of the stored metadata.
     */
open func metadata() -> ModelMetadata  {
    return try!  FfiConverterTypeModelMetadata_lift(try! rustCall() {
    uniffi_cera_ffi_fn_method_ceraengine_metadata(
            self.uniffiCloneHandle(),$0
    )
})
}
    
    /**
     * Open a new [`Session`] sharing this engine's model + tokenizer
     * by `Arc` clone. The returned session outlives `&self`; the
     * engine keeps the shared state live for every session it hands
     * out. Cheap — no model load, just config + state allocation.
     */
open func newSession(config: SessionConfig) -> Session  {
    return try!  FfiConverterTypeSession_lift(try! rustCall() {
    uniffi_cera_ffi_fn_method_ceraengine_new_session(
            self.uniffiCloneHandle(),
        FfiConverterTypeSessionConfig_lower(config),$0
    )
})
}
    
    /**
     * Look up a special token by name (e.g. `<|im_start|>`,
     * `<|im_end|>`, `<|tool_call|>`). Returns `None` if the token
     * isn't defined in the tokenizer's vocab.
     */
open func specialTokenId(name: String) -> UInt32?  {
    return try!  FfiConverterOptionUInt32.lift(try! rustCall() {
    uniffi_cera_ffi_fn_method_ceraengine_special_token_id(
            self.uniffiCloneHandle(),
        FfiConverterString.lower(name),$0
    )
})
}
    
    /**
     * Transcribe mono `f32` PCM audio (normalized to roughly `[-1.0, 1.0]`) to text using the
     * model's trained `"Perform ASR."` chat mode. `sample_rate` must match the audio encoder's
     * expected rate (resample beforehand if needed). Requires an audio-capable bundle; a text-only
     * model returns an [`FfiError`] for unsupported modality.
     *
     * Blocking: runs a full prefill + greedy decode. Foreign async runtimes should wrap the call in
     * `spawn_blocking` / its equivalent.
     */
open func transcribe(pcm: [Float], sampleRate: UInt32)throws  -> String  {
    return try  FfiConverterString.lift(try rustCallWithError(FfiConverterTypeFfiError_lift) {
    uniffi_cera_ffi_fn_method_ceraengine_transcribe(
            self.uniffiCloneHandle(),
        FfiConverterSequenceFloat.lower(pcm),
        FfiConverterUInt32.lower(sampleRate),$0
    )
})
}
    
    /**
     * Total vocabulary size — the number of distinct token IDs the
     * model can emit. Sourced from the model's config (matches
     * [`ModelMetadata::vocab_size`]) rather than the tokenizer's
     * own count: in healthy models they match, but the model's
     * config is the authoritative range for valid logit indices.
     */
open func vocabSize() -> UInt32  {
    return try!  FfiConverterUInt32.lift(try! rustCall() {
    uniffi_cera_ffi_fn_method_ceraengine_vocab_size(
            self.uniffiCloneHandle(),$0
    )
})
}
    

    
}


#if swift(>=5.8)
@_documentation(visibility: private)
#endif
public struct FfiConverterTypeCeraEngine: FfiConverter {
    typealias FfiType = UInt64
    typealias SwiftType = CeraEngine

    public static func lift(_ handle: UInt64) throws -> CeraEngine {
        return CeraEngine(unsafeFromHandle: handle)
    }

    public static func lower(_ value: CeraEngine) -> UInt64 {
        return value.uniffiCloneHandle()
    }

    public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> CeraEngine {
        let handle: UInt64 = try readInt(&buf)
        return try lift(handle)
    }

    public static func write(_ value: CeraEngine, into buf: inout [UInt8]) {
        writeInt(&buf, lower(value))
    }
}


#if swift(>=5.8)
@_documentation(visibility: private)
#endif
public func FfiConverterTypeCeraEngine_lift(_ handle: UInt64) throws -> CeraEngine {
    return try FfiConverterTypeCeraEngine.lift(handle)
}

#if swift(>=5.8)
@_documentation(visibility: private)
#endif
public func FfiConverterTypeCeraEngine_lower(_ value: CeraEngine) -> UInt64 {
    return FfiConverterTypeCeraEngine.lower(value)
}






/**
 * Foreign-trait callback for download progress events from
 * [`BundleRepo::with_progress`]. Implementers (Kotlin class, Swift
 * class, Python subclass) drive a progress UI from these events.
 *
 * All methods are required from foreign implementations (UniFFI
 * 0.31 foreign traits don't carry Rust default-impl fallbacks).
 *
 * Threading: `on_progress` is invoked from the thread driving the
 * download. For sync `from_bundle_id` that's the caller's thread;
 * for `from_bundle_id_async` it's a tokio blocking worker. If your
 * progress UI requires marshalling onto a UI thread (`@MainActor`,
 * `runOnUiThread`, etc.), the implementer is responsible for the
 * dispatch.
 */
public protocol DownloadProgressSink: AnyObject, Sendable {
    
    /**
     * Called periodically during a download. `bytes_downloaded` is
     * monotonic across the same call's stream; `total_bytes` is the
     * `Content-Length` reported by the server (may be `None` for
     * chunked-transfer responses or when HEAD didn't surface a
     * length). Same `url` value across all calls for one download
     * — pattern-match on it to drive a per-file UI within a
     * multi-file bundle download.
     *
     * Throttled by `cera-core` to ~256 KB granularity + one final
     * callback at end-of-stream so the consumer always sees the
     * final byte count.
     */
    func onProgress(url: String, bytesDownloaded: UInt64, totalBytes: UInt64?) 
    
}
/**
 * Foreign-trait callback for download progress events from
 * [`BundleRepo::with_progress`]. Implementers (Kotlin class, Swift
 * class, Python subclass) drive a progress UI from these events.
 *
 * All methods are required from foreign implementations (UniFFI
 * 0.31 foreign traits don't carry Rust default-impl fallbacks).
 *
 * Threading: `on_progress` is invoked from the thread driving the
 * download. For sync `from_bundle_id` that's the caller's thread;
 * for `from_bundle_id_async` it's a tokio blocking worker. If your
 * progress UI requires marshalling onto a UI thread (`@MainActor`,
 * `runOnUiThread`, etc.), the implementer is responsible for the
 * dispatch.
 */
open class DownloadProgressSinkImpl: DownloadProgressSink, @unchecked Sendable {
    fileprivate let handle: UInt64

    /// Used to instantiate a [FFIObject] without an actual handle, for fakes in tests, mostly.
#if swift(>=5.8)
    @_documentation(visibility: private)
#endif
    public struct NoHandle {
        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`.
#if swift(>=5.8)
    @_documentation(visibility: private)
#endif
    required public init(unsafeFromHandle handle: UInt64) {
        self.handle = handle
    }

    // This constructor can be used to instantiate a fake object.
    // - Parameter noHandle: 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 handle the FFI lower functions will crash.
#if swift(>=5.8)
    @_documentation(visibility: private)
#endif
    public init(noHandle: NoHandle) {
        self.handle = 0
    }

#if swift(>=5.8)
    @_documentation(visibility: private)
#endif
    public func uniffiCloneHandle() -> UInt64 {
        return try! rustCall { uniffi_cera_ffi_fn_clone_downloadprogresssink(self.handle, $0) }
    }
    // No primary constructor declared for this class.

    deinit {
        if handle == 0 {
            // Mock objects have handle=0 don't try to free them
            return
        }

        try! rustCall { uniffi_cera_ffi_fn_free_downloadprogresssink(handle, $0) }
    }

    

    
    /**
     * Called periodically during a download. `bytes_downloaded` is
     * monotonic across the same call's stream; `total_bytes` is the
     * `Content-Length` reported by the server (may be `None` for
     * chunked-transfer responses or when HEAD didn't surface a
     * length). Same `url` value across all calls for one download
     * — pattern-match on it to drive a per-file UI within a
     * multi-file bundle download.
     *
     * Throttled by `cera-core` to ~256 KB granularity + one final
     * callback at end-of-stream so the consumer always sees the
     * final byte count.
     */
open func onProgress(url: String, bytesDownloaded: UInt64, totalBytes: UInt64?)  {try! rustCall() {
    uniffi_cera_ffi_fn_method_downloadprogresssink_on_progress(
            self.uniffiCloneHandle(),
        FfiConverterString.lower(url),
        FfiConverterUInt64.lower(bytesDownloaded),
        FfiConverterOptionUInt64.lower(totalBytes),$0
    )
}
}
    

    
}



// Put the implementation in a struct so we don't pollute the top-level namespace
fileprivate struct UniffiCallbackInterfaceDownloadProgressSink {

    // Create the VTable using a series of closures.
    // Swift automatically converts these into C callback functions.
    //
    // Store the vtable directly.
    static let vtable: UniffiVTableCallbackInterfaceDownloadProgressSink = UniffiVTableCallbackInterfaceDownloadProgressSink(
        uniffiFree: { (uniffiHandle: UInt64) -> () in
            do {
                try FfiConverterTypeDownloadProgressSink.handleMap.remove(handle: uniffiHandle)
            } catch {
                print("Uniffi callback interface DownloadProgressSink: handle missing in uniffiFree")
            }
        },
        uniffiClone: { (uniffiHandle: UInt64) -> UInt64 in
            do {
                return try FfiConverterTypeDownloadProgressSink.handleMap.clone(handle: uniffiHandle)
            } catch {
                fatalError("Uniffi callback interface DownloadProgressSink: handle missing in uniffiClone")
            }
        },
        onProgress: { (
            uniffiHandle: UInt64,
            url: RustBuffer,
            bytesDownloaded: UInt64,
            totalBytes: RustBuffer,
            uniffiOutReturn: UnsafeMutableRawPointer,
            uniffiCallStatus: UnsafeMutablePointer<RustCallStatus>
        ) in
            let makeCall = {
                () throws -> () in
                guard let uniffiObj = try? FfiConverterTypeDownloadProgressSink.handleMap.get(handle: uniffiHandle) else {
                    throw UniffiInternalError.unexpectedStaleHandle
                }
                return uniffiObj.onProgress(
                     url: try FfiConverterString.lift(url),
                     bytesDownloaded: try FfiConverterUInt64.lift(bytesDownloaded),
                     totalBytes: try FfiConverterOptionUInt64.lift(totalBytes)
                )
            }

            
            let writeReturn = { () }
            uniffiTraitInterfaceCall(
                callStatus: uniffiCallStatus,
                makeCall: makeCall,
                writeReturn: writeReturn
            )
        }
    )

    // Rust stores this pointer for future callback invocations, so it must live
    // for the process lifetime (not just for the init function call).
    //
    // `nonisolated(unsafe)` is needed under Swift 6 strict concurrency.
    // This is safe because the pointee is initialized once during static init
    // and never mutated by either side of the FFI.  Its fields are C function pointers.
    nonisolated(unsafe) static let vtablePtr: UnsafePointer<UniffiVTableCallbackInterfaceDownloadProgressSink> = {
        let ptr = UnsafeMutablePointer<UniffiVTableCallbackInterfaceDownloadProgressSink>.allocate(capacity: 1)
        ptr.initialize(to: vtable)
        return UnsafePointer(ptr)
    }()
}

private func uniffiCallbackInitDownloadProgressSink() {
    uniffi_cera_ffi_fn_init_callback_vtable_downloadprogresssink(UniffiCallbackInterfaceDownloadProgressSink.vtablePtr)
}

#if swift(>=5.8)
@_documentation(visibility: private)
#endif
public struct FfiConverterTypeDownloadProgressSink: FfiConverter {
    fileprivate static let handleMap = UniffiHandleMap<DownloadProgressSink>()

    typealias FfiType = UInt64
    typealias SwiftType = DownloadProgressSink

    public static func lift(_ handle: UInt64) throws -> DownloadProgressSink {
        if ((handle & 1) == 0) {
            // Rust-generated handle, construct a new class that uses the handle to implement the
            // interface
            return DownloadProgressSinkImpl(unsafeFromHandle: handle)
        } else {
            // Swift-generated handle, get the object from the handle map
            return try handleMap.remove(handle: handle)
        }
    }

    public static func lower(_ value: DownloadProgressSink) -> UInt64 {
         if let rustImpl = value as? DownloadProgressSinkImpl {
             // Rust-implemented object.  Clone the handle and return it
            return rustImpl.uniffiCloneHandle()
         } else {
            // Swift object, generate a new vtable handle and return that.
            return handleMap.insert(obj: value)
         }
    }

    public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> DownloadProgressSink {
        let handle: UInt64 = try readInt(&buf)
        return try lift(handle)
    }

    public static func write(_ value: DownloadProgressSink, into buf: inout [UInt8]) {
        writeInt(&buf, lower(value))
    }
}


#if swift(>=5.8)
@_documentation(visibility: private)
#endif
public func FfiConverterTypeDownloadProgressSink_lift(_ handle: UInt64) throws -> DownloadProgressSink {
    return try FfiConverterTypeDownloadProgressSink.lift(handle)
}

#if swift(>=5.8)
@_documentation(visibility: private)
#endif
public func FfiConverterTypeDownloadProgressSink_lower(_ value: DownloadProgressSink) -> UInt64 {
    return FfiConverterTypeDownloadProgressSink.lower(value)
}






/**
 * A loaded LoRA adapter, ready to attach to a [`Session`] via
 * [`Session::attach_lora`]. Load it once and share the handle across sessions —
 * it's reference-counted internally, so attaching to multiple sessions doesn't
 * re-parse or re-allocate the factors.
 */
public protocol LoraAdaptersProtocol: AnyObject, Sendable {
    
    /**
     * Number of `(layer, target)` low-rank deltas the adapter carries — for
     * diagnostics / logging.
     */
    func targetCount()  -> UInt32
    
}
/**
 * A loaded LoRA adapter, ready to attach to a [`Session`] via
 * [`Session::attach_lora`]. Load it once and share the handle across sessions —
 * it's reference-counted internally, so attaching to multiple sessions doesn't
 * re-parse or re-allocate the factors.
 */
open class LoraAdapters: LoraAdaptersProtocol, @unchecked Sendable {
    fileprivate let handle: UInt64

    /// Used to instantiate a [FFIObject] without an actual handle, for fakes in tests, mostly.
#if swift(>=5.8)
    @_documentation(visibility: private)
#endif
    public struct NoHandle {
        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`.
#if swift(>=5.8)
    @_documentation(visibility: private)
#endif
    required public init(unsafeFromHandle handle: UInt64) {
        self.handle = handle
    }

    // This constructor can be used to instantiate a fake object.
    // - Parameter noHandle: 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 handle the FFI lower functions will crash.
#if swift(>=5.8)
    @_documentation(visibility: private)
#endif
    public init(noHandle: NoHandle) {
        self.handle = 0
    }

#if swift(>=5.8)
    @_documentation(visibility: private)
#endif
    public func uniffiCloneHandle() -> UInt64 {
        return try! rustCall { uniffi_cera_ffi_fn_clone_loraadapters(self.handle, $0) }
    }
    // No primary constructor declared for this class.

    deinit {
        if handle == 0 {
            // Mock objects have handle=0 don't try to free them
            return
        }

        try! rustCall { uniffi_cera_ffi_fn_free_loraadapters(handle, $0) }
    }

    
    /**
     * Load a llama.cpp-format GGUF adapter (`convert_lora_to_gguf` output) from
     * a local path. `alpha` is read from the adapter's `adapter.lora.alpha`
     * metadata (missing ⇒ scale = 1).
     */
public static func fromGguf(path: String)throws  -> LoraAdapters  {
    return try  FfiConverterTypeLoraAdapters_lift(try rustCallWithError(FfiConverterTypeFfiError_lift) {
    uniffi_cera_ffi_fn_constructor_loraadapters_from_gguf(
        FfiConverterString.lower(path),$0
    )
})
}
    
    /**
     * Load a PEFT `.safetensors` adapter from a local path. PEFT stores `alpha`
     * in a sibling `adapter_config.json`, so pass it explicitly here (`None` ⇒
     * scale = 1, i.e. `alpha == rank`).
     */
public static func fromSafetensors(path: String, alpha: Float?)throws  -> LoraAdapters  {
    return try  FfiConverterTypeLoraAdapters_lift(try rustCallWithError(FfiConverterTypeFfiError_lift) {
    uniffi_cera_ffi_fn_constructor_loraadapters_from_safetensors(
        FfiConverterString.lower(path),
        FfiConverterOptionFloat.lower(alpha),$0
    )
})
}
    

    
    /**
     * Number of `(layer, target)` low-rank deltas the adapter carries — for
     * diagnostics / logging.
     */
open func targetCount() -> UInt32  {
    return try!  FfiConverterUInt32.lift(try! rustCall() {
    uniffi_cera_ffi_fn_method_loraadapters_target_count(
            self.uniffiCloneHandle(),$0
    )
})
}
    

    
}


#if swift(>=5.8)
@_documentation(visibility: private)
#endif
public struct FfiConverterTypeLoraAdapters: FfiConverter {
    typealias FfiType = UInt64
    typealias SwiftType = LoraAdapters

    public static func lift(_ handle: UInt64) throws -> LoraAdapters {
        return LoraAdapters(unsafeFromHandle: handle)
    }

    public static func lower(_ value: LoraAdapters) -> UInt64 {
        return value.uniffiCloneHandle()
    }

    public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> LoraAdapters {
        let handle: UInt64 = try readInt(&buf)
        return try lift(handle)
    }

    public static func write(_ value: LoraAdapters, into buf: inout [UInt8]) {
        writeInt(&buf, lower(value))
    }
}


#if swift(>=5.8)
@_documentation(visibility: private)
#endif
public func FfiConverterTypeLoraAdapters_lift(_ handle: UInt64) throws -> LoraAdapters {
    return try FfiConverterTypeLoraAdapters.lift(handle)
}

#if swift(>=5.8)
@_documentation(visibility: private)
#endif
public func FfiConverterTypeLoraAdapters_lower(_ value: LoraAdapters) -> UInt64 {
    return FfiConverterTypeLoraAdapters.lower(value)
}






/**
 * Streaming sink for decode output. Foreign callers implement this
 * trait (Kotlin class, Swift class, Python subclass) and pass an
 * `Arc<dyn ModalitySink>` to [`Session::generate_streaming`] to
 * receive tokens + audio frames + the finish reason as they happen.
 *
 * All methods are required from foreign implementations (UniFFI 0.28
 * foreign traits don't carry Rust's default-impl fallbacks). Callers
 * that don't care about a modality can provide an empty body.
 *
 * Threading: every method is invoked on the same Rust thread running
 * `generate` — the decode thread. If the foreign runtime requires
 * marshalling onto a different thread (e.g. Swift's `@MainActor`) it
 * is the implementer's responsibility to dispatch the call there.
 */
public protocol ModalitySink: AnyObject, Sendable {
    
    /**
     * Called with each chunk of generated token IDs. Ownership of the
     * `Vec<u32>` is transferred to the callback, so implementations
     * may retain or store it directly if needed — no clone required.
     */
    func onTextTokens(tokens: [UInt32]) 
    
    /**
     * Called with each chunk of generated PCM audio samples. Not
     * called for text-only models; LFM2-Audio-class models emit here.
     * The `sample_rate` is the model's native output rate (typically
     * 24000 for LFM2-Audio) and is stable across the whole generate
     * call.
     */
    func onAudioFrames(pcm: [Float], sampleRate: UInt32) 
    
    /**
     * Called exactly once per [`Session::generate_streaming`] call,
     * as the last thing before the wrapper returns. Fires for both
     * success (`MaxTokens`, `Stop`, `Cancelled`, `ContextFull`) and
     * failure paths: on error the wrapper synthesizes a
     * [`FinishReason::Error`] so foreign consumers have a reliable
     * end-of-stream signal regardless of how the call exits.
     */
    func onDone(reason: FinishReason) 
    
}
/**
 * Streaming sink for decode output. Foreign callers implement this
 * trait (Kotlin class, Swift class, Python subclass) and pass an
 * `Arc<dyn ModalitySink>` to [`Session::generate_streaming`] to
 * receive tokens + audio frames + the finish reason as they happen.
 *
 * All methods are required from foreign implementations (UniFFI 0.28
 * foreign traits don't carry Rust's default-impl fallbacks). Callers
 * that don't care about a modality can provide an empty body.
 *
 * Threading: every method is invoked on the same Rust thread running
 * `generate` — the decode thread. If the foreign runtime requires
 * marshalling onto a different thread (e.g. Swift's `@MainActor`) it
 * is the implementer's responsibility to dispatch the call there.
 */
open class ModalitySinkImpl: ModalitySink, @unchecked Sendable {
    fileprivate let handle: UInt64

    /// Used to instantiate a [FFIObject] without an actual handle, for fakes in tests, mostly.
#if swift(>=5.8)
    @_documentation(visibility: private)
#endif
    public struct NoHandle {
        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`.
#if swift(>=5.8)
    @_documentation(visibility: private)
#endif
    required public init(unsafeFromHandle handle: UInt64) {
        self.handle = handle
    }

    // This constructor can be used to instantiate a fake object.
    // - Parameter noHandle: 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 handle the FFI lower functions will crash.
#if swift(>=5.8)
    @_documentation(visibility: private)
#endif
    public init(noHandle: NoHandle) {
        self.handle = 0
    }

#if swift(>=5.8)
    @_documentation(visibility: private)
#endif
    public func uniffiCloneHandle() -> UInt64 {
        return try! rustCall { uniffi_cera_ffi_fn_clone_modalitysink(self.handle, $0) }
    }
    // No primary constructor declared for this class.

    deinit {
        if handle == 0 {
            // Mock objects have handle=0 don't try to free them
            return
        }

        try! rustCall { uniffi_cera_ffi_fn_free_modalitysink(handle, $0) }
    }

    

    
    /**
     * Called with each chunk of generated token IDs. Ownership of the
     * `Vec<u32>` is transferred to the callback, so implementations
     * may retain or store it directly if needed — no clone required.
     */
open func onTextTokens(tokens: [UInt32])  {try! rustCall() {
    uniffi_cera_ffi_fn_method_modalitysink_on_text_tokens(
            self.uniffiCloneHandle(),
        FfiConverterSequenceUInt32.lower(tokens),$0
    )
}
}
    
    /**
     * Called with each chunk of generated PCM audio samples. Not
     * called for text-only models; LFM2-Audio-class models emit here.
     * The `sample_rate` is the model's native output rate (typically
     * 24000 for LFM2-Audio) and is stable across the whole generate
     * call.
     */
open func onAudioFrames(pcm: [Float], sampleRate: UInt32)  {try! rustCall() {
    uniffi_cera_ffi_fn_method_modalitysink_on_audio_frames(
            self.uniffiCloneHandle(),
        FfiConverterSequenceFloat.lower(pcm),
        FfiConverterUInt32.lower(sampleRate),$0
    )
}
}
    
    /**
     * Called exactly once per [`Session::generate_streaming`] call,
     * as the last thing before the wrapper returns. Fires for both
     * success (`MaxTokens`, `Stop`, `Cancelled`, `ContextFull`) and
     * failure paths: on error the wrapper synthesizes a
     * [`FinishReason::Error`] so foreign consumers have a reliable
     * end-of-stream signal regardless of how the call exits.
     */
open func onDone(reason: FinishReason)  {try! rustCall() {
    uniffi_cera_ffi_fn_method_modalitysink_on_done(
            self.uniffiCloneHandle(),
        FfiConverterTypeFinishReason_lower(reason),$0
    )
}
}
    

    
}



// Put the implementation in a struct so we don't pollute the top-level namespace
fileprivate struct UniffiCallbackInterfaceModalitySink {

    // Create the VTable using a series of closures.
    // Swift automatically converts these into C callback functions.
    //
    // Store the vtable directly.
    static let vtable: UniffiVTableCallbackInterfaceModalitySink = UniffiVTableCallbackInterfaceModalitySink(
        uniffiFree: { (uniffiHandle: UInt64) -> () in
            do {
                try FfiConverterTypeModalitySink.handleMap.remove(handle: uniffiHandle)
            } catch {
                print("Uniffi callback interface ModalitySink: handle missing in uniffiFree")
            }
        },
        uniffiClone: { (uniffiHandle: UInt64) -> UInt64 in
            do {
                return try FfiConverterTypeModalitySink.handleMap.clone(handle: uniffiHandle)
            } catch {
                fatalError("Uniffi callback interface ModalitySink: handle missing in uniffiClone")
            }
        },
        onTextTokens: { (
            uniffiHandle: UInt64,
            tokens: RustBuffer,
            uniffiOutReturn: UnsafeMutableRawPointer,
            uniffiCallStatus: UnsafeMutablePointer<RustCallStatus>
        ) in
            let makeCall = {
                () throws -> () in
                guard let uniffiObj = try? FfiConverterTypeModalitySink.handleMap.get(handle: uniffiHandle) else {
                    throw UniffiInternalError.unexpectedStaleHandle
                }
                return uniffiObj.onTextTokens(
                     tokens: try FfiConverterSequenceUInt32.lift(tokens)
                )
            }

            
            let writeReturn = { () }
            uniffiTraitInterfaceCall(
                callStatus: uniffiCallStatus,
                makeCall: makeCall,
                writeReturn: writeReturn
            )
        },
        onAudioFrames: { (
            uniffiHandle: UInt64,
            pcm: RustBuffer,
            sampleRate: UInt32,
            uniffiOutReturn: UnsafeMutableRawPointer,
            uniffiCallStatus: UnsafeMutablePointer<RustCallStatus>
        ) in
            let makeCall = {
                () throws -> () in
                guard let uniffiObj = try? FfiConverterTypeModalitySink.handleMap.get(handle: uniffiHandle) else {
                    throw UniffiInternalError.unexpectedStaleHandle
                }
                return uniffiObj.onAudioFrames(
                     pcm: try FfiConverterSequenceFloat.lift(pcm),
                     sampleRate: try FfiConverterUInt32.lift(sampleRate)
                )
            }

            
            let writeReturn = { () }
            uniffiTraitInterfaceCall(
                callStatus: uniffiCallStatus,
                makeCall: makeCall,
                writeReturn: writeReturn
            )
        },
        onDone: { (
            uniffiHandle: UInt64,
            reason: RustBuffer,
            uniffiOutReturn: UnsafeMutableRawPointer,
            uniffiCallStatus: UnsafeMutablePointer<RustCallStatus>
        ) in
            let makeCall = {
                () throws -> () in
                guard let uniffiObj = try? FfiConverterTypeModalitySink.handleMap.get(handle: uniffiHandle) else {
                    throw UniffiInternalError.unexpectedStaleHandle
                }
                return uniffiObj.onDone(
                     reason: try FfiConverterTypeFinishReason_lift(reason)
                )
            }

            
            let writeReturn = { () }
            uniffiTraitInterfaceCall(
                callStatus: uniffiCallStatus,
                makeCall: makeCall,
                writeReturn: writeReturn
            )
        }
    )

    // Rust stores this pointer for future callback invocations, so it must live
    // for the process lifetime (not just for the init function call).
    //
    // `nonisolated(unsafe)` is needed under Swift 6 strict concurrency.
    // This is safe because the pointee is initialized once during static init
    // and never mutated by either side of the FFI.  Its fields are C function pointers.
    nonisolated(unsafe) static let vtablePtr: UnsafePointer<UniffiVTableCallbackInterfaceModalitySink> = {
        let ptr = UnsafeMutablePointer<UniffiVTableCallbackInterfaceModalitySink>.allocate(capacity: 1)
        ptr.initialize(to: vtable)
        return UnsafePointer(ptr)
    }()
}

private func uniffiCallbackInitModalitySink() {
    uniffi_cera_ffi_fn_init_callback_vtable_modalitysink(UniffiCallbackInterfaceModalitySink.vtablePtr)
}

#if swift(>=5.8)
@_documentation(visibility: private)
#endif
public struct FfiConverterTypeModalitySink: FfiConverter {
    fileprivate static let handleMap = UniffiHandleMap<ModalitySink>()

    typealias FfiType = UInt64
    typealias SwiftType = ModalitySink

    public static func lift(_ handle: UInt64) throws -> ModalitySink {
        if ((handle & 1) == 0) {
            // Rust-generated handle, construct a new class that uses the handle to implement the
            // interface
            return ModalitySinkImpl(unsafeFromHandle: handle)
        } else {
            // Swift-generated handle, get the object from the handle map
            return try handleMap.remove(handle: handle)
        }
    }

    public static func lower(_ value: ModalitySink) -> UInt64 {
         if let rustImpl = value as? ModalitySinkImpl {
             // Rust-implemented object.  Clone the handle and return it
            return rustImpl.uniffiCloneHandle()
         } else {
            // Swift object, generate a new vtable handle and return that.
            return handleMap.insert(obj: value)
         }
    }

    public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> ModalitySink {
        let handle: UInt64 = try readInt(&buf)
        return try lift(handle)
    }

    public static func write(_ value: ModalitySink, into buf: inout [UInt8]) {
        writeInt(&buf, lower(value))
    }
}


#if swift(>=5.8)
@_documentation(visibility: private)
#endif
public func FfiConverterTypeModalitySink_lift(_ handle: UInt64) throws -> ModalitySink {
    return try FfiConverterTypeModalitySink.lift(handle)
}

#if swift(>=5.8)
@_documentation(visibility: private)
#endif
public func FfiConverterTypeModalitySink_lower(_ value: ModalitySink) -> UInt64 {
    return FfiConverterTypeModalitySink.lower(value)
}






/**
 * Stateful inference handle. Wraps [`cera::Session`] behind a
 * `Mutex` so UniFFI's `Arc<Session>` shape works with methods that
 * need `&mut self` on the inner session (prefill, generate, reset).
 *
 * Call [`CeraEngine::new_session`] to open a session; the engine's
 * `Arc<Model>` and `Arc<BpeTokenizer>` are cloned into the new
 * session so it outlives the engine handle across FFI calls.
 */
public protocol SessionProtocol: AnyObject, Sendable {
    
    /**
     * Append PCM audio samples (mono `f32`, normalized to roughly
     * `[-1.0, 1.0]`) at `sample_rate` Hz. The audio is encoded via
     * the bundle's mmproj (`AudioEncoderWeights`) and prefilled
     * into the LLM as soft tokens — see
     * [`cera::Session::append_audio`] for the underlying flow.
     *
     * `CeraEngine::new_session` auto-attaches the encoder when the
     * loaded bundle's `inference_type == LlamaCppLfm2AudioV1` and
     * has `multimodal_projector` set in the manifest, so FFI
     * consumers don't need any separate "load encoder" call.
     * Bundles where the manifest omits `multimodal_projector`
     * silently end up with no encoder attached (no log). Bundles
     * where the file is named but fails to open or parse log a
     * `tracing::warn!` at `CeraEngine` construction. Both cases
     * surface here as a "no audio encoder attached" `Backend`
     * error.
     *
     * `sample_rate` must be 16000 — resampling is out of scope.
     * Callers should resample externally before passing samples in.
     *
     * **Marshaling cost**: UniFFI maps `Vec<f32>` to `List<Float>`
     * in Kotlin and `[Float]` in Swift. The Kotlin side boxes each
     * `Float` to `java.lang.Float`, a ~4× memory overhead vs the
     * underlying `f32` wire bytes — negligible for O(seconds ×
     * sample-rate) chunks but worth knowing if you're streaming
     * continuous audio in tight loops.
     *
     * Errors:
     * - `EmptyInput` either when `samples` is empty (fast-fail,
     * enforced here for parity with `append_text` /
     * `append_tokens`) **or** when the audio is too short to
     * produce any encoder frames (e.g. shorter than one
     * center-padded STFT window).
     * - `UnsupportedModality` if the loaded model's
     * [`ModalityCapabilities::audio_in`] is `false`.
     * - `Backend(...)` for sample-rate mismatch, encoder/LLM
     * `hidden_size` mismatch, or missing encoder. The latter
     * includes both "manifest didn't list a mmproj" (no warn
     * logged) and "mmproj listed but failed to open/parse"
     * (warn logged at `CeraEngine::from_path`).
     * - `ContextOverflow` / `Cancelled` propagate from the
     * underlying prefill.
     */
    func appendAudio(samples: [Float], sampleRate: UInt32) throws 
    
    /**
     * Append an encoded image (PNG / JPEG bytes, auto-detected) to the
     * context. The image is decoded, resized, normalized, and run
     * through the bundle's vision mmproj (`VisionEncoderWeights`), then
     * prefilled into the LLM as soft tokens — see
     * [`cera::Session::append_image`] for the underlying flow.
     *
     * `CeraEngine::new_session` auto-attaches the vision encoder when
     * the loaded bundle's `inference_type` is a VL type with
     * `multimodal_projector` set in the manifest, so FFI consumers
     * don't need a separate "load encoder" call. Bundles whose
     * manifest omits the mmproj end up with no encoder attached (no
     * log); bundles where it's named but fails to open/parse log a
     * `tracing::warn!` at `CeraEngine` construction. Both surface here
     * as a "no vision encoder attached" `Backend` error.
     *
     * `max_long_size` controls the per-call cap on the longest side of
     * the *encoded* image, with three cases distinguished so the
     * session default stays reachable through FFI:
     * - `None` — defer to the session default set via
     * [`Self::set_image_max_long_size`] (no cap if none was set).
     * - `Some(0)` — explicitly force *no cap* for this call, ignoring
     * the session default.
     * - `Some(n)` (`n > 0`) — cap this call at `n`, overriding the
     * session default.
     *
     * When a cap applies, the resize target is shrunk
     * (aspect-preserving) so its longer side is at most `n` pixels,
     * floored at one aligned patch block (so a very small `n` can still
     * round up to that minimum) — a quality/cost knob (smaller = fewer
     * image tokens, faster, less detail). It only shrinks (never
     * upscales) and takes precedence over the model's
     * minimum-resolution floor. The cap bounds the *encode*, not the
     * *decode* (a huge source image is still decoded, bounded by
     * internal limits).
     *
     * **Placement matters.** Prefer driving multimodal turns through
     * the chat template; calling this at the wrong stream position
     * (outside the model's image-marker envelope) leaves the LLM
     * unable to interpret the embeddings as visual content. See
     * [`cera::Session::append_image`] for the marker recipe.
     *
     * Errors (capability is checked before emptiness, matching core):
     * - `UnsupportedModality` if the loaded model's
     * [`ModalityCapabilities::image_in`] is `false`.
     * - `EmptyInput` when `bytes` is empty (on a VL session).
     * - `Backend(...)` for image decode failure, missing vision
     * encoder, or encoder/LLM `projection_dim` ≠ `hidden_size`
     * mismatch.
     * - `ContextOverflow` / `Cancelled` propagate from the
     * underlying prefill.
     */
    func appendImage(bytes: Data, maxLongSize: UInt32?) throws 
    
    /**
     * Append raw text to the context, running a prefill over just
     * the new tokens. `EmptyInput` error if `text` is empty.
     */
    func appendText(text: String) throws 
    
    /**
     * Append pre-tokenized IDs. Useful when the caller has its own
     * tokenizer + chat-template pipeline.
     */
    func appendTokens(tokens: [UInt32]) throws 
    
    /**
     * Attach a [`LoraAdapters`] to this session (generated as `attachLora` in
     * Swift/Kotlin — this is the engine's equivalent of a `setLoraAdapters`
     * call). It's applied to every subsequent forward pass — generation **and**
     * hidden-states extraction — until removed or replaced (hot-swap), and is
     * preserved across [`Self::reset`]. Returns [`FfiError::LoraParse`] if the
     * adapter's dimensions don't match the loaded model. Only affects tokens
     * processed after the call (doesn't retroactively re-adapt cached KV).
     */
    func attachLora(adapters: LoraAdapters) throws 
    
    /**
     * Signal in-flight `generate()` to exit with
     * `FinishReason::Cancelled` at the next between-token check.
     * Safe from any thread. No-op if no `generate()` is running.
     */
    func cancel() 
    
    /**
     * Capabilities reported by the loaded model. Cheap — reads a
     * cached copy, no lock.
     */
    func capabilities()  -> ModalityCapabilities
    
    /**
     * Clear the cancel flag without dropping any session state.
     * Use this after observing a cancellation signal — either
     * [`FfiError::Cancelled`] from `append_text` / `append_tokens`
     * / `append_audio` (mid-prefill cancellation surfaces
     * typed), or `finish_reason = "Cancelled"` on the
     * [`GenerateOutput`] returned from `generate` (cancellation
     * during decode is reported as an `Ok` with that finish
     * reason rather than an `Err`) — when you want to resume
     * work on the same session without losing the accumulated
     * KV cache.
     *
     * Compared to [`Self::reset`]:
     * - `clear_cancel`: keeps KV state + position + sampler
     * intact; only flips the cancel atomic back to `false`.
     * Use for "interrupted but continuing" flows.
     * - `reset`: drops KV cache + position + last logits +
     * re-seeds sampler. Use for "clear conversation" flows.
     *
     * Atomic-backed; no mutex acquire, infallible, safe from
     * any thread (mirrors the shape of [`Self::cancel`]).
     */
    func clearCancel() 
    
    /**
     * Run autoregressive decode and return all emitted tokens +
     * a summary. Synchronous — the call blocks until the decode
     * loop exits (`max_tokens`, EOS, `cancel()`, or error).
     *
     * For streaming (per-chunk delivery) and async, see the PR 4 /
     * PR 5 follow-ups in `cera-ffi/README.md`.
     */
    func generate(opts: GenerateOpts) throws  -> GenerateOutput
    
    /**
     * Async variant of [`Session::generate`] — runs buffered decode
     * (returning every emitted token + a summary) on a tokio blocking
     * worker so the caller's async context isn't stalled by the
     * synchronous decode loop.
     *
     * Cancellation: dropping the returned future (Kotlin coroutine
     * scope exit, Swift `Task.cancel`, Python `asyncio.Task.cancel`)
     * triggers both an abort of the queued `spawn_blocking` task (so
     * a not-yet-started decode never runs) and a
     * [`Session::cancel`] call (so an in-flight decode exits at its
     * next between-token check with [`FinishReason::Cancelled`]).
     * Either path releases the session mutex; subsequent calls see
     * a clean session. You can also call [`Session::cancel`]
     * directly from any thread to trigger the same in-flight exit
     * without dropping the future. See `AsyncCancelGuard` for the
     * full rationale.
     *
     * On error the wrapper performs the same poisoned-mutex handling
     * as sync [`Session::generate`]. `JoinError` from a panic in the
     * blocking closure surfaces as [`FfiError::Backend`] with a
     * diagnostic prefix.
     */
    func generateAsync(opts: GenerateOpts) async throws  -> GenerateOutput
    
    /**
     * Run autoregressive decode, streaming every token (and audio
     * frame, for audio-capable models) to a foreign [`ModalitySink`]
     * as soon as it's produced. Returns only a [`GenerateSummary`] —
     * token IDs are delivered through `sink.on_text_tokens`, not a
     * return value.
     *
     * Synchronous: the call blocks on the decode thread and each
     * `sink` method runs on that same thread before decoding
     * continues. For async, see PR 5 in `cera-ffi/README.md`.
     *
     * **Callback reentrancy — deadlock hazard.** The session mutex is
     * held for the entire call, and sink callbacks run while that
     * lock is held. Calling back into methods that also take the
     * mutex ([`Session::append_text`], [`Session::append_tokens`],
     * [`Session::generate`], [`Session::generate_streaming`],
     * [`Session::reset`]) from inside a sink method will deadlock.
     * [`Session::cancel`] and [`Session::position`] are atomic-backed
     * and safe to call from the sink or from any other thread.
     *
     * Cancellation: call [`Session::cancel`] from any thread (or from
     * inside a sink callback on this thread) to terminate the loop at
     * the next between-token check; `sink.on_done` fires with
     * [`FinishReason::Cancelled`].
     *
     * End-of-stream guarantee: `sink.on_done` fires exactly once per
     * call, even on error paths. If the underlying decode returns an
     * error before reaching its own `on_done` call (e.g.,
     * `EmptyInput` with no prefill logits), the wrapper synthesizes
     * a terminal `on_done(FinishReason::Error { message })` so
     * foreign consumers have a reliable end-of-stream signal
     * regardless of how the call exits.
     */
    func generateStreaming(opts: GenerateOpts, sink: ModalitySink) throws  -> GenerateSummary
    
    /**
     * Async variant of [`Session::generate_streaming`] — delivers
     * tokens and audio frames to the foreign [`ModalitySink`] as the
     * decode loop produces them, from within a blocking worker so
     * the caller's async runtime stays responsive.
     *
     * Sink callbacks run on the blocking worker thread that's
     * executing the decode — **not** on the caller's async thread.
     * The reentrancy hazard documented on
     * [`Session::generate_streaming`] still applies: sink callbacks
     * that call back into `append_text` / `generate*` / `reset` from
     * inside the session will deadlock on the session mutex.
     * [`Session::cancel`] and [`Session::position`] remain atomic-
     * backed and safe to invoke from any thread (including from
     * inside a callback).
     *
     * Cancellation: dropping the returned future fires the same
     * abort + [`Session::cancel`] pair as [`Session::generate_async`]
     * (see `AsyncCancelGuard`). For an in-flight decode, the loop
     * exits with [`FinishReason::Cancelled`] and the sink's `on_done`
     * fires on the blocking worker before the task completes —
     * foreign consumers get the terminal signal even though they've
     * already stopped awaiting. For a queued-but-not-started decode,
     * abort cancels the task without ever running the closure; no
     * sink callbacks fire for that case (the decode never began).
     */
    func generateStreamingAsync(opts: GenerateOpts, sink: ModalitySink) async throws  -> GenerateSummary
    
    /**
     * Whether a LoRA adapter is currently attached to this session.
     */
    func hasLora() throws  -> Bool
    
    /**
     * Model hidden dimension `D`. Reshape a raw `[T*D]` byte buffer from
     * [`Self::hidden_states_for_tokens`] into `[T][D]` with this. Lock-free
     * (cached at construction), so — like `position()` — it's safe to call from
     * a `generate_streaming` sink callback.
     */
    func hiddenSize()  -> UInt32
    
    /**
     * Like [`Self::hidden_states_for_tokens`] but tokenizes `text` first
     * (Swift `hiddenStates(for:)`). Returns the same LE-f32 byte layout.
     */
    func hiddenStatesForText(text: String) throws  -> Data
    
    /**
     * Per-token last-layer hidden states (post-final-RMSNorm — the llama.cpp
     * `--pooling none` / `llama_get_embeddings_ith` vector) for `tokens`,
     * returned as **little-endian f32 bytes**: `n_tokens * hidden_size * 4`
     * bytes, row-major, token `t` channel `c` at `(t*D + c) * 4`.
     *
     * Bytes (UniFFI `Data` in Swift, `ByteArray` in Kotlin) rather than
     * `List<Float>` to avoid Kotlin's per-element boxing on the potentially
     * large `[T*D]` payload. Swift decodes via `Data.withUnsafeBytes`; reflects
     * the active LoRA once that lands. Side-effect-free: does not disturb the
     * session's generation KV.
     *
     * Like `append_*` / `generate`, this holds the session mutex for the
     * duration of the compute, so it must NOT be called re-entrantly from
     * within a `generate_streaming` sink callback (would self-deadlock).
     *
     * Errors: `EmptyInput` on empty input; `UnsupportedModality` if the backend
     * doesn't implement hidden-state extraction; `InvalidToken` if any id is
     * `>= vocab_size`.
     */
    func hiddenStatesForTokens(tokens: [UInt32]) throws  -> Data
    
    /**
     * Mean-pooled hidden state — a single `[hidden_size]` vector (the common
     * classifier path: pool in Rust, ship `D` floats not `T*D`). Returned as
     * `[Float]` / `List<Float>`; only `D` elements, so boxing is negligible.
     */
    func hiddenStatesMeanPooled(tokens: [UInt32]) throws  -> [Float]
    
    /**
     * Current KV position — how many tokens live in the cache.
     * Atomic-backed; safe to call from a different thread while
     * `generate()` is in flight.
     */
    func position()  -> UInt32
    
    /**
     * Remove any attached LoRA adapter, returning to base-model inference.
     */
    func removeLora() throws 
    
    /**
     * Drop cached state + resample the seed. After `reset()` the
     * session behaves like a freshly-opened one (same
     * model/tokenizer/config, no accumulated context).
     *
     * Returns `Result` so a poisoned-mutex case surfaces as an error
     * instead of panicking across the FFI boundary.
     */
    func reset() throws 
    
    /**
     * Set a session-default cap on the longest side of an appended
     * image, in pixels (`None` = no cap). Unlike the per-call
     * `max_long_size` argument to [`Self::append_image`], this default
     * is honored by every image-append path the session drives —
     * including chat-template flows — so a host can configure the
     * image-encode budget once. See [`Self::append_image`] for the cap
     * semantics (shrinks the encoded target, never upscales, takes
     * precedence over the model's minimum-resolution floor).
     */
    func setImageMaxLongSize(maxLongSize: UInt32?) throws 
    
}
/**
 * Stateful inference handle. Wraps [`cera::Session`] behind a
 * `Mutex` so UniFFI's `Arc<Session>` shape works with methods that
 * need `&mut self` on the inner session (prefill, generate, reset).
 *
 * Call [`CeraEngine::new_session`] to open a session; the engine's
 * `Arc<Model>` and `Arc<BpeTokenizer>` are cloned into the new
 * session so it outlives the engine handle across FFI calls.
 */
open class Session: SessionProtocol, @unchecked Sendable {
    fileprivate let handle: UInt64

    /// Used to instantiate a [FFIObject] without an actual handle, for fakes in tests, mostly.
#if swift(>=5.8)
    @_documentation(visibility: private)
#endif
    public struct NoHandle {
        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`.
#if swift(>=5.8)
    @_documentation(visibility: private)
#endif
    required public init(unsafeFromHandle handle: UInt64) {
        self.handle = handle
    }

    // This constructor can be used to instantiate a fake object.
    // - Parameter noHandle: 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 handle the FFI lower functions will crash.
#if swift(>=5.8)
    @_documentation(visibility: private)
#endif
    public init(noHandle: NoHandle) {
        self.handle = 0
    }

#if swift(>=5.8)
    @_documentation(visibility: private)
#endif
    public func uniffiCloneHandle() -> UInt64 {
        return try! rustCall { uniffi_cera_ffi_fn_clone_session(self.handle, $0) }
    }
    // No primary constructor declared for this class.

    deinit {
        if handle == 0 {
            // Mock objects have handle=0 don't try to free them
            return
        }

        try! rustCall { uniffi_cera_ffi_fn_free_session(handle, $0) }
    }

    

    
    /**
     * Append PCM audio samples (mono `f32`, normalized to roughly
     * `[-1.0, 1.0]`) at `sample_rate` Hz. The audio is encoded via
     * the bundle's mmproj (`AudioEncoderWeights`) and prefilled
     * into the LLM as soft tokens — see
     * [`cera::Session::append_audio`] for the underlying flow.
     *
     * `CeraEngine::new_session` auto-attaches the encoder when the
     * loaded bundle's `inference_type == LlamaCppLfm2AudioV1` and
     * has `multimodal_projector` set in the manifest, so FFI
     * consumers don't need any separate "load encoder" call.
     * Bundles where the manifest omits `multimodal_projector`
     * silently end up with no encoder attached (no log). Bundles
     * where the file is named but fails to open or parse log a
     * `tracing::warn!` at `CeraEngine` construction. Both cases
     * surface here as a "no audio encoder attached" `Backend`
     * error.
     *
     * `sample_rate` must be 16000 — resampling is out of scope.
     * Callers should resample externally before passing samples in.
     *
     * **Marshaling cost**: UniFFI maps `Vec<f32>` to `List<Float>`
     * in Kotlin and `[Float]` in Swift. The Kotlin side boxes each
     * `Float` to `java.lang.Float`, a ~4× memory overhead vs the
     * underlying `f32` wire bytes — negligible for O(seconds ×
     * sample-rate) chunks but worth knowing if you're streaming
     * continuous audio in tight loops.
     *
     * Errors:
     * - `EmptyInput` either when `samples` is empty (fast-fail,
     * enforced here for parity with `append_text` /
     * `append_tokens`) **or** when the audio is too short to
     * produce any encoder frames (e.g. shorter than one
     * center-padded STFT window).
     * - `UnsupportedModality` if the loaded model's
     * [`ModalityCapabilities::audio_in`] is `false`.
     * - `Backend(...)` for sample-rate mismatch, encoder/LLM
     * `hidden_size` mismatch, or missing encoder. The latter
     * includes both "manifest didn't list a mmproj" (no warn
     * logged) and "mmproj listed but failed to open/parse"
     * (warn logged at `CeraEngine::from_path`).
     * - `ContextOverflow` / `Cancelled` propagate from the
     * underlying prefill.
     */
open func appendAudio(samples: [Float], sampleRate: UInt32)throws   {try rustCallWithError(FfiConverterTypeFfiError_lift) {
    uniffi_cera_ffi_fn_method_session_append_audio(
            self.uniffiCloneHandle(),
        FfiConverterSequenceFloat.lower(samples),
        FfiConverterUInt32.lower(sampleRate),$0
    )
}
}
    
    /**
     * Append an encoded image (PNG / JPEG bytes, auto-detected) to the
     * context. The image is decoded, resized, normalized, and run
     * through the bundle's vision mmproj (`VisionEncoderWeights`), then
     * prefilled into the LLM as soft tokens — see
     * [`cera::Session::append_image`] for the underlying flow.
     *
     * `CeraEngine::new_session` auto-attaches the vision encoder when
     * the loaded bundle's `inference_type` is a VL type with
     * `multimodal_projector` set in the manifest, so FFI consumers
     * don't need a separate "load encoder" call. Bundles whose
     * manifest omits the mmproj end up with no encoder attached (no
     * log); bundles where it's named but fails to open/parse log a
     * `tracing::warn!` at `CeraEngine` construction. Both surface here
     * as a "no vision encoder attached" `Backend` error.
     *
     * `max_long_size` controls the per-call cap on the longest side of
     * the *encoded* image, with three cases distinguished so the
     * session default stays reachable through FFI:
     * - `None` — defer to the session default set via
     * [`Self::set_image_max_long_size`] (no cap if none was set).
     * - `Some(0)` — explicitly force *no cap* for this call, ignoring
     * the session default.
     * - `Some(n)` (`n > 0`) — cap this call at `n`, overriding the
     * session default.
     *
     * When a cap applies, the resize target is shrunk
     * (aspect-preserving) so its longer side is at most `n` pixels,
     * floored at one aligned patch block (so a very small `n` can still
     * round up to that minimum) — a quality/cost knob (smaller = fewer
     * image tokens, faster, less detail). It only shrinks (never
     * upscales) and takes precedence over the model's
     * minimum-resolution floor. The cap bounds the *encode*, not the
     * *decode* (a huge source image is still decoded, bounded by
     * internal limits).
     *
     * **Placement matters.** Prefer driving multimodal turns through
     * the chat template; calling this at the wrong stream position
     * (outside the model's image-marker envelope) leaves the LLM
     * unable to interpret the embeddings as visual content. See
     * [`cera::Session::append_image`] for the marker recipe.
     *
     * Errors (capability is checked before emptiness, matching core):
     * - `UnsupportedModality` if the loaded model's
     * [`ModalityCapabilities::image_in`] is `false`.
     * - `EmptyInput` when `bytes` is empty (on a VL session).
     * - `Backend(...)` for image decode failure, missing vision
     * encoder, or encoder/LLM `projection_dim` ≠ `hidden_size`
     * mismatch.
     * - `ContextOverflow` / `Cancelled` propagate from the
     * underlying prefill.
     */
open func appendImage(bytes: Data, maxLongSize: UInt32?)throws   {try rustCallWithError(FfiConverterTypeFfiError_lift) {
    uniffi_cera_ffi_fn_method_session_append_image(
            self.uniffiCloneHandle(),
        FfiConverterData.lower(bytes),
        FfiConverterOptionUInt32.lower(maxLongSize),$0
    )
}
}
    
    /**
     * Append raw text to the context, running a prefill over just
     * the new tokens. `EmptyInput` error if `text` is empty.
     */
open func appendText(text: String)throws   {try rustCallWithError(FfiConverterTypeFfiError_lift) {
    uniffi_cera_ffi_fn_method_session_append_text(
            self.uniffiCloneHandle(),
        FfiConverterString.lower(text),$0
    )
}
}
    
    /**
     * Append pre-tokenized IDs. Useful when the caller has its own
     * tokenizer + chat-template pipeline.
     */
open func appendTokens(tokens: [UInt32])throws   {try rustCallWithError(FfiConverterTypeFfiError_lift) {
    uniffi_cera_ffi_fn_method_session_append_tokens(
            self.uniffiCloneHandle(),
        FfiConverterSequenceUInt32.lower(tokens),$0
    )
}
}
    
    /**
     * Attach a [`LoraAdapters`] to this session (generated as `attachLora` in
     * Swift/Kotlin — this is the engine's equivalent of a `setLoraAdapters`
     * call). It's applied to every subsequent forward pass — generation **and**
     * hidden-states extraction — until removed or replaced (hot-swap), and is
     * preserved across [`Self::reset`]. Returns [`FfiError::LoraParse`] if the
     * adapter's dimensions don't match the loaded model. Only affects tokens
     * processed after the call (doesn't retroactively re-adapt cached KV).
     */
open func attachLora(adapters: LoraAdapters)throws   {try rustCallWithError(FfiConverterTypeFfiError_lift) {
    uniffi_cera_ffi_fn_method_session_attach_lora(
            self.uniffiCloneHandle(),
        FfiConverterTypeLoraAdapters_lower(adapters),$0
    )
}
}
    
    /**
     * Signal in-flight `generate()` to exit with
     * `FinishReason::Cancelled` at the next between-token check.
     * Safe from any thread. No-op if no `generate()` is running.
     */
open func cancel()  {try! rustCall() {
    uniffi_cera_ffi_fn_method_session_cancel(
            self.uniffiCloneHandle(),$0
    )
}
}
    
    /**
     * Capabilities reported by the loaded model. Cheap — reads a
     * cached copy, no lock.
     */
open func capabilities() -> ModalityCapabilities  {
    return try!  FfiConverterTypeModalityCapabilities_lift(try! rustCall() {
    uniffi_cera_ffi_fn_method_session_capabilities(
            self.uniffiCloneHandle(),$0
    )
})
}
    
    /**
     * Clear the cancel flag without dropping any session state.
     * Use this after observing a cancellation signal — either
     * [`FfiError::Cancelled`] from `append_text` / `append_tokens`
     * / `append_audio` (mid-prefill cancellation surfaces
     * typed), or `finish_reason = "Cancelled"` on the
     * [`GenerateOutput`] returned from `generate` (cancellation
     * during decode is reported as an `Ok` with that finish
     * reason rather than an `Err`) — when you want to resume
     * work on the same session without losing the accumulated
     * KV cache.
     *
     * Compared to [`Self::reset`]:
     * - `clear_cancel`: keeps KV state + position + sampler
     * intact; only flips the cancel atomic back to `false`.
     * Use for "interrupted but continuing" flows.
     * - `reset`: drops KV cache + position + last logits +
     * re-seeds sampler. Use for "clear conversation" flows.
     *
     * Atomic-backed; no mutex acquire, infallible, safe from
     * any thread (mirrors the shape of [`Self::cancel`]).
     */
open func clearCancel()  {try! rustCall() {
    uniffi_cera_ffi_fn_method_session_clear_cancel(
            self.uniffiCloneHandle(),$0
    )
}
}
    
    /**
     * Run autoregressive decode and return all emitted tokens +
     * a summary. Synchronous — the call blocks until the decode
     * loop exits (`max_tokens`, EOS, `cancel()`, or error).
     *
     * For streaming (per-chunk delivery) and async, see the PR 4 /
     * PR 5 follow-ups in `cera-ffi/README.md`.
     */
open func generate(opts: GenerateOpts)throws  -> GenerateOutput  {
    return try  FfiConverterTypeGenerateOutput_lift(try rustCallWithError(FfiConverterTypeFfiError_lift) {
    uniffi_cera_ffi_fn_method_session_generate(
            self.uniffiCloneHandle(),
        FfiConverterTypeGenerateOpts_lower(opts),$0
    )
})
}
    
    /**
     * Async variant of [`Session::generate`] — runs buffered decode
     * (returning every emitted token + a summary) on a tokio blocking
     * worker so the caller's async context isn't stalled by the
     * synchronous decode loop.
     *
     * Cancellation: dropping the returned future (Kotlin coroutine
     * scope exit, Swift `Task.cancel`, Python `asyncio.Task.cancel`)
     * triggers both an abort of the queued `spawn_blocking` task (so
     * a not-yet-started decode never runs) and a
     * [`Session::cancel`] call (so an in-flight decode exits at its
     * next between-token check with [`FinishReason::Cancelled`]).
     * Either path releases the session mutex; subsequent calls see
     * a clean session. You can also call [`Session::cancel`]
     * directly from any thread to trigger the same in-flight exit
     * without dropping the future. See `AsyncCancelGuard` for the
     * full rationale.
     *
     * On error the wrapper performs the same poisoned-mutex handling
     * as sync [`Session::generate`]. `JoinError` from a panic in the
     * blocking closure surfaces as [`FfiError::Backend`] with a
     * diagnostic prefix.
     */
open func generateAsync(opts: GenerateOpts)async throws  -> GenerateOutput  {
    return
        try  await uniffiRustCallAsync(
            rustFutureFunc: {
                uniffi_cera_ffi_fn_method_session_generate_async(
                    self.uniffiCloneHandle(),
                    FfiConverterTypeGenerateOpts_lower(opts)
                )
            },
            pollFunc: ffi_cera_ffi_rust_future_poll_rust_buffer,
            completeFunc: ffi_cera_ffi_rust_future_complete_rust_buffer,
            freeFunc: ffi_cera_ffi_rust_future_free_rust_buffer,
            liftFunc: FfiConverterTypeGenerateOutput_lift,
            errorHandler: FfiConverterTypeFfiError_lift
        )
}
    
    /**
     * Run autoregressive decode, streaming every token (and audio
     * frame, for audio-capable models) to a foreign [`ModalitySink`]
     * as soon as it's produced. Returns only a [`GenerateSummary`] —
     * token IDs are delivered through `sink.on_text_tokens`, not a
     * return value.
     *
     * Synchronous: the call blocks on the decode thread and each
     * `sink` method runs on that same thread before decoding
     * continues. For async, see PR 5 in `cera-ffi/README.md`.
     *
     * **Callback reentrancy — deadlock hazard.** The session mutex is
     * held for the entire call, and sink callbacks run while that
     * lock is held. Calling back into methods that also take the
     * mutex ([`Session::append_text`], [`Session::append_tokens`],
     * [`Session::generate`], [`Session::generate_streaming`],
     * [`Session::reset`]) from inside a sink method will deadlock.
     * [`Session::cancel`] and [`Session::position`] are atomic-backed
     * and safe to call from the sink or from any other thread.
     *
     * Cancellation: call [`Session::cancel`] from any thread (or from
     * inside a sink callback on this thread) to terminate the loop at
     * the next between-token check; `sink.on_done` fires with
     * [`FinishReason::Cancelled`].
     *
     * End-of-stream guarantee: `sink.on_done` fires exactly once per
     * call, even on error paths. If the underlying decode returns an
     * error before reaching its own `on_done` call (e.g.,
     * `EmptyInput` with no prefill logits), the wrapper synthesizes
     * a terminal `on_done(FinishReason::Error { message })` so
     * foreign consumers have a reliable end-of-stream signal
     * regardless of how the call exits.
     */
open func generateStreaming(opts: GenerateOpts, sink: ModalitySink)throws  -> GenerateSummary  {
    return try  FfiConverterTypeGenerateSummary_lift(try rustCallWithError(FfiConverterTypeFfiError_lift) {
    uniffi_cera_ffi_fn_method_session_generate_streaming(
            self.uniffiCloneHandle(),
        FfiConverterTypeGenerateOpts_lower(opts),
        FfiConverterTypeModalitySink_lower(sink),$0
    )
})
}
    
    /**
     * Async variant of [`Session::generate_streaming`] — delivers
     * tokens and audio frames to the foreign [`ModalitySink`] as the
     * decode loop produces them, from within a blocking worker so
     * the caller's async runtime stays responsive.
     *
     * Sink callbacks run on the blocking worker thread that's
     * executing the decode — **not** on the caller's async thread.
     * The reentrancy hazard documented on
     * [`Session::generate_streaming`] still applies: sink callbacks
     * that call back into `append_text` / `generate*` / `reset` from
     * inside the session will deadlock on the session mutex.
     * [`Session::cancel`] and [`Session::position`] remain atomic-
     * backed and safe to invoke from any thread (including from
     * inside a callback).
     *
     * Cancellation: dropping the returned future fires the same
     * abort + [`Session::cancel`] pair as [`Session::generate_async`]
     * (see `AsyncCancelGuard`). For an in-flight decode, the loop
     * exits with [`FinishReason::Cancelled`] and the sink's `on_done`
     * fires on the blocking worker before the task completes —
     * foreign consumers get the terminal signal even though they've
     * already stopped awaiting. For a queued-but-not-started decode,
     * abort cancels the task without ever running the closure; no
     * sink callbacks fire for that case (the decode never began).
     */
open func generateStreamingAsync(opts: GenerateOpts, sink: ModalitySink)async throws  -> GenerateSummary  {
    return
        try  await uniffiRustCallAsync(
            rustFutureFunc: {
                uniffi_cera_ffi_fn_method_session_generate_streaming_async(
                    self.uniffiCloneHandle(),
                    FfiConverterTypeGenerateOpts_lower(opts),FfiConverterTypeModalitySink_lower(sink)
                )
            },
            pollFunc: ffi_cera_ffi_rust_future_poll_rust_buffer,
            completeFunc: ffi_cera_ffi_rust_future_complete_rust_buffer,
            freeFunc: ffi_cera_ffi_rust_future_free_rust_buffer,
            liftFunc: FfiConverterTypeGenerateSummary_lift,
            errorHandler: FfiConverterTypeFfiError_lift
        )
}
    
    /**
     * Whether a LoRA adapter is currently attached to this session.
     */
open func hasLora()throws  -> Bool  {
    return try  FfiConverterBool.lift(try rustCallWithError(FfiConverterTypeFfiError_lift) {
    uniffi_cera_ffi_fn_method_session_has_lora(
            self.uniffiCloneHandle(),$0
    )
})
}
    
    /**
     * Model hidden dimension `D`. Reshape a raw `[T*D]` byte buffer from
     * [`Self::hidden_states_for_tokens`] into `[T][D]` with this. Lock-free
     * (cached at construction), so — like `position()` — it's safe to call from
     * a `generate_streaming` sink callback.
     */
open func hiddenSize() -> UInt32  {
    return try!  FfiConverterUInt32.lift(try! rustCall() {
    uniffi_cera_ffi_fn_method_session_hidden_size(
            self.uniffiCloneHandle(),$0
    )
})
}
    
    /**
     * Like [`Self::hidden_states_for_tokens`] but tokenizes `text` first
     * (Swift `hiddenStates(for:)`). Returns the same LE-f32 byte layout.
     */
open func hiddenStatesForText(text: String)throws  -> Data  {
    return try  FfiConverterData.lift(try rustCallWithError(FfiConverterTypeFfiError_lift) {
    uniffi_cera_ffi_fn_method_session_hidden_states_for_text(
            self.uniffiCloneHandle(),
        FfiConverterString.lower(text),$0
    )
})
}
    
    /**
     * Per-token last-layer hidden states (post-final-RMSNorm — the llama.cpp
     * `--pooling none` / `llama_get_embeddings_ith` vector) for `tokens`,
     * returned as **little-endian f32 bytes**: `n_tokens * hidden_size * 4`
     * bytes, row-major, token `t` channel `c` at `(t*D + c) * 4`.
     *
     * Bytes (UniFFI `Data` in Swift, `ByteArray` in Kotlin) rather than
     * `List<Float>` to avoid Kotlin's per-element boxing on the potentially
     * large `[T*D]` payload. Swift decodes via `Data.withUnsafeBytes`; reflects
     * the active LoRA once that lands. Side-effect-free: does not disturb the
     * session's generation KV.
     *
     * Like `append_*` / `generate`, this holds the session mutex for the
     * duration of the compute, so it must NOT be called re-entrantly from
     * within a `generate_streaming` sink callback (would self-deadlock).
     *
     * Errors: `EmptyInput` on empty input; `UnsupportedModality` if the backend
     * doesn't implement hidden-state extraction; `InvalidToken` if any id is
     * `>= vocab_size`.
     */
open func hiddenStatesForTokens(tokens: [UInt32])throws  -> Data  {
    return try  FfiConverterData.lift(try rustCallWithError(FfiConverterTypeFfiError_lift) {
    uniffi_cera_ffi_fn_method_session_hidden_states_for_tokens(
            self.uniffiCloneHandle(),
        FfiConverterSequenceUInt32.lower(tokens),$0
    )
})
}
    
    /**
     * Mean-pooled hidden state — a single `[hidden_size]` vector (the common
     * classifier path: pool in Rust, ship `D` floats not `T*D`). Returned as
     * `[Float]` / `List<Float>`; only `D` elements, so boxing is negligible.
     */
open func hiddenStatesMeanPooled(tokens: [UInt32])throws  -> [Float]  {
    return try  FfiConverterSequenceFloat.lift(try rustCallWithError(FfiConverterTypeFfiError_lift) {
    uniffi_cera_ffi_fn_method_session_hidden_states_mean_pooled(
            self.uniffiCloneHandle(),
        FfiConverterSequenceUInt32.lower(tokens),$0
    )
})
}
    
    /**
     * Current KV position — how many tokens live in the cache.
     * Atomic-backed; safe to call from a different thread while
     * `generate()` is in flight.
     */
open func position() -> UInt32  {
    return try!  FfiConverterUInt32.lift(try! rustCall() {
    uniffi_cera_ffi_fn_method_session_position(
            self.uniffiCloneHandle(),$0
    )
})
}
    
    /**
     * Remove any attached LoRA adapter, returning to base-model inference.
     */
open func removeLora()throws   {try rustCallWithError(FfiConverterTypeFfiError_lift) {
    uniffi_cera_ffi_fn_method_session_remove_lora(
            self.uniffiCloneHandle(),$0
    )
}
}
    
    /**
     * Drop cached state + resample the seed. After `reset()` the
     * session behaves like a freshly-opened one (same
     * model/tokenizer/config, no accumulated context).
     *
     * Returns `Result` so a poisoned-mutex case surfaces as an error
     * instead of panicking across the FFI boundary.
     */
open func reset()throws   {try rustCallWithError(FfiConverterTypeFfiError_lift) {
    uniffi_cera_ffi_fn_method_session_reset(
            self.uniffiCloneHandle(),$0
    )
}
}
    
    /**
     * Set a session-default cap on the longest side of an appended
     * image, in pixels (`None` = no cap). Unlike the per-call
     * `max_long_size` argument to [`Self::append_image`], this default
     * is honored by every image-append path the session drives —
     * including chat-template flows — so a host can configure the
     * image-encode budget once. See [`Self::append_image`] for the cap
     * semantics (shrinks the encoded target, never upscales, takes
     * precedence over the model's minimum-resolution floor).
     */
open func setImageMaxLongSize(maxLongSize: UInt32?)throws   {try rustCallWithError(FfiConverterTypeFfiError_lift) {
    uniffi_cera_ffi_fn_method_session_set_image_max_long_size(
            self.uniffiCloneHandle(),
        FfiConverterOptionUInt32.lower(maxLongSize),$0
    )
}
}
    

    
}


#if swift(>=5.8)
@_documentation(visibility: private)
#endif
public struct FfiConverterTypeSession: FfiConverter {
    typealias FfiType = UInt64
    typealias SwiftType = Session

    public static func lift(_ handle: UInt64) throws -> Session {
        return Session(unsafeFromHandle: handle)
    }

    public static func lower(_ value: Session) -> UInt64 {
        return value.uniffiCloneHandle()
    }

    public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> Session {
        let handle: UInt64 = try readInt(&buf)
        return try lift(handle)
    }

    public static func write(_ value: Session, into buf: inout [UInt8]) {
        writeInt(&buf, lower(value))
    }
}


#if swift(>=5.8)
@_documentation(visibility: private)
#endif
public func FfiConverterTypeSession_lift(_ handle: UInt64) throws -> Session {
    return try FfiConverterTypeSession.lift(handle)
}

#if swift(>=5.8)
@_documentation(visibility: private)
#endif
public func FfiConverterTypeSession_lower(_ value: Session) -> UInt64 {
    return FfiConverterTypeSession.lower(value)
}




/**
 * One message in a chat-template conversation. Mirrors
 * [`cera::tokenizer::ChatMessage`]. Pass a `Vec<ChatMessage>` to
 * [`CeraEngine::apply_chat_template`] to render the model's
 * chat-template (Jinja2 from GGUF metadata) into a prompt string
 * ready to feed into [`Session::append_text`].
 *
 * `role` follows the OpenAI / chat-template convention — typically
 * one of `"system"`, `"user"`, `"assistant"`, occasionally
 * `"tool"`. cera-ffi doesn't validate the role string; whatever is
 * passed flows directly into the Jinja template. Whether an
 * unknown role errors or silently no-ops depends on the template's
 * own logic — many templates have an explicit error path for
 * unrecognized roles, but it's template-dependent rather than
 * enforced by [`CeraEngine::apply_chat_template`].
 */
public struct ChatMessage: Equatable, Hashable {
    public var role: String
    public var content: String

    // Default memberwise initializers are never public by default, so we
    // declare one manually.
    public init(role: String, content: String) {
        self.role = role
        self.content = content
    }

    

    
}

#if compiler(>=6)
extension ChatMessage: Sendable {}
#endif

#if swift(>=5.8)
@_documentation(visibility: private)
#endif
public struct FfiConverterTypeChatMessage: FfiConverterRustBuffer {
    public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> ChatMessage {
        return
            try ChatMessage(
                role: FfiConverterString.read(from: &buf), 
                content: FfiConverterString.read(from: &buf)
        )
    }

    public static func write(_ value: ChatMessage, into buf: inout [UInt8]) {
        FfiConverterString.write(value.role, into: &buf)
        FfiConverterString.write(value.content, into: &buf)
    }
}


#if swift(>=5.8)
@_documentation(visibility: private)
#endif
public func FfiConverterTypeChatMessage_lift(_ buf: RustBuffer) throws -> ChatMessage {
    return try FfiConverterTypeChatMessage.lift(buf)
}

#if swift(>=5.8)
@_documentation(visibility: private)
#endif
public func FfiConverterTypeChatMessage_lower(_ value: ChatMessage) -> RustBuffer {
    return FfiConverterTypeChatMessage.lower(value)
}


/**
 * Per-engine configuration at load time. Mirrors [`cera::EngineConfig`]
 * with `u64` fields (UniFFI doesn't marshal `usize`).
 */
public struct EngineConfig {
    /**
     * KV-cache capacity in tokens. Capped by the model's own
     * `max_seq_len`. Pass `0` to use the model's full declared
     * `max_seq_len` (translated to `usize::MAX` internally, then
     * capped by the loader).
     */
    public var contextSize: UInt64
    public var backend: BackendPreference
    /**
     * Bundle repository for resolving `http(s)://` URLs in manifests
     * (or for [`CeraEngine::from_bundle_id`]). `None` means "remote
     * URLs will fail with an error"; set this to a [`BundleRepo`]
     * rooted at a persistent cache directory to enable remote
     * downloads. Construct the repo once + reuse it across engine
     * loads so its HTTP client pool + on-disk cache are shared.
     */
    public var bundleRepo: BundleRepo?

    // Default memberwise initializers are never public by default, so we
    // declare one manually.
    public init(
        /**
         * KV-cache capacity in tokens. Capped by the model's own
         * `max_seq_len`. Pass `0` to use the model's full declared
         * `max_seq_len` (translated to `usize::MAX` internally, then
         * capped by the loader).
         */contextSize: UInt64, backend: BackendPreference, 
        /**
         * Bundle repository for resolving `http(s)://` URLs in manifests
         * (or for [`CeraEngine::from_bundle_id`]). `None` means "remote
         * URLs will fail with an error"; set this to a [`BundleRepo`]
         * rooted at a persistent cache directory to enable remote
         * downloads. Construct the repo once + reuse it across engine
         * loads so its HTTP client pool + on-disk cache are shared.
         */bundleRepo: BundleRepo?) {
        self.contextSize = contextSize
        self.backend = backend
        self.bundleRepo = bundleRepo
    }

    

    
}

#if compiler(>=6)
extension EngineConfig: Sendable {}
#endif

#if swift(>=5.8)
@_documentation(visibility: private)
#endif
public struct FfiConverterTypeEngineConfig: FfiConverterRustBuffer {
    public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> EngineConfig {
        return
            try EngineConfig(
                contextSize: FfiConverterUInt64.read(from: &buf), 
                backend: FfiConverterTypeBackendPreference.read(from: &buf), 
                bundleRepo: FfiConverterOptionTypeBundleRepo.read(from: &buf)
        )
    }

    public static func write(_ value: EngineConfig, into buf: inout [UInt8]) {
        FfiConverterUInt64.write(value.contextSize, into: &buf)
        FfiConverterTypeBackendPreference.write(value.backend, into: &buf)
        FfiConverterOptionTypeBundleRepo.write(value.bundleRepo, into: &buf)
    }
}


#if swift(>=5.8)
@_documentation(visibility: private)
#endif
public func FfiConverterTypeEngineConfig_lift(_ buf: RustBuffer) throws -> EngineConfig {
    return try FfiConverterTypeEngineConfig.lift(buf)
}

#if swift(>=5.8)
@_documentation(visibility: private)
#endif
public func FfiConverterTypeEngineConfig_lower(_ value: EngineConfig) -> RustBuffer {
    return FfiConverterTypeEngineConfig.lower(value)
}


/**
 * Per-call decode options. Mirrors [`cera::GenerateOpts`].
 *
 * `flush_every_tokens` / `flush_every_ms` are accepted but have no
 * effect under the synchronous [`Session::generate`] — they're
 * meaningful once streaming (foreign-trait `ModalitySink`) lands
 * in a follow-up PR. Including them in the record now keeps the FFI
 * surface stable across that transition.
 */
public struct GenerateOpts: Equatable, Hashable {
    public var maxTokens: UInt32
    public var temperature: Float
    public var topP: Float
    public var topK: UInt32
    /**
     * Min-p (relative) nucleus cutoff: drop tokens below `min_p * p_max`. `0.0`
     * disables it. Honored in the stochastic path.
     */
    public var minP: Float
    /**
     * Repetition penalty over tokens generated this call. `1.0` disables it.
     * Honored in the stochastic path (greedy/argmax decoding is unaffected).
     */
    public var repetitionPenalty: Float
    /**
     * Early-stop IDs (EOS / instruction markers / end-of-turn).
     */
    public var stopTokens: [UInt32]
    /**
     * Optional GBNF grammar **source text** constraining the output (e.g. a
     * JSON grammar). When absent (the default), decoding is unconstrained. The
     * grammar is compiled on the Rust side when generation starts; a malformed
     * grammar is reported as a `GrammarParse` error.
     */
    public var grammar: String?
    /**
     * Ignored under synchronous generate; reserved for streaming.
     */
    public var flushEveryTokens: UInt32
    /**
     * Ignored under synchronous generate; reserved for streaming.
     */
    public var flushEveryMs: UInt32

    // Default memberwise initializers are never public by default, so we
    // declare one manually.
    public init(maxTokens: UInt32, temperature: Float, topP: Float, topK: UInt32, 
        /**
         * Min-p (relative) nucleus cutoff: drop tokens below `min_p * p_max`. `0.0`
         * disables it. Honored in the stochastic path.
         */minP: Float, 
        /**
         * Repetition penalty over tokens generated this call. `1.0` disables it.
         * Honored in the stochastic path (greedy/argmax decoding is unaffected).
         */repetitionPenalty: Float, 
        /**
         * Early-stop IDs (EOS / instruction markers / end-of-turn).
         */stopTokens: [UInt32], 
        /**
         * Optional GBNF grammar **source text** constraining the output (e.g. a
         * JSON grammar). When absent (the default), decoding is unconstrained. The
         * grammar is compiled on the Rust side when generation starts; a malformed
         * grammar is reported as a `GrammarParse` error.
         */grammar: String?, 
        /**
         * Ignored under synchronous generate; reserved for streaming.
         */flushEveryTokens: UInt32, 
        /**
         * Ignored under synchronous generate; reserved for streaming.
         */flushEveryMs: UInt32) {
        self.maxTokens = maxTokens
        self.temperature = temperature
        self.topP = topP
        self.topK = topK
        self.minP = minP
        self.repetitionPenalty = repetitionPenalty
        self.stopTokens = stopTokens
        self.grammar = grammar
        self.flushEveryTokens = flushEveryTokens
        self.flushEveryMs = flushEveryMs
    }

    

    
}

#if compiler(>=6)
extension GenerateOpts: Sendable {}
#endif

#if swift(>=5.8)
@_documentation(visibility: private)
#endif
public struct FfiConverterTypeGenerateOpts: FfiConverterRustBuffer {
    public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> GenerateOpts {
        return
            try GenerateOpts(
                maxTokens: FfiConverterUInt32.read(from: &buf), 
                temperature: FfiConverterFloat.read(from: &buf), 
                topP: FfiConverterFloat.read(from: &buf), 
                topK: FfiConverterUInt32.read(from: &buf), 
                minP: FfiConverterFloat.read(from: &buf), 
                repetitionPenalty: FfiConverterFloat.read(from: &buf), 
                stopTokens: FfiConverterSequenceUInt32.read(from: &buf), 
                grammar: FfiConverterOptionString.read(from: &buf), 
                flushEveryTokens: FfiConverterUInt32.read(from: &buf), 
                flushEveryMs: FfiConverterUInt32.read(from: &buf)
        )
    }

    public static func write(_ value: GenerateOpts, into buf: inout [UInt8]) {
        FfiConverterUInt32.write(value.maxTokens, into: &buf)
        FfiConverterFloat.write(value.temperature, into: &buf)
        FfiConverterFloat.write(value.topP, into: &buf)
        FfiConverterUInt32.write(value.topK, into: &buf)
        FfiConverterFloat.write(value.minP, into: &buf)
        FfiConverterFloat.write(value.repetitionPenalty, into: &buf)
        FfiConverterSequenceUInt32.write(value.stopTokens, into: &buf)
        FfiConverterOptionString.write(value.grammar, into: &buf)
        FfiConverterUInt32.write(value.flushEveryTokens, into: &buf)
        FfiConverterUInt32.write(value.flushEveryMs, into: &buf)
    }
}


#if swift(>=5.8)
@_documentation(visibility: private)
#endif
public func FfiConverterTypeGenerateOpts_lift(_ buf: RustBuffer) throws -> GenerateOpts {
    return try FfiConverterTypeGenerateOpts.lift(buf)
}

#if swift(>=5.8)
@_documentation(visibility: private)
#endif
public func FfiConverterTypeGenerateOpts_lower(_ value: GenerateOpts) -> RustBuffer {
    return FfiConverterTypeGenerateOpts.lower(value)
}


/**
 * Bundle of everything a synchronous `generate` call produces:
 * the generated token IDs plus the decode summary. The two are
 * returned together so callers don't have to manage a separate
 * callback channel; streaming (per-chunk delivery) lands in PR 4.
 */
public struct GenerateOutput: Equatable, Hashable {
    /**
     * Generated token IDs, in order, not including any prompt
     * tokens. Decode with [`cera::tokenizer::BpeTokenizer`] on the
     * Rust side or (once exposed) through a tokenizer handle on the
     * FFI side.
     */
    public var tokens: [UInt32]
    public var summary: GenerateSummary

    // Default memberwise initializers are never public by default, so we
    // declare one manually.
    public init(
        /**
         * Generated token IDs, in order, not including any prompt
         * tokens. Decode with [`cera::tokenizer::BpeTokenizer`] on the
         * Rust side or (once exposed) through a tokenizer handle on the
         * FFI side.
         */tokens: [UInt32], summary: GenerateSummary) {
        self.tokens = tokens
        self.summary = summary
    }

    

    
}

#if compiler(>=6)
extension GenerateOutput: Sendable {}
#endif

#if swift(>=5.8)
@_documentation(visibility: private)
#endif
public struct FfiConverterTypeGenerateOutput: FfiConverterRustBuffer {
    public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> GenerateOutput {
        return
            try GenerateOutput(
                tokens: FfiConverterSequenceUInt32.read(from: &buf), 
                summary: FfiConverterTypeGenerateSummary.read(from: &buf)
        )
    }

    public static func write(_ value: GenerateOutput, into buf: inout [UInt8]) {
        FfiConverterSequenceUInt32.write(value.tokens, into: &buf)
        FfiConverterTypeGenerateSummary.write(value.summary, into: &buf)
    }
}


#if swift(>=5.8)
@_documentation(visibility: private)
#endif
public func FfiConverterTypeGenerateOutput_lift(_ buf: RustBuffer) throws -> GenerateOutput {
    return try FfiConverterTypeGenerateOutput.lift(buf)
}

#if swift(>=5.8)
@_documentation(visibility: private)
#endif
public func FfiConverterTypeGenerateOutput_lower(_ value: GenerateOutput) -> RustBuffer {
    return FfiConverterTypeGenerateOutput.lower(value)
}


/**
 * Decode-run metadata. Mirrors [`cera::GenerateSummary`].
 */
public struct GenerateSummary: Equatable, Hashable {
    public var tokensGenerated: UInt32
    public var promptEvalTokens: UInt32
    public var promptEvalMs: UInt32
    public var decodeMs: UInt32
    public var finishReason: FinishReason

    // Default memberwise initializers are never public by default, so we
    // declare one manually.
    public init(tokensGenerated: UInt32, promptEvalTokens: UInt32, promptEvalMs: UInt32, decodeMs: UInt32, finishReason: FinishReason) {
        self.tokensGenerated = tokensGenerated
        self.promptEvalTokens = promptEvalTokens
        self.promptEvalMs = promptEvalMs
        self.decodeMs = decodeMs
        self.finishReason = finishReason
    }

    

    
}

#if compiler(>=6)
extension GenerateSummary: Sendable {}
#endif

#if swift(>=5.8)
@_documentation(visibility: private)
#endif
public struct FfiConverterTypeGenerateSummary: FfiConverterRustBuffer {
    public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> GenerateSummary {
        return
            try GenerateSummary(
                tokensGenerated: FfiConverterUInt32.read(from: &buf), 
                promptEvalTokens: FfiConverterUInt32.read(from: &buf), 
                promptEvalMs: FfiConverterUInt32.read(from: &buf), 
                decodeMs: FfiConverterUInt32.read(from: &buf), 
                finishReason: FfiConverterTypeFinishReason.read(from: &buf)
        )
    }

    public static func write(_ value: GenerateSummary, into buf: inout [UInt8]) {
        FfiConverterUInt32.write(value.tokensGenerated, into: &buf)
        FfiConverterUInt32.write(value.promptEvalTokens, into: &buf)
        FfiConverterUInt32.write(value.promptEvalMs, into: &buf)
        FfiConverterUInt32.write(value.decodeMs, into: &buf)
        FfiConverterTypeFinishReason.write(value.finishReason, into: &buf)
    }
}


#if swift(>=5.8)
@_documentation(visibility: private)
#endif
public func FfiConverterTypeGenerateSummary_lift(_ buf: RustBuffer) throws -> GenerateSummary {
    return try FfiConverterTypeGenerateSummary.lift(buf)
}

#if swift(>=5.8)
@_documentation(visibility: private)
#endif
public func FfiConverterTypeGenerateSummary_lower(_ value: GenerateSummary) -> RustBuffer {
    return FfiConverterTypeGenerateSummary.lower(value)
}


/**
 * Modality support flags for a loaded model. Mirrors
 * [`cera::ModalityCapabilities`].
 */
public struct ModalityCapabilities: Equatable, Hashable {
    public var textIn: Bool
    public var textOut: Bool
    public var imageIn: Bool
    public var audioIn: Bool
    public var audioOut: Bool

    // Default memberwise initializers are never public by default, so we
    // declare one manually.
    public init(textIn: Bool, textOut: Bool, imageIn: Bool, audioIn: Bool, audioOut: Bool) {
        self.textIn = textIn
        self.textOut = textOut
        self.imageIn = imageIn
        self.audioIn = audioIn
        self.audioOut = audioOut
    }

    

    
}

#if compiler(>=6)
extension ModalityCapabilities: Sendable {}
#endif

#if swift(>=5.8)
@_documentation(visibility: private)
#endif
public struct FfiConverterTypeModalityCapabilities: FfiConverterRustBuffer {
    public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> ModalityCapabilities {
        return
            try ModalityCapabilities(
                textIn: FfiConverterBool.read(from: &buf), 
                textOut: FfiConverterBool.read(from: &buf), 
                imageIn: FfiConverterBool.read(from: &buf), 
                audioIn: FfiConverterBool.read(from: &buf), 
                audioOut: FfiConverterBool.read(from: &buf)
        )
    }

    public static func write(_ value: ModalityCapabilities, into buf: inout [UInt8]) {
        FfiConverterBool.write(value.textIn, into: &buf)
        FfiConverterBool.write(value.textOut, into: &buf)
        FfiConverterBool.write(value.imageIn, into: &buf)
        FfiConverterBool.write(value.audioIn, into: &buf)
        FfiConverterBool.write(value.audioOut, into: &buf)
    }
}


#if swift(>=5.8)
@_documentation(visibility: private)
#endif
public func FfiConverterTypeModalityCapabilities_lift(_ buf: RustBuffer) throws -> ModalityCapabilities {
    return try FfiConverterTypeModalityCapabilities.lift(buf)
}

#if swift(>=5.8)
@_documentation(visibility: private)
#endif
public func FfiConverterTypeModalityCapabilities_lower(_ value: ModalityCapabilities) -> RustBuffer {
    return FfiConverterTypeModalityCapabilities.lower(value)
}


/**
 * Short summary of a loaded model. Mirrors [`cera::ModelMetadata`].
 */
public struct ModelMetadata: Equatable, Hashable {
    public var architecture: String
    public var maxSeqLen: UInt32
    public var vocabSize: UInt32
    public var hasChatTemplate: Bool
    public var quantization: String
    /**
     * Mirror of GGUF `tokenizer.ggml.add_bos_token`. Consumers that
     * want to insert a BOS at the head of a raw prompt should honor it.
     */
    public var addBosToken: Bool
    /**
     * SIMD backend tier the runtime resolved for this host (e.g.
     * `"neon+dotprod"`, `"avx2"`, `"scalar"`). A host property, not
     * model-specific — surfaced here so consumers fetching metadata also
     * get backend diagnostics for telemetry / bug reports. For the full
     * feature list, see [`cpu_backend_report`].
     */
    public var cpuBackend: String

    // Default memberwise initializers are never public by default, so we
    // declare one manually.
    public init(architecture: String, maxSeqLen: UInt32, vocabSize: UInt32, hasChatTemplate: Bool, quantization: String, 
        /**
         * Mirror of GGUF `tokenizer.ggml.add_bos_token`. Consumers that
         * want to insert a BOS at the head of a raw prompt should honor it.
         */addBosToken: Bool, 
        /**
         * SIMD backend tier the runtime resolved for this host (e.g.
         * `"neon+dotprod"`, `"avx2"`, `"scalar"`). A host property, not
         * model-specific — surfaced here so consumers fetching metadata also
         * get backend diagnostics for telemetry / bug reports. For the full
         * feature list, see [`cpu_backend_report`].
         */cpuBackend: String) {
        self.architecture = architecture
        self.maxSeqLen = maxSeqLen
        self.vocabSize = vocabSize
        self.hasChatTemplate = hasChatTemplate
        self.quantization = quantization
        self.addBosToken = addBosToken
        self.cpuBackend = cpuBackend
    }

    

    
}

#if compiler(>=6)
extension ModelMetadata: Sendable {}
#endif

#if swift(>=5.8)
@_documentation(visibility: private)
#endif
public struct FfiConverterTypeModelMetadata: FfiConverterRustBuffer {
    public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> ModelMetadata {
        return
            try ModelMetadata(
                architecture: FfiConverterString.read(from: &buf), 
                maxSeqLen: FfiConverterUInt32.read(from: &buf), 
                vocabSize: FfiConverterUInt32.read(from: &buf), 
                hasChatTemplate: FfiConverterBool.read(from: &buf), 
                quantization: FfiConverterString.read(from: &buf), 
                addBosToken: FfiConverterBool.read(from: &buf), 
                cpuBackend: FfiConverterString.read(from: &buf)
        )
    }

    public static func write(_ value: ModelMetadata, into buf: inout [UInt8]) {
        FfiConverterString.write(value.architecture, into: &buf)
        FfiConverterUInt32.write(value.maxSeqLen, into: &buf)
        FfiConverterUInt32.write(value.vocabSize, into: &buf)
        FfiConverterBool.write(value.hasChatTemplate, into: &buf)
        FfiConverterString.write(value.quantization, into: &buf)
        FfiConverterBool.write(value.addBosToken, into: &buf)
        FfiConverterString.write(value.cpuBackend, into: &buf)
    }
}


#if swift(>=5.8)
@_documentation(visibility: private)
#endif
public func FfiConverterTypeModelMetadata_lift(_ buf: RustBuffer) throws -> ModelMetadata {
    return try FfiConverterTypeModelMetadata.lift(buf)
}

#if swift(>=5.8)
@_documentation(visibility: private)
#endif
public func FfiConverterTypeModelMetadata_lower(_ value: ModelMetadata) -> RustBuffer {
    return FfiConverterTypeModelMetadata.lower(value)
}


/**
 * Per-session configuration. Mirrors [`cera::SessionConfig`].
 */
public struct SessionConfig: Equatable, Hashable {
    /**
     * Cap on total tokens held in KV. `None` → model's default
     * `max_seq_len`.
     */
    public var maxSeqLen: UInt32?
    /**
     * KV cache compression mode.
     */
    public var kvCompression: KvCompression
    /**
     * Pinned-prefix length for Phase-1.5 context shift on overflow.
     * `0` disables shift; overflow returns `ContextOverflow` error.
     */
    public var nKeep: UInt32
    /**
     * Deterministic sampling seed. `None` = fresh entropy per call.
     */
    public var seed: UInt64?
    /**
     * Chunked-prefill ubatch size. `0` = monolithic prefill.
     */
    public var ubatchSize: UInt32

    // Default memberwise initializers are never public by default, so we
    // declare one manually.
    public init(
        /**
         * Cap on total tokens held in KV. `None` → model's default
         * `max_seq_len`.
         */maxSeqLen: UInt32?, 
        /**
         * KV cache compression mode.
         */kvCompression: KvCompression, 
        /**
         * Pinned-prefix length for Phase-1.5 context shift on overflow.
         * `0` disables shift; overflow returns `ContextOverflow` error.
         */nKeep: UInt32, 
        /**
         * Deterministic sampling seed. `None` = fresh entropy per call.
         */seed: UInt64?, 
        /**
         * Chunked-prefill ubatch size. `0` = monolithic prefill.
         */ubatchSize: UInt32) {
        self.maxSeqLen = maxSeqLen
        self.kvCompression = kvCompression
        self.nKeep = nKeep
        self.seed = seed
        self.ubatchSize = ubatchSize
    }

    

    
}

#if compiler(>=6)
extension SessionConfig: Sendable {}
#endif

#if swift(>=5.8)
@_documentation(visibility: private)
#endif
public struct FfiConverterTypeSessionConfig: FfiConverterRustBuffer {
    public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> SessionConfig {
        return
            try SessionConfig(
                maxSeqLen: FfiConverterOptionUInt32.read(from: &buf), 
                kvCompression: FfiConverterTypeKvCompression.read(from: &buf), 
                nKeep: FfiConverterUInt32.read(from: &buf), 
                seed: FfiConverterOptionUInt64.read(from: &buf), 
                ubatchSize: FfiConverterUInt32.read(from: &buf)
        )
    }

    public static func write(_ value: SessionConfig, into buf: inout [UInt8]) {
        FfiConverterOptionUInt32.write(value.maxSeqLen, into: &buf)
        FfiConverterTypeKvCompression.write(value.kvCompression, into: &buf)
        FfiConverterUInt32.write(value.nKeep, into: &buf)
        FfiConverterOptionUInt64.write(value.seed, into: &buf)
        FfiConverterUInt32.write(value.ubatchSize, into: &buf)
    }
}


#if swift(>=5.8)
@_documentation(visibility: private)
#endif
public func FfiConverterTypeSessionConfig_lift(_ buf: RustBuffer) throws -> SessionConfig {
    return try FfiConverterTypeSessionConfig.lift(buf)
}

#if swift(>=5.8)
@_documentation(visibility: private)
#endif
public func FfiConverterTypeSessionConfig_lower(_ value: SessionConfig) -> RustBuffer {
    return FfiConverterTypeSessionConfig.lower(value)
}

// Note that we don't yet support `indirect` for enums.
// See https://github.com/mozilla/uniffi-rs/issues/396 for further discussion.
/**
 * Compute-backend selector. Mirrors [`cera::BackendPreference`];
 * kept as a separate type so the `cera` crate doesn't carry UniFFI
 * annotations.
 */

public enum BackendPreference: Equatable, Hashable {
    
    /**
     * Probe Metal → GPU → CPU at load time.
     */
    case auto
    case cpu
    /**
     * `wgpu` (Vulkan / Metal / DX12). Requires the `gpu` feature.
     */
    case gpu
    /**
     * Native Metal. Requires the `metal` feature + macOS.
     */
    case metal





}

#if compiler(>=6)
extension BackendPreference: Sendable {}
#endif

#if swift(>=5.8)
@_documentation(visibility: private)
#endif
public struct FfiConverterTypeBackendPreference: FfiConverterRustBuffer {
    typealias SwiftType = BackendPreference

    public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> BackendPreference {
        let variant: Int32 = try readInt(&buf)
        switch variant {
        
        case 1: return .auto
        
        case 2: return .cpu
        
        case 3: return .gpu
        
        case 4: return .metal
        
        default: throw UniffiInternalError.unexpectedEnumCase
        }
    }

    public static func write(_ value: BackendPreference, into buf: inout [UInt8]) {
        switch value {
        
        
        case .auto:
            writeInt(&buf, Int32(1))
        
        
        case .cpu:
            writeInt(&buf, Int32(2))
        
        
        case .gpu:
            writeInt(&buf, Int32(3))
        
        
        case .metal:
            writeInt(&buf, Int32(4))
        
        }
    }
}


#if swift(>=5.8)
@_documentation(visibility: private)
#endif
public func FfiConverterTypeBackendPreference_lift(_ buf: RustBuffer) throws -> BackendPreference {
    return try FfiConverterTypeBackendPreference.lift(buf)
}

#if swift(>=5.8)
@_documentation(visibility: private)
#endif
public func FfiConverterTypeBackendPreference_lower(_ value: BackendPreference) -> RustBuffer {
    return FfiConverterTypeBackendPreference.lower(value)
}



/**
 * Typed error surface for `cera-ffi`. Mirrors [`cera::CeraError`] one-
 * to-one so foreign callers can pattern-match on error class (Kotlin
 * `when`, Swift `switch`, Python `match`) instead of string-sniffing
 * a generic message.
 *
 * `Backend` is **not** a silent fallback for unmapped `cera::CeraError`
 * variants — the `From<CeraError>` impl is exhaustive, so adding a
 * new cera variant breaks compilation here. `Backend` exists solely
 * for FFI-internal errors that have no cera analog: `JoinError` from
 * a panicking `spawn_blocking` task, a poisoned `Session::inner`
 * mutex, 32-bit `u64 → usize` overflow in `EngineConfig::try_from`.
 *
 * Every variant carries the data needed to act on it:
 * `ContextOverflow` exposes `max_seq_len` and `by` so callers can
 * reset or truncate rather than re-reading the message;
 * `UnsupportedInferenceType` exposes the offending value;
 * `Io` preserves the underlying OS error message as a string since
 * `io::Error` isn't UniFFI-marshallable.
 *
 * `#[error(...)]` format strings match `cera::CeraError` exactly for
 * every shared variant, so `Display` output is identical whether the
 * error originates from cera directly or routes through the FFI
 * wrapper. Pinned by `ffi_error_display_matches_cera_error_for_every_shared_variant`.
 */
public enum FfiError: Swift.Error, Equatable, Hashable, Foundation.LocalizedError {

    
    
    /**
     * The loaded model doesn't support the modality the caller
     * requested (e.g. `append_audio` on a text-only LLM).
     */
    case UnsupportedModality
    /**
     * The manifest's `inference_type` is one cera doesn't recognize
     * at this version. Field carries the offending string.
     */
    case UnsupportedInferenceType(inferenceType: String
    )
    /**
     * A concurrent `generate*` call is already in flight on this
     * session. Rust side guards with a mutex; this surfaces when the
     * FFI detects contention.
     */
    case Busy
    /**
     * The caller (or the cancel-on-drop guard) flipped the cancel
     * atomic mid-call. Surfaces from `append_text`, `append_tokens`,
     * and `append_audio` when chunked prefill detects the cancel
     * flag between micro-batches and aborts (see
     * [`cera::Session::append_tokens`] for the chunked-prefill
     * mechanism). Call [`Session::clear_cancel`] to reset the flag
     * so the next call can proceed.
     *
     * `generate` reports cancellation via a different path: the
     * call still returns `Ok` with a [`GenerateOutput`] whose
     * `finish_reason` is set to `Cancelled`. Two paths because
     * chunked prefill has nothing useful to return on cancel (no
     * decoded tokens) while decode has accumulated tokens worth
     * preserving.
     */
    case Cancelled
    /**
     * The context window is full and the session can't shift to make
     * room (e.g. `n_keep == 0`, TurboQuant caches, or the active
     * model doesn't support rope-shift). `max_seq_len` is the cap
     * that was hit; `by` is the overshoot in tokens.
     */
    case ContextOverflow(maxSeqLen: UInt32, by: UInt32
    )
    /**
     * Input buffer was empty (e.g. `append_text("")`, or decode with
     * no prefill state).
     */
    case EmptyInput
    /**
     * Filesystem / mmap / network error surfaced from cera. The
     * underlying `io::Error` isn't marshallable, so the message is
     * flattened to a string. Callers that need the raw kind should
     * parse the `detail` field or open an issue to request a typed
     * field.
     *
     * Field is named `detail` rather than `message` because UniFFI's
     * 0.31 Kotlin generator emits `class Io(val `message`) : FfiException()`
     * AND `override val message` in the body when the field is literally
     * named `message`, producing a "conflicting declarations" error
     * (the constructor param collides with the inherited
     * `Throwable.message` override). Renaming to `detail` sidesteps
     * the collision.
     *
     * Format string matches `cera::CeraError::Io`'s `"io: {0}"` so
     * foreign `.toString()` / `String(describing:)` gives the same
     * output Rust consumers see.
     */
    case Io(detail: String
    )
    /**
     * FFI-internal error with no cera analog: `JoinError` from a
     * panicking `spawn_blocking` task, poisoned `Session::inner`
     * mutex, 32-bit `u64 → usize` overflow in `EngineConfig::try_from`,
     * or `cera::CeraError::Backend` routed through the `From` impl.
     * Format string matches `cera::CeraError::Backend`'s
     * `"backend: {0}"` — FFI-internal constructors that have already
     * formatted a descriptive message (e.g. "generate_async join
     * error: ...") still read cleanly with the `backend:` label.
     *
     * Field is named `detail` rather than `message` for the same
     * `Throwable.message` collision reason as [`FfiError::Io`].
     */
    case Backend(detail: String
    )
    /**
     * The GBNF grammar string passed in `GenerateOpts.grammar` failed to
     * compile. Grammar compilation happens in the FFI wrapper (the compiled
     * grammar object can't cross the boundary, so callers pass the source text
     * and it's parsed here). `detail` carries the parser's diagnostic.
     */
    case GrammarParse(detail: String
    )
    /**
     * A token id passed to `hidden_states_for_tokens` (or another
     * token-taking method) was `>= vocab_size`. Returned as a typed error
     * rather than tripping the model-layer `assert!` (whose panic would
     * unwind through the held session lock and poison it). Mirrors
     * `cera::CeraError::InvalidToken`.
     */
    case InvalidToken(id: UInt32, vocabSize: UInt32
    )
    /**
     * A LoRA adapter failed to load ([`LoraAdapters::from_gguf`] /
     * [`LoraAdapters::from_safetensors`]) or was incompatible with the model at
     * attach time (wrong dimensions). `detail` carries the diagnostic.
     */
    case LoraParse(detail: String
    )

    

    

    
    public var errorDescription: String? {
        String(reflecting: self)
    }
    
}

#if compiler(>=6)
extension FfiError: Sendable {}
#endif

#if swift(>=5.8)
@_documentation(visibility: private)
#endif
public struct FfiConverterTypeFfiError: FfiConverterRustBuffer {
    typealias SwiftType = FfiError

    public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> FfiError {
        let variant: Int32 = try readInt(&buf)
        switch variant {

        

        
        case 1: return .UnsupportedModality
        case 2: return .UnsupportedInferenceType(
            inferenceType: try FfiConverterString.read(from: &buf)
            )
        case 3: return .Busy
        case 4: return .Cancelled
        case 5: return .ContextOverflow(
            maxSeqLen: try FfiConverterUInt32.read(from: &buf), 
            by: try FfiConverterUInt32.read(from: &buf)
            )
        case 6: return .EmptyInput
        case 7: return .Io(
            detail: try FfiConverterString.read(from: &buf)
            )
        case 8: return .Backend(
            detail: try FfiConverterString.read(from: &buf)
            )
        case 9: return .GrammarParse(
            detail: try FfiConverterString.read(from: &buf)
            )
        case 10: return .InvalidToken(
            id: try FfiConverterUInt32.read(from: &buf), 
            vocabSize: try FfiConverterUInt32.read(from: &buf)
            )
        case 11: return .LoraParse(
            detail: try FfiConverterString.read(from: &buf)
            )

         default: throw UniffiInternalError.unexpectedEnumCase
        }
    }

    public static func write(_ value: FfiError, into buf: inout [UInt8]) {
        switch value {

        

        
        
        case .UnsupportedModality:
            writeInt(&buf, Int32(1))
        
        
        case let .UnsupportedInferenceType(inferenceType):
            writeInt(&buf, Int32(2))
            FfiConverterString.write(inferenceType, into: &buf)
            
        
        case .Busy:
            writeInt(&buf, Int32(3))
        
        
        case .Cancelled:
            writeInt(&buf, Int32(4))
        
        
        case let .ContextOverflow(maxSeqLen,by):
            writeInt(&buf, Int32(5))
            FfiConverterUInt32.write(maxSeqLen, into: &buf)
            FfiConverterUInt32.write(by, into: &buf)
            
        
        case .EmptyInput:
            writeInt(&buf, Int32(6))
        
        
        case let .Io(detail):
            writeInt(&buf, Int32(7))
            FfiConverterString.write(detail, into: &buf)
            
        
        case let .Backend(detail):
            writeInt(&buf, Int32(8))
            FfiConverterString.write(detail, into: &buf)
            
        
        case let .GrammarParse(detail):
            writeInt(&buf, Int32(9))
            FfiConverterString.write(detail, into: &buf)
            
        
        case let .InvalidToken(id,vocabSize):
            writeInt(&buf, Int32(10))
            FfiConverterUInt32.write(id, into: &buf)
            FfiConverterUInt32.write(vocabSize, into: &buf)
            
        
        case let .LoraParse(detail):
            writeInt(&buf, Int32(11))
            FfiConverterString.write(detail, into: &buf)
            
        }
    }
}


#if swift(>=5.8)
@_documentation(visibility: private)
#endif
public func FfiConverterTypeFfiError_lift(_ buf: RustBuffer) throws -> FfiError {
    return try FfiConverterTypeFfiError.lift(buf)
}

#if swift(>=5.8)
@_documentation(visibility: private)
#endif
public func FfiConverterTypeFfiError_lower(_ value: FfiError) -> RustBuffer {
    return FfiConverterTypeFfiError.lower(value)
}

// Note that we don't yet support `indirect` for enums.
// See https://github.com/mozilla/uniffi-rs/issues/396 for further discussion.
/**
 * Why a decode loop exited. Mirrors [`cera::FinishReason`].
 */

public enum FinishReason: Equatable, Hashable {
    
    case maxTokens
    case stop
    case cancelled
    case contextFull
    /**
     * A grammar constraint left no token allowed at this step — decoding
     * stopped because the grammar dead-ended. Only reachable when
     * `GenerateOpts.grammar` is set.
     */
    case grammarDeadEnd
    case error(message: String
    )





}

#if compiler(>=6)
extension FinishReason: Sendable {}
#endif

#if swift(>=5.8)
@_documentation(visibility: private)
#endif
public struct FfiConverterTypeFinishReason: FfiConverterRustBuffer {
    typealias SwiftType = FinishReason

    public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> FinishReason {
        let variant: Int32 = try readInt(&buf)
        switch variant {
        
        case 1: return .maxTokens
        
        case 2: return .stop
        
        case 3: return .cancelled
        
        case 4: return .contextFull
        
        case 5: return .grammarDeadEnd
        
        case 6: return .error(message: try FfiConverterString.read(from: &buf)
        )
        
        default: throw UniffiInternalError.unexpectedEnumCase
        }
    }

    public static func write(_ value: FinishReason, into buf: inout [UInt8]) {
        switch value {
        
        
        case .maxTokens:
            writeInt(&buf, Int32(1))
        
        
        case .stop:
            writeInt(&buf, Int32(2))
        
        
        case .cancelled:
            writeInt(&buf, Int32(3))
        
        
        case .contextFull:
            writeInt(&buf, Int32(4))
        
        
        case .grammarDeadEnd:
            writeInt(&buf, Int32(5))
        
        
        case let .error(message):
            writeInt(&buf, Int32(6))
            FfiConverterString.write(message, into: &buf)
            
        }
    }
}


#if swift(>=5.8)
@_documentation(visibility: private)
#endif
public func FfiConverterTypeFinishReason_lift(_ buf: RustBuffer) throws -> FinishReason {
    return try FfiConverterTypeFinishReason.lift(buf)
}

#if swift(>=5.8)
@_documentation(visibility: private)
#endif
public func FfiConverterTypeFinishReason_lower(_ value: FinishReason) -> RustBuffer {
    return FfiConverterTypeFinishReason.lower(value)
}


// Note that we don't yet support `indirect` for enums.
// See https://github.com/mozilla/uniffi-rs/issues/396 for further discussion.
/**
 * KV-cache compression mode. Mirrors [`cera::kv_cache::KvCompression`].
 * `TurboQuant` is honored by the CPU backend only; Metal / GPU ignore
 * the setting and use the f32 path.
 */

public enum KvCompression: Equatable, Hashable {
    
    /**
     * No compression — f32 keys and values (default).
     */
    case none
    /**
     * TurboQuant compression. Both `keys` + `values` true is the
     * production configuration; toggling them individually is
     * primarily for debugging the drift contribution of each side.
     * `seed` drives the per-layer randomized Hadamard rotations.
     */
    case turboQuant(seed: UInt64, keys: Bool, values: Bool
    )





}

#if compiler(>=6)
extension KvCompression: Sendable {}
#endif

#if swift(>=5.8)
@_documentation(visibility: private)
#endif
public struct FfiConverterTypeKvCompression: FfiConverterRustBuffer {
    typealias SwiftType = KvCompression

    public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> KvCompression {
        let variant: Int32 = try readInt(&buf)
        switch variant {
        
        case 1: return .none
        
        case 2: return .turboQuant(seed: try FfiConverterUInt64.read(from: &buf), keys: try FfiConverterBool.read(from: &buf), values: try FfiConverterBool.read(from: &buf)
        )
        
        default: throw UniffiInternalError.unexpectedEnumCase
        }
    }

    public static func write(_ value: KvCompression, into buf: inout [UInt8]) {
        switch value {
        
        
        case .none:
            writeInt(&buf, Int32(1))
        
        
        case let .turboQuant(seed,keys,values):
            writeInt(&buf, Int32(2))
            FfiConverterUInt64.write(seed, into: &buf)
            FfiConverterBool.write(keys, into: &buf)
            FfiConverterBool.write(values, into: &buf)
            
        }
    }
}


#if swift(>=5.8)
@_documentation(visibility: private)
#endif
public func FfiConverterTypeKvCompression_lift(_ buf: RustBuffer) throws -> KvCompression {
    return try FfiConverterTypeKvCompression.lift(buf)
}

#if swift(>=5.8)
@_documentation(visibility: private)
#endif
public func FfiConverterTypeKvCompression_lower(_ value: KvCompression) -> RustBuffer {
    return FfiConverterTypeKvCompression.lower(value)
}


#if swift(>=5.8)
@_documentation(visibility: private)
#endif
fileprivate struct FfiConverterOptionUInt32: FfiConverterRustBuffer {
    typealias SwiftType = UInt32?

    public static func write(_ value: SwiftType, into buf: inout [UInt8]) {
        guard let value = value else {
            writeInt(&buf, Int8(0))
            return
        }
        writeInt(&buf, Int8(1))
        FfiConverterUInt32.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 FfiConverterUInt32.read(from: &buf)
        default: throw UniffiInternalError.unexpectedOptionalTag
        }
    }
}

#if swift(>=5.8)
@_documentation(visibility: private)
#endif
fileprivate struct FfiConverterOptionUInt64: FfiConverterRustBuffer {
    typealias SwiftType = UInt64?

    public static func write(_ value: SwiftType, into buf: inout [UInt8]) {
        guard let value = value else {
            writeInt(&buf, Int8(0))
            return
        }
        writeInt(&buf, Int8(1))
        FfiConverterUInt64.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 FfiConverterUInt64.read(from: &buf)
        default: throw UniffiInternalError.unexpectedOptionalTag
        }
    }
}

#if swift(>=5.8)
@_documentation(visibility: private)
#endif
fileprivate struct FfiConverterOptionFloat: FfiConverterRustBuffer {
    typealias SwiftType = Float?

    public static func write(_ value: SwiftType, into buf: inout [UInt8]) {
        guard let value = value else {
            writeInt(&buf, Int8(0))
            return
        }
        writeInt(&buf, Int8(1))
        FfiConverterFloat.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 FfiConverterFloat.read(from: &buf)
        default: throw UniffiInternalError.unexpectedOptionalTag
        }
    }
}

#if swift(>=5.8)
@_documentation(visibility: private)
#endif
fileprivate 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
        }
    }
}

#if swift(>=5.8)
@_documentation(visibility: private)
#endif
fileprivate struct FfiConverterOptionTypeBundleRepo: FfiConverterRustBuffer {
    typealias SwiftType = BundleRepo?

    public static func write(_ value: SwiftType, into buf: inout [UInt8]) {
        guard let value = value else {
            writeInt(&buf, Int8(0))
            return
        }
        writeInt(&buf, Int8(1))
        FfiConverterTypeBundleRepo.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 FfiConverterTypeBundleRepo.read(from: &buf)
        default: throw UniffiInternalError.unexpectedOptionalTag
        }
    }
}

#if swift(>=5.8)
@_documentation(visibility: private)
#endif
fileprivate struct FfiConverterSequenceUInt32: FfiConverterRustBuffer {
    typealias SwiftType = [UInt32]

    public static func write(_ value: [UInt32], into buf: inout [UInt8]) {
        let len = Int32(value.count)
        writeInt(&buf, len)
        for item in value {
            FfiConverterUInt32.write(item, into: &buf)
        }
    }

    public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> [UInt32] {
        let len: Int32 = try readInt(&buf)
        var seq = [UInt32]()
        seq.reserveCapacity(Int(len))
        for _ in 0 ..< len {
            seq.append(try FfiConverterUInt32.read(from: &buf))
        }
        return seq
    }
}

#if swift(>=5.8)
@_documentation(visibility: private)
#endif
fileprivate struct FfiConverterSequenceFloat: FfiConverterRustBuffer {
    typealias SwiftType = [Float]

    public static func write(_ value: [Float], into buf: inout [UInt8]) {
        let len = Int32(value.count)
        writeInt(&buf, len)
        for item in value {
            FfiConverterFloat.write(item, into: &buf)
        }
    }

    public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> [Float] {
        let len: Int32 = try readInt(&buf)
        var seq = [Float]()
        seq.reserveCapacity(Int(len))
        for _ in 0 ..< len {
            seq.append(try FfiConverterFloat.read(from: &buf))
        }
        return seq
    }
}

#if swift(>=5.8)
@_documentation(visibility: private)
#endif
fileprivate struct FfiConverterSequenceTypeChatMessage: FfiConverterRustBuffer {
    typealias SwiftType = [ChatMessage]

    public static func write(_ value: [ChatMessage], into buf: inout [UInt8]) {
        let len = Int32(value.count)
        writeInt(&buf, len)
        for item in value {
            FfiConverterTypeChatMessage.write(item, into: &buf)
        }
    }

    public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> [ChatMessage] {
        let len: Int32 = try readInt(&buf)
        var seq = [ChatMessage]()
        seq.reserveCapacity(Int(len))
        for _ in 0 ..< len {
            seq.append(try FfiConverterTypeChatMessage.read(from: &buf))
        }
        return seq
    }
}
private let UNIFFI_RUST_FUTURE_POLL_READY: Int8 = 0
private let UNIFFI_RUST_FUTURE_POLL_WAKE: Int8 = 1

fileprivate let uniffiContinuationHandleMap = UniffiHandleMap<UnsafeContinuation<Int8, Never>>()

fileprivate func uniffiRustCallAsync<F, T>(
    rustFutureFunc: () -> UInt64,
    pollFunc: (UInt64, @escaping UniffiRustFutureContinuationCallback, UInt64) -> (),
    completeFunc: (UInt64, UnsafeMutablePointer<RustCallStatus>) -> F,
    freeFunc: (UInt64) -> (),
    liftFunc: (F) throws -> T,
    errorHandler: ((RustBuffer) throws -> Swift.Error)?
) async throws -> T {
    // Make sure to call the ensure init function since future creation doesn't have a
    // RustCallStatus param, so doesn't use makeRustCall()
    uniffiEnsureCeraFfiInitialized()
    let rustFuture = rustFutureFunc()
    defer {
        freeFunc(rustFuture)
    }
    var pollResult: Int8;
    repeat {
        pollResult = await withUnsafeContinuation {
            pollFunc(
                rustFuture,
                { handle, pollResult in
                    uniffiFutureContinuationCallback(handle: handle, pollResult: pollResult)
                },
                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.
fileprivate func uniffiFutureContinuationCallback(handle: UInt64, pollResult: Int8) {
    if let continuation = try? uniffiContinuationHandleMap.remove(handle: handle) {
        continuation.resume(returning: pollResult)
    } else {
        print("uniffiFutureContinuationCallback invalid handle")
    }
}
/**
 * Version string of the `cera-ffi` crate. Useful as a smoke test
 * from the foreign-language side — if this is callable, the binding
 * pipeline works end-to-end.
 */
public func ceraFfiVersion() -> String  {
    return try!  FfiConverterString.lift(try! rustCall() {
    uniffi_cera_ffi_fn_func_cera_ffi_version($0
    )
})
}
/**
 * One-line CPU backend report for this host — the resolved SIMD tier plus the
 * detected feature flags, e.g. `cpu: tier=neon+dotprod [neon dotprod]`. A host
 * property independent of any loaded model; callable without an engine. Handy
 * for telemetry and bug reports (tells you which kernel path actually ran).
 */
public func cpuBackendReport() -> String  {
    return try!  FfiConverterString.lift(try! rustCall() {
    uniffi_cera_ffi_fn_func_cpu_backend_report($0
    )
})
}

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 let initializationResult: InitializationResult = {
    // Get the bindings contract version from our ComponentInterface
    let bindings_contract_version = 30
    // Get the scaffolding contract version by calling the into the dylib
    let scaffolding_contract_version = ffi_cera_ffi_uniffi_contract_version()
    if bindings_contract_version != scaffolding_contract_version {
        return InitializationResult.contractVersionMismatch
    }
    if (uniffi_cera_ffi_checksum_func_cera_ffi_version() != 39330) {
        return InitializationResult.apiChecksumMismatch
    }
    if (uniffi_cera_ffi_checksum_func_cpu_backend_report() != 61086) {
        return InitializationResult.apiChecksumMismatch
    }
    if (uniffi_cera_ffi_checksum_method_bundlerepo_cache_size() != 29364) {
        return InitializationResult.apiChecksumMismatch
    }
    if (uniffi_cera_ffi_checksum_method_bundlerepo_clear_cache() != 11512) {
        return InitializationResult.apiChecksumMismatch
    }
    if (uniffi_cera_ffi_checksum_method_bundlerepo_store_dir() != 40876) {
        return InitializationResult.apiChecksumMismatch
    }
    if (uniffi_cera_ffi_checksum_method_ceraengine_apply_chat_template() != 38712) {
        return InitializationResult.apiChecksumMismatch
    }
    if (uniffi_cera_ffi_checksum_method_ceraengine_bos_token() != 30744) {
        return InitializationResult.apiChecksumMismatch
    }
    if (uniffi_cera_ffi_checksum_method_ceraengine_capabilities() != 65060) {
        return InitializationResult.apiChecksumMismatch
    }
    if (uniffi_cera_ffi_checksum_method_ceraengine_context_size() != 47091) {
        return InitializationResult.apiChecksumMismatch
    }
    if (uniffi_cera_ffi_checksum_method_ceraengine_decode_tokens() != 27407) {
        return InitializationResult.apiChecksumMismatch
    }
    if (uniffi_cera_ffi_checksum_method_ceraengine_encode_text() != 52220) {
        return InitializationResult.apiChecksumMismatch
    }
    if (uniffi_cera_ffi_checksum_method_ceraengine_eos_token() != 21294) {
        return InitializationResult.apiChecksumMismatch
    }
    if (uniffi_cera_ffi_checksum_method_ceraengine_has_chat_template() != 63563) {
        return InitializationResult.apiChecksumMismatch
    }
    if (uniffi_cera_ffi_checksum_method_ceraengine_is_special_token() != 7395) {
        return InitializationResult.apiChecksumMismatch
    }
    if (uniffi_cera_ffi_checksum_method_ceraengine_metadata() != 46262) {
        return InitializationResult.apiChecksumMismatch
    }
    if (uniffi_cera_ffi_checksum_method_ceraengine_new_session() != 54382) {
        return InitializationResult.apiChecksumMismatch
    }
    if (uniffi_cera_ffi_checksum_method_ceraengine_special_token_id() != 35790) {
        return InitializationResult.apiChecksumMismatch
    }
    if (uniffi_cera_ffi_checksum_method_ceraengine_transcribe() != 9680) {
        return InitializationResult.apiChecksumMismatch
    }
    if (uniffi_cera_ffi_checksum_method_ceraengine_vocab_size() != 13487) {
        return InitializationResult.apiChecksumMismatch
    }
    if (uniffi_cera_ffi_checksum_method_downloadprogresssink_on_progress() != 33688) {
        return InitializationResult.apiChecksumMismatch
    }
    if (uniffi_cera_ffi_checksum_method_loraadapters_target_count() != 23137) {
        return InitializationResult.apiChecksumMismatch
    }
    if (uniffi_cera_ffi_checksum_method_modalitysink_on_text_tokens() != 50332) {
        return InitializationResult.apiChecksumMismatch
    }
    if (uniffi_cera_ffi_checksum_method_modalitysink_on_audio_frames() != 54889) {
        return InitializationResult.apiChecksumMismatch
    }
    if (uniffi_cera_ffi_checksum_method_modalitysink_on_done() != 2908) {
        return InitializationResult.apiChecksumMismatch
    }
    if (uniffi_cera_ffi_checksum_method_session_append_audio() != 44552) {
        return InitializationResult.apiChecksumMismatch
    }
    if (uniffi_cera_ffi_checksum_method_session_append_image() != 13190) {
        return InitializationResult.apiChecksumMismatch
    }
    if (uniffi_cera_ffi_checksum_method_session_append_text() != 13301) {
        return InitializationResult.apiChecksumMismatch
    }
    if (uniffi_cera_ffi_checksum_method_session_append_tokens() != 1227) {
        return InitializationResult.apiChecksumMismatch
    }
    if (uniffi_cera_ffi_checksum_method_session_attach_lora() != 28982) {
        return InitializationResult.apiChecksumMismatch
    }
    if (uniffi_cera_ffi_checksum_method_session_cancel() != 7555) {
        return InitializationResult.apiChecksumMismatch
    }
    if (uniffi_cera_ffi_checksum_method_session_capabilities() != 8147) {
        return InitializationResult.apiChecksumMismatch
    }
    if (uniffi_cera_ffi_checksum_method_session_clear_cancel() != 11168) {
        return InitializationResult.apiChecksumMismatch
    }
    if (uniffi_cera_ffi_checksum_method_session_generate() != 57005) {
        return InitializationResult.apiChecksumMismatch
    }
    if (uniffi_cera_ffi_checksum_method_session_generate_async() != 58489) {
        return InitializationResult.apiChecksumMismatch
    }
    if (uniffi_cera_ffi_checksum_method_session_generate_streaming() != 43707) {
        return InitializationResult.apiChecksumMismatch
    }
    if (uniffi_cera_ffi_checksum_method_session_generate_streaming_async() != 12198) {
        return InitializationResult.apiChecksumMismatch
    }
    if (uniffi_cera_ffi_checksum_method_session_has_lora() != 13931) {
        return InitializationResult.apiChecksumMismatch
    }
    if (uniffi_cera_ffi_checksum_method_session_hidden_size() != 46607) {
        return InitializationResult.apiChecksumMismatch
    }
    if (uniffi_cera_ffi_checksum_method_session_hidden_states_for_text() != 54184) {
        return InitializationResult.apiChecksumMismatch
    }
    if (uniffi_cera_ffi_checksum_method_session_hidden_states_for_tokens() != 65100) {
        return InitializationResult.apiChecksumMismatch
    }
    if (uniffi_cera_ffi_checksum_method_session_hidden_states_mean_pooled() != 61246) {
        return InitializationResult.apiChecksumMismatch
    }
    if (uniffi_cera_ffi_checksum_method_session_position() != 13264) {
        return InitializationResult.apiChecksumMismatch
    }
    if (uniffi_cera_ffi_checksum_method_session_remove_lora() != 29534) {
        return InitializationResult.apiChecksumMismatch
    }
    if (uniffi_cera_ffi_checksum_method_session_reset() != 48041) {
        return InitializationResult.apiChecksumMismatch
    }
    if (uniffi_cera_ffi_checksum_method_session_set_image_max_long_size() != 36283) {
        return InitializationResult.apiChecksumMismatch
    }
    if (uniffi_cera_ffi_checksum_constructor_bundlerepo_new() != 15544) {
        return InitializationResult.apiChecksumMismatch
    }
    if (uniffi_cera_ffi_checksum_constructor_bundlerepo_with_progress() != 24631) {
        return InitializationResult.apiChecksumMismatch
    }
    if (uniffi_cera_ffi_checksum_constructor_ceraengine_from_bundle_id() != 60717) {
        return InitializationResult.apiChecksumMismatch
    }
    if (uniffi_cera_ffi_checksum_constructor_ceraengine_from_bundle_id_async() != 14088) {
        return InitializationResult.apiChecksumMismatch
    }
    if (uniffi_cera_ffi_checksum_constructor_ceraengine_from_path() != 64420) {
        return InitializationResult.apiChecksumMismatch
    }
    if (uniffi_cera_ffi_checksum_constructor_loraadapters_from_gguf() != 57598) {
        return InitializationResult.apiChecksumMismatch
    }
    if (uniffi_cera_ffi_checksum_constructor_loraadapters_from_safetensors() != 11183) {
        return InitializationResult.apiChecksumMismatch
    }

    uniffiCallbackInitDownloadProgressSink()
    uniffiCallbackInitModalitySink()
    return InitializationResult.ok
}()

// Make the ensure init function public so that other modules which have external type references to
// our types can call it.
public func uniffiEnsureCeraFfiInitialized() {
    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