// This file was autogenerated by some hot garbage in the `uniffi` crate.
// Trust me, you don't want to mess with it!

@file:Suppress("NAME_SHADOWING")

package mozilla.appservices.suggest

// Common helper code.
//
// Ideally this would live in a separate .kt file where it can be unittested etc
// in isolation, and perhaps even published as a re-useable package.
//
// However, it's important that the details of how this helper code works (e.g. the
// way that different builtin types are passed across the FFI) exactly match what's
// expected by the Rust code on the other side of the interface. In practice right
// now that means coming from the exact some version of `uniffi` that was used to
// compile the Rust component. The easiest way to ensure this is to bundle the Kotlin
// helpers directly inline like we're doing here.

import com.sun.jna.Library
import com.sun.jna.IntegerType
import com.sun.jna.Native
import com.sun.jna.Pointer
import com.sun.jna.Structure
import com.sun.jna.Callback
import com.sun.jna.ptr.*
import java.nio.ByteBuffer
import java.nio.ByteOrder
import java.nio.CharBuffer
import java.nio.charset.CodingErrorAction
import java.util.concurrent.atomic.AtomicLong
import java.util.concurrent.ConcurrentHashMap
import java.util.concurrent.atomic.AtomicBoolean
import mozilla.appservices.remotesettings.FfiConverterTypeRemoteSettingsServer
import mozilla.appservices.remotesettings.FfiConverterTypeRemoteSettingsService
import mozilla.appservices.remotesettings.RemoteSettingsServer
import mozilla.appservices.remotesettings.RemoteSettingsService
import mozilla.appservices.remotesettings.RustBuffer as RustBufferRemoteSettingsServer
import mozilla.appservices.remotesettings.RustBuffer as RustBufferRemoteSettingsService

// This is a helper for safely working with byte buffers returned from the Rust code.
// A rust-owned buffer is represented by its capacity, its current length, and a
// pointer to the underlying data.

/**
 * @suppress
 */
@Structure.FieldOrder("capacity", "len", "data")
open class RustBuffer : Structure() {
    // Note: `capacity` and `len` are actually `ULong` values, but JVM only supports signed values.
    // When dealing with these fields, make sure to call `toULong()`.
    @JvmField var capacity: Long = 0
    @JvmField var len: Long = 0
    @JvmField var data: Pointer? = null

    class ByValue: RustBuffer(), Structure.ByValue
    class ByReference: RustBuffer(), Structure.ByReference

   internal fun setValue(other: RustBuffer) {
        capacity = other.capacity
        len = other.len
        data = other.data
    }

    companion object {
        internal fun alloc(size: ULong = 0UL) = uniffiRustCall() { status ->
            // Note: need to convert the size to a `Long` value to make this work with JVM.
            UniffiLib.ffi_suggest_rustbuffer_alloc(size.toLong(), status)
        }.also {
            if(it.data == null) {
               throw RuntimeException("RustBuffer.alloc() returned null data pointer (size=${size})")
           }
        }

        internal fun create(capacity: ULong, len: ULong, data: Pointer?): RustBuffer.ByValue {
            var buf = RustBuffer.ByValue()
            buf.capacity = capacity.toLong()
            buf.len = len.toLong()
            buf.data = data
            return buf
        }

        internal fun free(buf: RustBuffer.ByValue) = uniffiRustCall() { status ->
            UniffiLib.ffi_suggest_rustbuffer_free(buf, status)
        }
    }

    @Suppress("TooGenericExceptionThrown")
    fun asByteBuffer() =
        this.data?.getByteBuffer(0, this.len)?.also {
            it.order(ByteOrder.BIG_ENDIAN)
        }
}

// This is a helper for safely passing byte references into the rust code.
// It's not actually used at the moment, because there aren't many things that you
// can take a direct pointer to in the JVM, and if we're going to copy something
// then we might as well copy it into a `RustBuffer`. But it's here for API
// completeness.

@Structure.FieldOrder("len", "data")
internal open class ForeignBytes : Structure() {
    @JvmField var len: Int = 0
    @JvmField var data: Pointer? = null

    class ByValue : ForeignBytes(), Structure.ByValue
}
/**
 * The FfiConverter interface handles converter types to and from the FFI
 *
 * All implementing objects should be public to support external types.  When a
 * type is external we need to import it's FfiConverter.
 *
 * @suppress
 */
public interface FfiConverter<KotlinType, FfiType> {
    // Convert an FFI type to a Kotlin type
    fun lift(value: FfiType): KotlinType

    // Convert an Kotlin type to an FFI type
    fun lower(value: KotlinType): FfiType

    // Read a Kotlin type from a `ByteBuffer`
    fun read(buf: ByteBuffer): KotlinType

    // Calculate bytes to allocate when creating a `RustBuffer`
    //
    // This must return at least as many bytes as the write() function will
    // write. It can return more bytes than needed, for example when writing
    // Strings we can't know the exact bytes needed until we the UTF-8
    // encoding, so we pessimistically allocate the largest size possible (3
    // bytes per codepoint).  Allocating extra bytes is not really a big deal
    // because the `RustBuffer` is short-lived.
    fun allocationSize(value: KotlinType): ULong

    // Write a Kotlin type to a `ByteBuffer`
    fun write(value: KotlinType, buf: ByteBuffer)

    // Lower a value into a `RustBuffer`
    //
    // This method lowers a value into a `RustBuffer` rather than the normal
    // FfiType.  It's used by the callback interface code.  Callback interface
    // returns are always serialized into a `RustBuffer` regardless of their
    // normal FFI type.
    fun lowerIntoRustBuffer(value: KotlinType): RustBuffer.ByValue {
        val rbuf = RustBuffer.alloc(allocationSize(value))
        try {
            val bbuf = rbuf.data!!.getByteBuffer(0, rbuf.capacity).also {
                it.order(ByteOrder.BIG_ENDIAN)
            }
            write(value, bbuf)
            rbuf.writeField("len", bbuf.position().toLong())
            return rbuf
        } catch (e: Throwable) {
            RustBuffer.free(rbuf)
            throw e
        }
    }

    // Lift a value from a `RustBuffer`.
    //
    // This here mostly because of the symmetry with `lowerIntoRustBuffer()`.
    // It's currently only used by the `FfiConverterRustBuffer` class below.
    fun liftFromRustBuffer(rbuf: RustBuffer.ByValue): KotlinType {
        val byteBuf = rbuf.asByteBuffer()!!
        try {
           val item = read(byteBuf)
           if (byteBuf.hasRemaining()) {
               throw RuntimeException("junk remaining in buffer after lifting, something is very wrong!!")
           }
           return item
        } finally {
            RustBuffer.free(rbuf)
        }
    }
}

/**
 * FfiConverter that uses `RustBuffer` as the FfiType
 *
 * @suppress
 */
public interface FfiConverterRustBuffer<KotlinType>: FfiConverter<KotlinType, RustBuffer.ByValue> {
    override fun lift(value: RustBuffer.ByValue) = liftFromRustBuffer(value)
    override fun lower(value: KotlinType) = lowerIntoRustBuffer(value)
}
// A handful of classes and functions to support the generated data structures.
// This would be a good candidate for isolating in its own ffi-support lib.

internal const val UNIFFI_CALL_SUCCESS = 0.toByte()
internal const val UNIFFI_CALL_ERROR = 1.toByte()
internal const val UNIFFI_CALL_UNEXPECTED_ERROR = 2.toByte()

@Structure.FieldOrder("code", "error_buf")
internal open class UniffiRustCallStatus : Structure() {
    @JvmField var code: Byte = 0
    @JvmField var error_buf: RustBuffer.ByValue = RustBuffer.ByValue()

    class ByValue: UniffiRustCallStatus(), Structure.ByValue

    fun isSuccess(): Boolean {
        return code == UNIFFI_CALL_SUCCESS
    }

    fun isError(): Boolean {
        return code == UNIFFI_CALL_ERROR
    }

    fun isPanic(): Boolean {
        return code == UNIFFI_CALL_UNEXPECTED_ERROR
    }

    companion object {
        fun create(code: Byte, errorBuf: RustBuffer.ByValue): UniffiRustCallStatus.ByValue {
            val callStatus = UniffiRustCallStatus.ByValue()
            callStatus.code = code
            callStatus.error_buf = errorBuf
            return callStatus
        }
    }
}

class InternalException(message: String) : kotlin.Exception(message)

/**
 * Each top-level error class has a companion object that can lift the error from the call status's rust buffer
 *
 * @suppress
 */
interface UniffiRustCallStatusErrorHandler<E> {
    fun lift(error_buf: RustBuffer.ByValue): E;
}

// Helpers for calling Rust
// In practice we usually need to be synchronized to call this safely, so it doesn't
// synchronize itself

// Call a rust function that returns a Result<>.  Pass in the Error class companion that corresponds to the Err
private inline fun <U, E: kotlin.Exception> uniffiRustCallWithError(errorHandler: UniffiRustCallStatusErrorHandler<E>, callback: (UniffiRustCallStatus) -> U): U {
    var status = UniffiRustCallStatus()
    val return_value = callback(status)
    uniffiCheckCallStatus(errorHandler, status)
    return return_value
}

// Check UniffiRustCallStatus and throw an error if the call wasn't successful
private fun<E: kotlin.Exception> uniffiCheckCallStatus(errorHandler: UniffiRustCallStatusErrorHandler<E>, status: UniffiRustCallStatus) {
    if (status.isSuccess()) {
        return
    } else if (status.isError()) {
        throw errorHandler.lift(status.error_buf)
    } else if (status.isPanic()) {
        // 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 (status.error_buf.len > 0) {
            throw InternalException(FfiConverterString.lift(status.error_buf))
        } else {
            throw InternalException("Rust panic")
        }
    } else {
        throw InternalException("Unknown rust call status: $status.code")
    }
}

/**
 * UniffiRustCallStatusErrorHandler implementation for times when we don't expect a CALL_ERROR
 *
 * @suppress
 */
object UniffiNullRustCallStatusErrorHandler: UniffiRustCallStatusErrorHandler<InternalException> {
    override fun lift(error_buf: RustBuffer.ByValue): InternalException {
        RustBuffer.free(error_buf)
        return InternalException("Unexpected CALL_ERROR")
    }
}

// Call a rust function that returns a plain value
private inline fun <U> uniffiRustCall(callback: (UniffiRustCallStatus) -> U): U {
    return uniffiRustCallWithError(UniffiNullRustCallStatusErrorHandler, callback)
}

internal inline fun<T> uniffiTraitInterfaceCall(
    callStatus: UniffiRustCallStatus,
    makeCall: () -> T,
    writeReturn: (T) -> Unit,
) {
    try {
        writeReturn(makeCall())
    } catch(e: kotlin.Exception) {
        val err = try { e.stackTraceToString() } catch(_: Throwable) { "" }
        callStatus.code = UNIFFI_CALL_UNEXPECTED_ERROR
        callStatus.error_buf = FfiConverterString.lower(err)
    }
}

internal inline fun<T, reified E: Throwable> uniffiTraitInterfaceCallWithError(
    callStatus: UniffiRustCallStatus,
    makeCall: () -> T,
    writeReturn: (T) -> Unit,
    lowerError: (E) -> RustBuffer.ByValue
) {
    try {
        writeReturn(makeCall())
    } catch(e: kotlin.Exception) {
        if (e is E) {
            callStatus.code = UNIFFI_CALL_ERROR
            callStatus.error_buf = lowerError(e)
        } else {
            val err = try { e.stackTraceToString() } catch(_: Throwable) { "" }
            callStatus.code = UNIFFI_CALL_UNEXPECTED_ERROR
            callStatus.error_buf = FfiConverterString.lower(err)
        }
    }
}
// Initial value and increment amount for handles. 
// These ensure that Kotlin-generated handles always have the lowest bit set
private const val UNIFFI_HANDLEMAP_INITIAL = 1.toLong()
private const val UNIFFI_HANDLEMAP_DELTA = 2.toLong()

// Map handles to objects
//
// This is used pass an opaque 64-bit handle representing a foreign object to the Rust code.
internal class UniffiHandleMap<T: Any> {
    private val map = ConcurrentHashMap<Long, T>()
    // Start 
    private val counter = java.util.concurrent.atomic.AtomicLong(UNIFFI_HANDLEMAP_INITIAL)

    val size: Int
        get() = map.size

    // Insert a new object into the handle map and get a handle for it
    fun insert(obj: T): Long {
        val handle = counter.getAndAdd(UNIFFI_HANDLEMAP_DELTA)
        map.put(handle, obj)
        return handle
    }

    // Clone a handle, creating a new one
    fun clone(handle: Long): Long {
        val obj = map.get(handle) ?: throw InternalException("UniffiHandleMap.clone: Invalid handle")
        return insert(obj)
    }

    // Get an object from the handle map
    fun get(handle: Long): T {
        return map.get(handle) ?: throw InternalException("UniffiHandleMap.get: Invalid handle")
    }

    // Remove an entry from the handlemap and get the Kotlin object back
    fun remove(handle: Long): T {
        return map.remove(handle) ?: throw InternalException("UniffiHandleMap: Invalid handle")
    }
}

// Contains loading, initialization code,
// and the FFI Function declarations in a com.sun.jna.Library.
@Synchronized
private fun findLibraryName(componentName: String): String {
    val libOverride = System.getProperty("uniffi.component.$componentName.libraryOverride")
    if (libOverride != null) {
        return libOverride
    }
    return "megazord"
}

// Define FFI callback types
internal interface UniffiRustFutureContinuationCallback : com.sun.jna.Callback {
    fun callback(`data`: Long,`pollResult`: Byte,)
}
internal interface UniffiForeignFutureDroppedCallback : com.sun.jna.Callback {
    fun callback(`handle`: Long,)
}
internal interface UniffiCallbackInterfaceFree : com.sun.jna.Callback {
    fun callback(`handle`: Long,)
}
internal interface UniffiCallbackInterfaceClone : com.sun.jna.Callback {
    fun callback(`handle`: Long,)
    : Long
}
@Structure.FieldOrder("handle", "free")
internal open class UniffiForeignFutureDroppedCallbackStruct(
    @JvmField internal var `handle`: Long = 0.toLong(),
    @JvmField internal var `free`: UniffiForeignFutureDroppedCallback? = null,
) : Structure() {
    class UniffiByValue(
        `handle`: Long = 0.toLong(),
        `free`: UniffiForeignFutureDroppedCallback? = null,
    ): UniffiForeignFutureDroppedCallbackStruct(`handle`,`free`,), Structure.ByValue

   internal fun uniffiSetValue(other: UniffiForeignFutureDroppedCallbackStruct) {
        `handle` = other.`handle`
        `free` = other.`free`
    }

}
@Structure.FieldOrder("returnValue", "callStatus")
internal open class UniffiForeignFutureResultU8(
    @JvmField internal var `returnValue`: Byte = 0.toByte(),
    @JvmField internal var `callStatus`: UniffiRustCallStatus.ByValue = UniffiRustCallStatus.ByValue(),
) : Structure() {
    class UniffiByValue(
        `returnValue`: Byte = 0.toByte(),
        `callStatus`: UniffiRustCallStatus.ByValue = UniffiRustCallStatus.ByValue(),
    ): UniffiForeignFutureResultU8(`returnValue`,`callStatus`,), Structure.ByValue

   internal fun uniffiSetValue(other: UniffiForeignFutureResultU8) {
        `returnValue` = other.`returnValue`
        `callStatus` = other.`callStatus`
    }

}
internal interface UniffiForeignFutureCompleteU8 : com.sun.jna.Callback {
    fun callback(`callbackData`: Long,`result`: UniffiForeignFutureResultU8.UniffiByValue,)
}
@Structure.FieldOrder("returnValue", "callStatus")
internal open class UniffiForeignFutureResultI8(
    @JvmField internal var `returnValue`: Byte = 0.toByte(),
    @JvmField internal var `callStatus`: UniffiRustCallStatus.ByValue = UniffiRustCallStatus.ByValue(),
) : Structure() {
    class UniffiByValue(
        `returnValue`: Byte = 0.toByte(),
        `callStatus`: UniffiRustCallStatus.ByValue = UniffiRustCallStatus.ByValue(),
    ): UniffiForeignFutureResultI8(`returnValue`,`callStatus`,), Structure.ByValue

   internal fun uniffiSetValue(other: UniffiForeignFutureResultI8) {
        `returnValue` = other.`returnValue`
        `callStatus` = other.`callStatus`
    }

}
internal interface UniffiForeignFutureCompleteI8 : com.sun.jna.Callback {
    fun callback(`callbackData`: Long,`result`: UniffiForeignFutureResultI8.UniffiByValue,)
}
@Structure.FieldOrder("returnValue", "callStatus")
internal open class UniffiForeignFutureResultU16(
    @JvmField internal var `returnValue`: Short = 0.toShort(),
    @JvmField internal var `callStatus`: UniffiRustCallStatus.ByValue = UniffiRustCallStatus.ByValue(),
) : Structure() {
    class UniffiByValue(
        `returnValue`: Short = 0.toShort(),
        `callStatus`: UniffiRustCallStatus.ByValue = UniffiRustCallStatus.ByValue(),
    ): UniffiForeignFutureResultU16(`returnValue`,`callStatus`,), Structure.ByValue

   internal fun uniffiSetValue(other: UniffiForeignFutureResultU16) {
        `returnValue` = other.`returnValue`
        `callStatus` = other.`callStatus`
    }

}
internal interface UniffiForeignFutureCompleteU16 : com.sun.jna.Callback {
    fun callback(`callbackData`: Long,`result`: UniffiForeignFutureResultU16.UniffiByValue,)
}
@Structure.FieldOrder("returnValue", "callStatus")
internal open class UniffiForeignFutureResultI16(
    @JvmField internal var `returnValue`: Short = 0.toShort(),
    @JvmField internal var `callStatus`: UniffiRustCallStatus.ByValue = UniffiRustCallStatus.ByValue(),
) : Structure() {
    class UniffiByValue(
        `returnValue`: Short = 0.toShort(),
        `callStatus`: UniffiRustCallStatus.ByValue = UniffiRustCallStatus.ByValue(),
    ): UniffiForeignFutureResultI16(`returnValue`,`callStatus`,), Structure.ByValue

   internal fun uniffiSetValue(other: UniffiForeignFutureResultI16) {
        `returnValue` = other.`returnValue`
        `callStatus` = other.`callStatus`
    }

}
internal interface UniffiForeignFutureCompleteI16 : com.sun.jna.Callback {
    fun callback(`callbackData`: Long,`result`: UniffiForeignFutureResultI16.UniffiByValue,)
}
@Structure.FieldOrder("returnValue", "callStatus")
internal open class UniffiForeignFutureResultU32(
    @JvmField internal var `returnValue`: Int = 0,
    @JvmField internal var `callStatus`: UniffiRustCallStatus.ByValue = UniffiRustCallStatus.ByValue(),
) : Structure() {
    class UniffiByValue(
        `returnValue`: Int = 0,
        `callStatus`: UniffiRustCallStatus.ByValue = UniffiRustCallStatus.ByValue(),
    ): UniffiForeignFutureResultU32(`returnValue`,`callStatus`,), Structure.ByValue

   internal fun uniffiSetValue(other: UniffiForeignFutureResultU32) {
        `returnValue` = other.`returnValue`
        `callStatus` = other.`callStatus`
    }

}
internal interface UniffiForeignFutureCompleteU32 : com.sun.jna.Callback {
    fun callback(`callbackData`: Long,`result`: UniffiForeignFutureResultU32.UniffiByValue,)
}
@Structure.FieldOrder("returnValue", "callStatus")
internal open class UniffiForeignFutureResultI32(
    @JvmField internal var `returnValue`: Int = 0,
    @JvmField internal var `callStatus`: UniffiRustCallStatus.ByValue = UniffiRustCallStatus.ByValue(),
) : Structure() {
    class UniffiByValue(
        `returnValue`: Int = 0,
        `callStatus`: UniffiRustCallStatus.ByValue = UniffiRustCallStatus.ByValue(),
    ): UniffiForeignFutureResultI32(`returnValue`,`callStatus`,), Structure.ByValue

   internal fun uniffiSetValue(other: UniffiForeignFutureResultI32) {
        `returnValue` = other.`returnValue`
        `callStatus` = other.`callStatus`
    }

}
internal interface UniffiForeignFutureCompleteI32 : com.sun.jna.Callback {
    fun callback(`callbackData`: Long,`result`: UniffiForeignFutureResultI32.UniffiByValue,)
}
@Structure.FieldOrder("returnValue", "callStatus")
internal open class UniffiForeignFutureResultU64(
    @JvmField internal var `returnValue`: Long = 0.toLong(),
    @JvmField internal var `callStatus`: UniffiRustCallStatus.ByValue = UniffiRustCallStatus.ByValue(),
) : Structure() {
    class UniffiByValue(
        `returnValue`: Long = 0.toLong(),
        `callStatus`: UniffiRustCallStatus.ByValue = UniffiRustCallStatus.ByValue(),
    ): UniffiForeignFutureResultU64(`returnValue`,`callStatus`,), Structure.ByValue

   internal fun uniffiSetValue(other: UniffiForeignFutureResultU64) {
        `returnValue` = other.`returnValue`
        `callStatus` = other.`callStatus`
    }

}
internal interface UniffiForeignFutureCompleteU64 : com.sun.jna.Callback {
    fun callback(`callbackData`: Long,`result`: UniffiForeignFutureResultU64.UniffiByValue,)
}
@Structure.FieldOrder("returnValue", "callStatus")
internal open class UniffiForeignFutureResultI64(
    @JvmField internal var `returnValue`: Long = 0.toLong(),
    @JvmField internal var `callStatus`: UniffiRustCallStatus.ByValue = UniffiRustCallStatus.ByValue(),
) : Structure() {
    class UniffiByValue(
        `returnValue`: Long = 0.toLong(),
        `callStatus`: UniffiRustCallStatus.ByValue = UniffiRustCallStatus.ByValue(),
    ): UniffiForeignFutureResultI64(`returnValue`,`callStatus`,), Structure.ByValue

   internal fun uniffiSetValue(other: UniffiForeignFutureResultI64) {
        `returnValue` = other.`returnValue`
        `callStatus` = other.`callStatus`
    }

}
internal interface UniffiForeignFutureCompleteI64 : com.sun.jna.Callback {
    fun callback(`callbackData`: Long,`result`: UniffiForeignFutureResultI64.UniffiByValue,)
}
@Structure.FieldOrder("returnValue", "callStatus")
internal open class UniffiForeignFutureResultF32(
    @JvmField internal var `returnValue`: Float = 0.0f,
    @JvmField internal var `callStatus`: UniffiRustCallStatus.ByValue = UniffiRustCallStatus.ByValue(),
) : Structure() {
    class UniffiByValue(
        `returnValue`: Float = 0.0f,
        `callStatus`: UniffiRustCallStatus.ByValue = UniffiRustCallStatus.ByValue(),
    ): UniffiForeignFutureResultF32(`returnValue`,`callStatus`,), Structure.ByValue

   internal fun uniffiSetValue(other: UniffiForeignFutureResultF32) {
        `returnValue` = other.`returnValue`
        `callStatus` = other.`callStatus`
    }

}
internal interface UniffiForeignFutureCompleteF32 : com.sun.jna.Callback {
    fun callback(`callbackData`: Long,`result`: UniffiForeignFutureResultF32.UniffiByValue,)
}
@Structure.FieldOrder("returnValue", "callStatus")
internal open class UniffiForeignFutureResultF64(
    @JvmField internal var `returnValue`: Double = 0.0,
    @JvmField internal var `callStatus`: UniffiRustCallStatus.ByValue = UniffiRustCallStatus.ByValue(),
) : Structure() {
    class UniffiByValue(
        `returnValue`: Double = 0.0,
        `callStatus`: UniffiRustCallStatus.ByValue = UniffiRustCallStatus.ByValue(),
    ): UniffiForeignFutureResultF64(`returnValue`,`callStatus`,), Structure.ByValue

   internal fun uniffiSetValue(other: UniffiForeignFutureResultF64) {
        `returnValue` = other.`returnValue`
        `callStatus` = other.`callStatus`
    }

}
internal interface UniffiForeignFutureCompleteF64 : com.sun.jna.Callback {
    fun callback(`callbackData`: Long,`result`: UniffiForeignFutureResultF64.UniffiByValue,)
}
@Structure.FieldOrder("returnValue", "callStatus")
internal open class UniffiForeignFutureResultRustBuffer(
    @JvmField internal var `returnValue`: RustBuffer.ByValue = RustBuffer.ByValue(),
    @JvmField internal var `callStatus`: UniffiRustCallStatus.ByValue = UniffiRustCallStatus.ByValue(),
) : Structure() {
    class UniffiByValue(
        `returnValue`: RustBuffer.ByValue = RustBuffer.ByValue(),
        `callStatus`: UniffiRustCallStatus.ByValue = UniffiRustCallStatus.ByValue(),
    ): UniffiForeignFutureResultRustBuffer(`returnValue`,`callStatus`,), Structure.ByValue

   internal fun uniffiSetValue(other: UniffiForeignFutureResultRustBuffer) {
        `returnValue` = other.`returnValue`
        `callStatus` = other.`callStatus`
    }

}
internal interface UniffiForeignFutureCompleteRustBuffer : com.sun.jna.Callback {
    fun callback(`callbackData`: Long,`result`: UniffiForeignFutureResultRustBuffer.UniffiByValue,)
}
@Structure.FieldOrder("callStatus")
internal open class UniffiForeignFutureResultVoid(
    @JvmField internal var `callStatus`: UniffiRustCallStatus.ByValue = UniffiRustCallStatus.ByValue(),
) : Structure() {
    class UniffiByValue(
        `callStatus`: UniffiRustCallStatus.ByValue = UniffiRustCallStatus.ByValue(),
    ): UniffiForeignFutureResultVoid(`callStatus`,), Structure.ByValue

   internal fun uniffiSetValue(other: UniffiForeignFutureResultVoid) {
        `callStatus` = other.`callStatus`
    }

}
internal interface UniffiForeignFutureCompleteVoid : com.sun.jna.Callback {
    fun callback(`callbackData`: Long,`result`: UniffiForeignFutureResultVoid.UniffiByValue,)
}

// A JNA Library to expose the extern-C FFI definitions.
// This is an implementation detail which will be called internally by the public API.

// For large crates we prevent `MethodTooLargeException` (see #2340)
// N.B. the name of the extension is very misleading, since it is
// rather `InterfaceTooLargeException`, caused by too many methods
// in the interface for large crates.
//
// By splitting the otherwise huge interface into two parts
// * UniffiLib (this)
// * IntegrityCheckingUniffiLib
// And all checksum methods are put into `IntegrityCheckingUniffiLib`
// we allow for ~2x as many methods in the UniffiLib interface.
//
// Note: above all written when we used JNA's `loadIndirect` etc.
// We now use JNA's "direct mapping" - unclear if same considerations apply exactly.
internal object IntegrityCheckingUniffiLib {
    init {
        Native.register(IntegrityCheckingUniffiLib::class.java, findLibraryName(componentName = "suggest"))
        uniffiCheckContractApiVersion(this)
    }
    external fun uniffi_suggest_checksum_func_raw_suggestion_url_matches(
    ): Short
    external fun uniffi_suggest_checksum_method_suggeststore_any_dismissed_suggestions(
    ): Short
    external fun uniffi_suggest_checksum_method_suggeststore_clear(
    ): Short
    external fun uniffi_suggest_checksum_method_suggeststore_clear_dismissed_suggestions(
    ): Short
    external fun uniffi_suggest_checksum_method_suggeststore_dismiss_by_key(
    ): Short
    external fun uniffi_suggest_checksum_method_suggeststore_dismiss_by_suggestion(
    ): Short
    external fun uniffi_suggest_checksum_method_suggeststore_dismiss_suggestion(
    ): Short
    external fun uniffi_suggest_checksum_method_suggeststore_fetch_geoname_alternates(
    ): Short
    external fun uniffi_suggest_checksum_method_suggeststore_fetch_geonames(
    ): Short
    external fun uniffi_suggest_checksum_method_suggeststore_fetch_global_config(
    ): Short
    external fun uniffi_suggest_checksum_method_suggeststore_fetch_provider_config(
    ): Short
    external fun uniffi_suggest_checksum_method_suggeststore_ingest(
    ): Short
    external fun uniffi_suggest_checksum_method_suggeststore_interrupt(
    ): Short
    external fun uniffi_suggest_checksum_method_suggeststore_is_dismissed_by_key(
    ): Short
    external fun uniffi_suggest_checksum_method_suggeststore_is_dismissed_by_suggestion(
    ): Short
    external fun uniffi_suggest_checksum_method_suggeststore_query(
    ): Short
    external fun uniffi_suggest_checksum_method_suggeststore_query_with_metrics(
    ): Short
    external fun uniffi_suggest_checksum_method_suggeststorebuilder_build(
    ): Short
    external fun uniffi_suggest_checksum_method_suggeststorebuilder_cache_path(
    ): Short
    external fun uniffi_suggest_checksum_method_suggeststorebuilder_data_path(
    ): Short
    external fun uniffi_suggest_checksum_method_suggeststorebuilder_load_extension(
    ): Short
    external fun uniffi_suggest_checksum_method_suggeststorebuilder_remote_settings_bucket_name(
    ): Short
    external fun uniffi_suggest_checksum_method_suggeststorebuilder_remote_settings_server(
    ): Short
    external fun uniffi_suggest_checksum_method_suggeststorebuilder_remote_settings_service(
    ): Short
    external fun uniffi_suggest_checksum_constructor_suggeststore_new(
    ): Short
    external fun uniffi_suggest_checksum_constructor_suggeststorebuilder_new(
    ): Short
    external fun ffi_suggest_uniffi_contract_version(
    ): Int

        
}

internal object UniffiLib {
    
    // The Cleaner for the whole library
    internal val CLEANER: UniffiCleaner by lazy {
        UniffiCleaner.create()
    }
    

    init {
        Native.register(UniffiLib::class.java, findLibraryName(componentName = "suggest"))
        mozilla.appservices.remotesettings.uniffiEnsureInitialized()
        
    }
    external fun uniffi_suggest_fn_clone_suggeststore(`handle`: Long,uniffi_out_err: UniffiRustCallStatus, 
    ): Long
    external fun uniffi_suggest_fn_free_suggeststore(`handle`: Long,uniffi_out_err: UniffiRustCallStatus, 
    ): Unit
    external fun uniffi_suggest_fn_constructor_suggeststore_new(`path`: RustBuffer.ByValue,`remoteSettingsService`: Long,uniffi_out_err: UniffiRustCallStatus, 
    ): Long
    external fun uniffi_suggest_fn_method_suggeststore_any_dismissed_suggestions(`ptr`: Long,uniffi_out_err: UniffiRustCallStatus, 
    ): Byte
    external fun uniffi_suggest_fn_method_suggeststore_clear(`ptr`: Long,uniffi_out_err: UniffiRustCallStatus, 
    ): Unit
    external fun uniffi_suggest_fn_method_suggeststore_clear_dismissed_suggestions(`ptr`: Long,uniffi_out_err: UniffiRustCallStatus, 
    ): Unit
    external fun uniffi_suggest_fn_method_suggeststore_dismiss_by_key(`ptr`: Long,`key`: RustBuffer.ByValue,uniffi_out_err: UniffiRustCallStatus, 
    ): Unit
    external fun uniffi_suggest_fn_method_suggeststore_dismiss_by_suggestion(`ptr`: Long,`suggestion`: RustBuffer.ByValue,uniffi_out_err: UniffiRustCallStatus, 
    ): Unit
    external fun uniffi_suggest_fn_method_suggeststore_dismiss_suggestion(`ptr`: Long,`suggestionUrl`: RustBuffer.ByValue,uniffi_out_err: UniffiRustCallStatus, 
    ): Unit
    external fun uniffi_suggest_fn_method_suggeststore_fetch_geoname_alternates(`ptr`: Long,`geoname`: RustBuffer.ByValue,uniffi_out_err: UniffiRustCallStatus, 
    ): RustBuffer.ByValue
    external fun uniffi_suggest_fn_method_suggeststore_fetch_geonames(`ptr`: Long,`query`: RustBuffer.ByValue,`matchNamePrefix`: Byte,`filter`: RustBuffer.ByValue,uniffi_out_err: UniffiRustCallStatus, 
    ): RustBuffer.ByValue
    external fun uniffi_suggest_fn_method_suggeststore_fetch_global_config(`ptr`: Long,uniffi_out_err: UniffiRustCallStatus, 
    ): RustBuffer.ByValue
    external fun uniffi_suggest_fn_method_suggeststore_fetch_provider_config(`ptr`: Long,`provider`: RustBuffer.ByValue,uniffi_out_err: UniffiRustCallStatus, 
    ): RustBuffer.ByValue
    external fun uniffi_suggest_fn_method_suggeststore_ingest(`ptr`: Long,`constraints`: RustBuffer.ByValue,uniffi_out_err: UniffiRustCallStatus, 
    ): RustBuffer.ByValue
    external fun uniffi_suggest_fn_method_suggeststore_interrupt(`ptr`: Long,`kind`: RustBuffer.ByValue,uniffi_out_err: UniffiRustCallStatus, 
    ): Unit
    external fun uniffi_suggest_fn_method_suggeststore_is_dismissed_by_key(`ptr`: Long,`key`: RustBuffer.ByValue,uniffi_out_err: UniffiRustCallStatus, 
    ): Byte
    external fun uniffi_suggest_fn_method_suggeststore_is_dismissed_by_suggestion(`ptr`: Long,`suggestion`: RustBuffer.ByValue,uniffi_out_err: UniffiRustCallStatus, 
    ): Byte
    external fun uniffi_suggest_fn_method_suggeststore_query(`ptr`: Long,`query`: RustBuffer.ByValue,uniffi_out_err: UniffiRustCallStatus, 
    ): RustBuffer.ByValue
    external fun uniffi_suggest_fn_method_suggeststore_query_with_metrics(`ptr`: Long,`query`: RustBuffer.ByValue,uniffi_out_err: UniffiRustCallStatus, 
    ): RustBuffer.ByValue
    external fun uniffi_suggest_fn_clone_suggeststorebuilder(`handle`: Long,uniffi_out_err: UniffiRustCallStatus, 
    ): Long
    external fun uniffi_suggest_fn_free_suggeststorebuilder(`handle`: Long,uniffi_out_err: UniffiRustCallStatus, 
    ): Unit
    external fun uniffi_suggest_fn_constructor_suggeststorebuilder_new(uniffi_out_err: UniffiRustCallStatus, 
    ): Long
    external fun uniffi_suggest_fn_method_suggeststorebuilder_build(`ptr`: Long,uniffi_out_err: UniffiRustCallStatus, 
    ): Long
    external fun uniffi_suggest_fn_method_suggeststorebuilder_cache_path(`ptr`: Long,`path`: RustBuffer.ByValue,uniffi_out_err: UniffiRustCallStatus, 
    ): Long
    external fun uniffi_suggest_fn_method_suggeststorebuilder_data_path(`ptr`: Long,`path`: RustBuffer.ByValue,uniffi_out_err: UniffiRustCallStatus, 
    ): Long
    external fun uniffi_suggest_fn_method_suggeststorebuilder_load_extension(`ptr`: Long,`library`: RustBuffer.ByValue,`entryPoint`: RustBuffer.ByValue,uniffi_out_err: UniffiRustCallStatus, 
    ): Long
    external fun uniffi_suggest_fn_method_suggeststorebuilder_remote_settings_bucket_name(`ptr`: Long,`bucketName`: RustBuffer.ByValue,uniffi_out_err: UniffiRustCallStatus, 
    ): Long
    external fun uniffi_suggest_fn_method_suggeststorebuilder_remote_settings_server(`ptr`: Long,`server`: RustBufferRemoteSettingsServer.ByValue,uniffi_out_err: UniffiRustCallStatus, 
    ): Long
    external fun uniffi_suggest_fn_method_suggeststorebuilder_remote_settings_service(`ptr`: Long,`rsService`: Long,uniffi_out_err: UniffiRustCallStatus, 
    ): Long
    external fun uniffi_suggest_fn_func_raw_suggestion_url_matches(`rawUrl`: RustBuffer.ByValue,`cookedUrl`: RustBuffer.ByValue,uniffi_out_err: UniffiRustCallStatus, 
    ): Byte
    external fun ffi_suggest_rustbuffer_alloc(`size`: Long,uniffi_out_err: UniffiRustCallStatus, 
    ): RustBuffer.ByValue
    external fun ffi_suggest_rustbuffer_from_bytes(`bytes`: ForeignBytes.ByValue,uniffi_out_err: UniffiRustCallStatus, 
    ): RustBuffer.ByValue
    external fun ffi_suggest_rustbuffer_free(`buf`: RustBuffer.ByValue,uniffi_out_err: UniffiRustCallStatus, 
    ): Unit
    external fun ffi_suggest_rustbuffer_reserve(`buf`: RustBuffer.ByValue,`additional`: Long,uniffi_out_err: UniffiRustCallStatus, 
    ): RustBuffer.ByValue
    external fun ffi_suggest_rust_future_poll_u8(`handle`: Long,`callback`: UniffiRustFutureContinuationCallback,`callbackData`: Long,
    ): Unit
    external fun ffi_suggest_rust_future_cancel_u8(`handle`: Long,
    ): Unit
    external fun ffi_suggest_rust_future_free_u8(`handle`: Long,
    ): Unit
    external fun ffi_suggest_rust_future_complete_u8(`handle`: Long,uniffi_out_err: UniffiRustCallStatus, 
    ): Byte
    external fun ffi_suggest_rust_future_poll_i8(`handle`: Long,`callback`: UniffiRustFutureContinuationCallback,`callbackData`: Long,
    ): Unit
    external fun ffi_suggest_rust_future_cancel_i8(`handle`: Long,
    ): Unit
    external fun ffi_suggest_rust_future_free_i8(`handle`: Long,
    ): Unit
    external fun ffi_suggest_rust_future_complete_i8(`handle`: Long,uniffi_out_err: UniffiRustCallStatus, 
    ): Byte
    external fun ffi_suggest_rust_future_poll_u16(`handle`: Long,`callback`: UniffiRustFutureContinuationCallback,`callbackData`: Long,
    ): Unit
    external fun ffi_suggest_rust_future_cancel_u16(`handle`: Long,
    ): Unit
    external fun ffi_suggest_rust_future_free_u16(`handle`: Long,
    ): Unit
    external fun ffi_suggest_rust_future_complete_u16(`handle`: Long,uniffi_out_err: UniffiRustCallStatus, 
    ): Short
    external fun ffi_suggest_rust_future_poll_i16(`handle`: Long,`callback`: UniffiRustFutureContinuationCallback,`callbackData`: Long,
    ): Unit
    external fun ffi_suggest_rust_future_cancel_i16(`handle`: Long,
    ): Unit
    external fun ffi_suggest_rust_future_free_i16(`handle`: Long,
    ): Unit
    external fun ffi_suggest_rust_future_complete_i16(`handle`: Long,uniffi_out_err: UniffiRustCallStatus, 
    ): Short
    external fun ffi_suggest_rust_future_poll_u32(`handle`: Long,`callback`: UniffiRustFutureContinuationCallback,`callbackData`: Long,
    ): Unit
    external fun ffi_suggest_rust_future_cancel_u32(`handle`: Long,
    ): Unit
    external fun ffi_suggest_rust_future_free_u32(`handle`: Long,
    ): Unit
    external fun ffi_suggest_rust_future_complete_u32(`handle`: Long,uniffi_out_err: UniffiRustCallStatus, 
    ): Int
    external fun ffi_suggest_rust_future_poll_i32(`handle`: Long,`callback`: UniffiRustFutureContinuationCallback,`callbackData`: Long,
    ): Unit
    external fun ffi_suggest_rust_future_cancel_i32(`handle`: Long,
    ): Unit
    external fun ffi_suggest_rust_future_free_i32(`handle`: Long,
    ): Unit
    external fun ffi_suggest_rust_future_complete_i32(`handle`: Long,uniffi_out_err: UniffiRustCallStatus, 
    ): Int
    external fun ffi_suggest_rust_future_poll_u64(`handle`: Long,`callback`: UniffiRustFutureContinuationCallback,`callbackData`: Long,
    ): Unit
    external fun ffi_suggest_rust_future_cancel_u64(`handle`: Long,
    ): Unit
    external fun ffi_suggest_rust_future_free_u64(`handle`: Long,
    ): Unit
    external fun ffi_suggest_rust_future_complete_u64(`handle`: Long,uniffi_out_err: UniffiRustCallStatus, 
    ): Long
    external fun ffi_suggest_rust_future_poll_i64(`handle`: Long,`callback`: UniffiRustFutureContinuationCallback,`callbackData`: Long,
    ): Unit
    external fun ffi_suggest_rust_future_cancel_i64(`handle`: Long,
    ): Unit
    external fun ffi_suggest_rust_future_free_i64(`handle`: Long,
    ): Unit
    external fun ffi_suggest_rust_future_complete_i64(`handle`: Long,uniffi_out_err: UniffiRustCallStatus, 
    ): Long
    external fun ffi_suggest_rust_future_poll_f32(`handle`: Long,`callback`: UniffiRustFutureContinuationCallback,`callbackData`: Long,
    ): Unit
    external fun ffi_suggest_rust_future_cancel_f32(`handle`: Long,
    ): Unit
    external fun ffi_suggest_rust_future_free_f32(`handle`: Long,
    ): Unit
    external fun ffi_suggest_rust_future_complete_f32(`handle`: Long,uniffi_out_err: UniffiRustCallStatus, 
    ): Float
    external fun ffi_suggest_rust_future_poll_f64(`handle`: Long,`callback`: UniffiRustFutureContinuationCallback,`callbackData`: Long,
    ): Unit
    external fun ffi_suggest_rust_future_cancel_f64(`handle`: Long,
    ): Unit
    external fun ffi_suggest_rust_future_free_f64(`handle`: Long,
    ): Unit
    external fun ffi_suggest_rust_future_complete_f64(`handle`: Long,uniffi_out_err: UniffiRustCallStatus, 
    ): Double
    external fun ffi_suggest_rust_future_poll_rust_buffer(`handle`: Long,`callback`: UniffiRustFutureContinuationCallback,`callbackData`: Long,
    ): Unit
    external fun ffi_suggest_rust_future_cancel_rust_buffer(`handle`: Long,
    ): Unit
    external fun ffi_suggest_rust_future_free_rust_buffer(`handle`: Long,
    ): Unit
    external fun ffi_suggest_rust_future_complete_rust_buffer(`handle`: Long,uniffi_out_err: UniffiRustCallStatus, 
    ): RustBuffer.ByValue
    external fun ffi_suggest_rust_future_poll_void(`handle`: Long,`callback`: UniffiRustFutureContinuationCallback,`callbackData`: Long,
    ): Unit
    external fun ffi_suggest_rust_future_cancel_void(`handle`: Long,
    ): Unit
    external fun ffi_suggest_rust_future_free_void(`handle`: Long,
    ): Unit
    external fun ffi_suggest_rust_future_complete_void(`handle`: Long,uniffi_out_err: UniffiRustCallStatus, 
    ): Unit

        
}

private fun uniffiCheckContractApiVersion(lib: IntegrityCheckingUniffiLib) {
    // Get the bindings contract version from our ComponentInterface
    val bindings_contract_version = 30
    // Get the scaffolding contract version by calling the into the dylib
    val scaffolding_contract_version = lib.ffi_suggest_uniffi_contract_version()
    if (bindings_contract_version != scaffolding_contract_version) {
        throw RuntimeException("UniFFI contract version mismatch: try cleaning and rebuilding your project")
    }
}

/**
 * @suppress
 */
public fun uniffiEnsureInitialized() {
    IntegrityCheckingUniffiLib
    // UniffiLib() initialized as objects are used, but we still need to explicitly
    // reference it so initialization across crates works as expected.
    UniffiLib
}

// Async support

// Public interface members begin here.


// Interface implemented by anything that can contain an object reference.
//
// Such types expose a `destroy()` method that must be called to cleanly
// dispose of the contained objects. Failure to call this method may result
// in memory leaks.
//
// The easiest way to ensure this method is called is to use the `.use`
// helper method to execute a block and destroy the object at the end.
interface Disposable {
    fun destroy()
    companion object {
        fun destroy(vararg args: Any?) {
            for (arg in args) {
                when (arg) {
                    is Disposable -> arg.destroy()
                    is ArrayList<*> -> {
                        for (idx in arg.indices) {
                            val element = arg[idx]
                            if (element is Disposable) {
                                element.destroy()
                            }
                        }
                    }
                    is Map<*, *> -> {
                        for (element in arg.values) {
                            if (element is Disposable) {
                                element.destroy()
                            }
                        }
                    }
                    is Iterable<*> -> {
                        for (element in arg) {
                            if (element is Disposable) {
                                element.destroy()
                            }
                        }
                    }
                }
            }
        }
    }
}

/**
 * @suppress
 */
inline fun <T : Disposable?, R> T.use(block: (T) -> R) =
    try {
        block(this)
    } finally {
        try {
            // N.B. our implementation is on the nullable type `Disposable?`.
            this?.destroy()
        } catch (e: Throwable) {
            // swallow
        }
    }

/** 
 * Placeholder object used to signal that we're constructing an interface with a FFI handle.
 *
 * This is the first argument for interface constructors that input a raw handle. It exists is that
 * so we can avoid signature conflicts when an interface has a regular constructor than inputs a
 * Long.
 *
 * @suppress
 * */
object UniffiWithHandle

/** 
 * Used to instantiate an interface without an actual pointer, for fakes in tests, mostly.
 *
 * @suppress
 * */
object NoHandle
/**
 * The cleaner interface for Object finalization code to run.
 * This is the entry point to any implementation that we're using.
 *
 * The cleaner registers objects and returns cleanables, so now we are
 * defining a `UniffiCleaner` with a `UniffiClenaer.Cleanable` to abstract the
 * different implmentations available at compile time.
 *
 * @suppress
 */
interface UniffiCleaner {
    interface Cleanable {
        fun clean()
    }

    fun register(value: Any, cleanUpTask: Runnable): UniffiCleaner.Cleanable

    companion object
}

// The fallback Jna cleaner, which is available for both Android, and the JVM.
private class UniffiJnaCleaner : UniffiCleaner {
    private val cleaner = com.sun.jna.internal.Cleaner.getCleaner()

    override fun register(value: Any, cleanUpTask: Runnable): UniffiCleaner.Cleanable =
        UniffiJnaCleanable(cleaner.register(value, cleanUpTask))
}

private class UniffiJnaCleanable(
    private val cleanable: com.sun.jna.internal.Cleaner.Cleanable,
) : UniffiCleaner.Cleanable {
    override fun clean() = cleanable.clean()
}


// We decide at uniffi binding generation time whether we were
// using Android or not.
// There are further runtime checks to chose the correct implementation
// of the cleaner.
private fun UniffiCleaner.Companion.create(): UniffiCleaner =
    try {
        // For safety's sake: if the library hasn't been run in android_cleaner = true
        // mode, but is being run on Android, then we still need to think about
        // Android API versions.
        // So we check if java.lang.ref.Cleaner is there, and use that…
        java.lang.Class.forName("java.lang.ref.Cleaner")
        JavaLangRefCleaner()
    } catch (e: ClassNotFoundException) {
        // … otherwise, fallback to the JNA cleaner.
        UniffiJnaCleaner()
    }

private class JavaLangRefCleaner : UniffiCleaner {
    val cleaner = java.lang.ref.Cleaner.create()

    override fun register(value: Any, cleanUpTask: Runnable): UniffiCleaner.Cleanable =
        JavaLangRefCleanable(cleaner.register(value, cleanUpTask))
}

private class JavaLangRefCleanable(
    val cleanable: java.lang.ref.Cleaner.Cleanable
) : UniffiCleaner.Cleanable {
    override fun clean() = cleanable.clean()
}

/**
 * @suppress
 */
public object FfiConverterUByte: FfiConverter<UByte, Byte> {
    override fun lift(value: Byte): UByte {
        return value.toUByte()
    }

    override fun read(buf: ByteBuffer): UByte {
        return lift(buf.get())
    }

    override fun lower(value: UByte): Byte {
        return value.toByte()
    }

    override fun allocationSize(value: UByte) = 1UL

    override fun write(value: UByte, buf: ByteBuffer) {
        buf.put(value.toByte())
    }
}

/**
 * @suppress
 */
public object FfiConverterInt: FfiConverter<Int, Int> {
    override fun lift(value: Int): Int {
        return value
    }

    override fun read(buf: ByteBuffer): Int {
        return buf.getInt()
    }

    override fun lower(value: Int): Int {
        return value
    }

    override fun allocationSize(value: Int) = 4UL

    override fun write(value: Int, buf: ByteBuffer) {
        buf.putInt(value)
    }
}

/**
 * @suppress
 */
public object FfiConverterULong: FfiConverter<ULong, Long> {
    override fun lift(value: Long): ULong {
        return value.toULong()
    }

    override fun read(buf: ByteBuffer): ULong {
        return lift(buf.getLong())
    }

    override fun lower(value: ULong): Long {
        return value.toLong()
    }

    override fun allocationSize(value: ULong) = 8UL

    override fun write(value: ULong, buf: ByteBuffer) {
        buf.putLong(value.toLong())
    }
}

/**
 * @suppress
 */
public object FfiConverterLong: FfiConverter<Long, Long> {
    override fun lift(value: Long): Long {
        return value
    }

    override fun read(buf: ByteBuffer): Long {
        return buf.getLong()
    }

    override fun lower(value: Long): Long {
        return value
    }

    override fun allocationSize(value: Long) = 8UL

    override fun write(value: Long, buf: ByteBuffer) {
        buf.putLong(value)
    }
}

/**
 * @suppress
 */
public object FfiConverterDouble: FfiConverter<Double, Double> {
    override fun lift(value: Double): Double {
        return value
    }

    override fun read(buf: ByteBuffer): Double {
        return buf.getDouble()
    }

    override fun lower(value: Double): Double {
        return value
    }

    override fun allocationSize(value: Double) = 8UL

    override fun write(value: Double, buf: ByteBuffer) {
        buf.putDouble(value)
    }
}

/**
 * @suppress
 */
public object FfiConverterBoolean: FfiConverter<Boolean, Byte> {
    override fun lift(value: Byte): Boolean {
        return value.toInt() != 0
    }

    override fun read(buf: ByteBuffer): Boolean {
        return lift(buf.get())
    }

    override fun lower(value: Boolean): Byte {
        return if (value) 1.toByte() else 0.toByte()
    }

    override fun allocationSize(value: Boolean) = 1UL

    override fun write(value: Boolean, buf: ByteBuffer) {
        buf.put(lower(value))
    }
}

/**
 * @suppress
 */
public object FfiConverterString: FfiConverter<String, RustBuffer.ByValue> {
    // Note: we don't inherit from FfiConverterRustBuffer, because we use a
    // special encoding when lowering/lifting.  We can use `RustBuffer.len` to
    // store our length and avoid writing it out to the buffer.
    override fun lift(value: RustBuffer.ByValue): String {
        try {
            val byteArr = ByteArray(value.len.toInt())
            value.asByteBuffer()!!.get(byteArr)
            return byteArr.toString(Charsets.UTF_8)
        } finally {
            RustBuffer.free(value)
        }
    }

    override fun read(buf: ByteBuffer): String {
        val len = buf.getInt()
        val byteArr = ByteArray(len)
        buf.get(byteArr)
        return byteArr.toString(Charsets.UTF_8)
    }

    fun toUtf8(value: String): ByteBuffer {
        // Make sure we don't have invalid UTF-16, check for lone surrogates.
        return Charsets.UTF_8.newEncoder().run {
            onMalformedInput(CodingErrorAction.REPORT)
            encode(CharBuffer.wrap(value))
        }
    }

    override fun lower(value: String): RustBuffer.ByValue {
        val byteBuf = toUtf8(value)
        // Ideally we'd pass these bytes to `ffi_bytebuffer_from_bytes`, but doing so would require us
        // to copy them into a JNA `Memory`. So we might as well directly copy them into a `RustBuffer`.
        val rbuf = RustBuffer.alloc(byteBuf.limit().toULong())
        rbuf.asByteBuffer()!!.put(byteBuf)
        return rbuf
    }

    // We aren't sure exactly how many bytes our string will be once it's UTF-8
    // encoded.  Allocate 3 bytes per UTF-16 code unit which will always be
    // enough.
    override fun allocationSize(value: String): ULong {
        val sizeForLength = 4UL
        val sizeForString = value.length.toULong() * 3UL
        return sizeForLength + sizeForString
    }

    override fun write(value: String, buf: ByteBuffer) {
        val byteBuf = toUtf8(value)
        buf.putInt(byteBuf.limit())
        buf.put(byteBuf)
    }
}

/**
 * @suppress
 */
public object FfiConverterByteArray: FfiConverterRustBuffer<ByteArray> {
    override fun read(buf: ByteBuffer): ByteArray {
        val len = buf.getInt()
        val byteArr = ByteArray(len)
        buf.get(byteArr)
        return byteArr
    }
    override fun allocationSize(value: ByteArray): ULong {
        return 4UL + value.size.toULong()
    }
    override fun write(value: ByteArray, buf: ByteBuffer) {
        buf.putInt(value.size)
        buf.put(value)
    }
}


// This template implements a class for working with a Rust struct via a handle
// to the live Rust struct on the other side of the FFI.
//
// There's some subtlety here, because we have to be careful not to operate on a Rust
// struct after it has been dropped, and because we must expose a public API for freeing
// theq Kotlin wrapper object in lieu of reliable finalizers. The core requirements are:
//
//   * Each instance holds an opaque handle to the underlying Rust struct.
//     Method calls need to read this handle from the object's state and pass it in to
//     the Rust FFI.
//
//   * When an instance is no longer needed, its handle should be passed to a
//     special destructor function provided by the Rust FFI, which will drop the
//     underlying Rust struct.
//
//   * Given an instance, calling code is expected to call the special
//     `destroy` method in order to free it after use, either by calling it explicitly
//     or by using a higher-level helper like the `use` method. Failing to do so risks
//     leaking the underlying Rust struct.
//
//   * We can't assume that calling code will do the right thing, and must be prepared
//     to handle Kotlin method calls executing concurrently with or even after a call to
//     `destroy`, and to handle multiple (possibly concurrent!) calls to `destroy`.
//
//   * We must never allow Rust code to operate on the underlying Rust struct after
//     the destructor has been called, and must never call the destructor more than once.
//     Doing so may trigger memory unsafety.
//
//   * To mitigate many of the risks of leaking memory and use-after-free unsafety, a `Cleaner`
//     is implemented to call the destructor when the Kotlin object becomes unreachable.
//     This is done in a background thread. This is not a panacea, and client code should be aware that
//      1. the thread may starve if some there are objects that have poorly performing
//     `drop` methods or do significant work in their `drop` methods.
//      2. the thread is shared across the whole library. This can be tuned by using `android_cleaner = true`,
//         or `android = true` in the [`kotlin` section of the `uniffi.toml` file](https://mozilla.github.io/uniffi-rs/kotlin/configuration.html).
//
// If we try to implement this with mutual exclusion on access to the handle, there is the
// possibility of a race between a method call and a concurrent call to `destroy`:
//
//    * Thread A starts a method call, reads the value of the handle, but is interrupted
//      before it can pass the handle over the FFI to Rust.
//    * Thread B calls `destroy` and frees the underlying Rust struct.
//    * Thread A resumes, passing the already-read handle value to Rust and triggering
//      a use-after-free.
//
// One possible solution would be to use a `ReadWriteLock`, with each method call taking
// a read lock (and thus allowed to run concurrently) and the special `destroy` method
// taking a write lock (and thus blocking on live method calls). However, we aim not to
// generate methods with any hidden blocking semantics, and a `destroy` method that might
// block if called incorrectly seems to meet that bar.
//
// So, we achieve our goals by giving each instance an associated `AtomicLong` counter to track
// the number of in-flight method calls, and an `AtomicBoolean` flag to indicate whether `destroy`
// has been called. These are updated according to the following rules:
//
//    * The initial value of the counter is 1, indicating a live object with no in-flight calls.
//      The initial value for the flag is false.
//
//    * At the start of each method call, we atomically check the counter.
//      If it is 0 then the underlying Rust struct has already been destroyed and the call is aborted.
//      If it is nonzero them we atomically increment it by 1 and proceed with the method call.
//
//    * At the end of each method call, we atomically decrement and check the counter.
//      If it has reached zero then we destroy the underlying Rust struct.
//
//    * When `destroy` is called, we atomically flip the flag from false to true.
//      If the flag was already true we silently fail.
//      Otherwise we atomically decrement and check the counter.
//      If it has reached zero then we destroy the underlying Rust struct.
//
// Astute readers may observe that this all sounds very similar to the way that Rust's `Arc<T>` works,
// and indeed it is, with the addition of a flag to guard against multiple calls to `destroy`.
//
// The overall effect is that the underlying Rust struct is destroyed only when `destroy` has been
// called *and* all in-flight method calls have completed, avoiding violating any of the expectations
// of the underlying Rust code.
//
// This makes a cleaner a better alternative to _not_ calling `destroy()` as
// and when the object is finished with, but the abstraction is not perfect: if the Rust object's `drop`
// method is slow, and/or there are many objects to cleanup, and it's on a low end Android device, then the cleaner
// thread may be starved, and the app will leak memory.
//
// In this case, `destroy`ing manually may be a better solution.
//
// The cleaner can live side by side with the manual calling of `destroy`. In the order of responsiveness, uniffi objects
// with Rust peers are reclaimed:
//
// 1. By calling the `destroy` method of the object, which calls `rustObject.free()`. If that doesn't happen:
// 2. When the object becomes unreachable, AND the Cleaner thread gets to call `rustObject.free()`. If the thread is starved then:
// 3. The memory is reclaimed when the process terminates.
//
// [1] https://stackoverflow.com/questions/24376768/can-java-finalize-an-object-when-it-is-still-in-scope/24380219
//


/**
 * The store is the entry point to the Suggest component. It incrementally
 * downloads suggestions from the Remote Settings service, stores them in a
 * local database, and returns them in response to user queries.
 *
 * Your application should create a single store, and manage it as a singleton.
 * The store is thread-safe, and supports concurrent queries and ingests. We
 * expect that your application will call [`SuggestStore::query()`] to show
 * suggestions as the user types into the address bar, and periodically call
 * [`SuggestStore::ingest()`] in the background to update the database with
 * new suggestions from Remote Settings.
 *
 * For responsiveness, we recommend always calling `query()` on a worker
 * thread. When the user types new input into the address bar, call
 * [`SuggestStore::interrupt()`] on the main thread to cancel the query
 * for the old input, and unblock the worker thread for the new query.
 *
 * The store keeps track of the state needed to support incremental ingestion,
 * but doesn't schedule the ingestion work itself, or decide how many
 * suggestions to ingest at once. This is for two reasons:
 *
 * 1. The primitives for scheduling background work vary between platforms, and
 * aren't available to the lower-level Rust layer. You might use an idle
 * timer on Desktop, `WorkManager` on Android, or `BGTaskScheduler` on iOS.
 * 2. Ingestion constraints can change, depending on the platform and the needs
 * of your application. A mobile device on a metered connection might want
 * to request a small subset of the Suggest data and download the rest
 * later, while a desktop on a fast link might download the entire dataset
 * on the first launch.
 */
public interface SuggestStoreInterface {
    
    /**
     * Return whether any suggestions have been dismissed.
     */
    fun `anyDismissedSuggestions`(): kotlin.Boolean
    
    /**
     * Removes all content from the database.
     */
    fun `clear`()
    
    /**
     * Clear dismissed suggestions
     */
    fun `clearDismissedSuggestions`()
    
    /**
     * Dismiss a suggestion by its dismissal key.
     *
     * Dismissed suggestions cannot be fetched again.
     *
     * Prefer [SuggestStore::dismiss_by_suggestion] if you have a
     * `crate::Suggestion`. This method is intended for cases where a
     * suggestion originates outside this component.
     */
    fun `dismissByKey`(`key`: kotlin.String)
    
    /**
     * Dismiss a suggestion.
     *
     * Dismissed suggestions cannot be fetched again.
     */
    fun `dismissBySuggestion`(`suggestion`: Suggestion)
    
    /**
     * Deprecated, use [SuggestStore::dismiss_by_suggestion] or
     * [SuggestStore::dismiss_by_key] instead.
     *
     * Dismiss a suggestion
     *
     * Dismissed suggestions will not be returned again
     */
    fun `dismissSuggestion`(`suggestionUrl`: kotlin.String)
    
    /**
     * Fetches a geoname's names stored in the database.
     *
     * See `fetch_geoname_alternates` in `geoname.rs` for documentation.
     */
    fun `fetchGeonameAlternates`(`geoname`: Geoname): GeonameAlternates
    
    /**
     * Fetches geonames stored in the database. A geoname represents a
     * geographic place.
     *
     * See `fetch_geonames` in `geoname.rs` for documentation.
     */
    fun `fetchGeonames`(`query`: kotlin.String, `matchNamePrefix`: kotlin.Boolean, `filter`: List<Geoname>?): List<GeonameMatch>
    
    /**
     * Returns global Suggest configuration data.
     */
    fun `fetchGlobalConfig`(): SuggestGlobalConfig
    
    /**
     * Returns per-provider Suggest configuration data.
     */
    fun `fetchProviderConfig`(`provider`: SuggestionProvider): SuggestProviderConfig?
    
    /**
     * Ingests new suggestions from Remote Settings.
     */
    fun `ingest`(`constraints`: SuggestIngestionConstraints): SuggestIngestionMetrics
    
    /**
     * Interrupts any ongoing queries.
     *
     * This should be called when the user types new input into the address
     * bar, to ensure that they see fresh suggestions as they type. This
     * method does not interrupt any ongoing ingests.
     */
    fun `interrupt`(`kind`: InterruptKind? = null)
    
    /**
     * Return whether a suggestion has been dismissed given its dismissal key.
     *
     * [SuggestStore::query] will never return dismissed suggestions, so
     * normally you never need to know whether a suggestion has been dismissed.
     * This method is intended for cases where a dismissal key originates
     * outside this component.
     */
    fun `isDismissedByKey`(`key`: kotlin.String): kotlin.Boolean
    
    /**
     * Return whether a suggestion has been dismissed.
     *
     * [SuggestStore::query] will never return dismissed suggestions, so
     * normally you never need to know whether a `Suggestion` has been
     * dismissed, but this method can be used to do so.
     */
    fun `isDismissedBySuggestion`(`suggestion`: Suggestion): kotlin.Boolean
    
    /**
     * Queries the database for suggestions.
     */
    fun `query`(`query`: SuggestionQuery): List<Suggestion>
    
    /**
     * Queries the database for suggestions.
     */
    fun `queryWithMetrics`(`query`: SuggestionQuery): QueryWithMetricsResult
    
    companion object
}

/**
 * The store is the entry point to the Suggest component. It incrementally
 * downloads suggestions from the Remote Settings service, stores them in a
 * local database, and returns them in response to user queries.
 *
 * Your application should create a single store, and manage it as a singleton.
 * The store is thread-safe, and supports concurrent queries and ingests. We
 * expect that your application will call [`SuggestStore::query()`] to show
 * suggestions as the user types into the address bar, and periodically call
 * [`SuggestStore::ingest()`] in the background to update the database with
 * new suggestions from Remote Settings.
 *
 * For responsiveness, we recommend always calling `query()` on a worker
 * thread. When the user types new input into the address bar, call
 * [`SuggestStore::interrupt()`] on the main thread to cancel the query
 * for the old input, and unblock the worker thread for the new query.
 *
 * The store keeps track of the state needed to support incremental ingestion,
 * but doesn't schedule the ingestion work itself, or decide how many
 * suggestions to ingest at once. This is for two reasons:
 *
 * 1. The primitives for scheduling background work vary between platforms, and
 * aren't available to the lower-level Rust layer. You might use an idle
 * timer on Desktop, `WorkManager` on Android, or `BGTaskScheduler` on iOS.
 * 2. Ingestion constraints can change, depending on the platform and the needs
 * of your application. A mobile device on a metered connection might want
 * to request a small subset of the Suggest data and download the rest
 * later, while a desktop on a fast link might download the entire dataset
 * on the first launch.
 */
open class SuggestStore: Disposable, AutoCloseable, SuggestStoreInterface
{

    @Suppress("UNUSED_PARAMETER")
    /**
     * @suppress
     */
    constructor(withHandle: UniffiWithHandle, handle: Long) {
        this.handle = handle
        this.cleanable = UniffiLib.CLEANER.register(this, UniffiCleanAction(handle))
    }

    /**
     * @suppress
     *
     * This constructor can be used to instantiate a fake object. Only used for tests. Any
     * attempt to actually use an object constructed this way will fail as there is no
     * connected Rust object.
     */
    @Suppress("UNUSED_PARAMETER")
    constructor(noHandle: NoHandle) {
        this.handle = 0
        this.cleanable = null
    }
    /**
     * Creates a Suggest store.
     */
    constructor(`path`: kotlin.String, `remoteSettingsService`: RemoteSettingsService) :
        this(UniffiWithHandle, 
    uniffiRustCall() { _status ->
    UniffiLib.uniffi_suggest_fn_constructor_suggeststore_new(
    
        FfiConverterString.lower(`path`),FfiConverterTypeRemoteSettingsService.lower(`remoteSettingsService`),_status)
}
    )

    protected val handle: Long
    protected val cleanable: UniffiCleaner.Cleanable?

    private val wasDestroyed = AtomicBoolean(false)
    private val callCounter = AtomicLong(1)

    override fun destroy() {
        // Only allow a single call to this method.
        // TODO: maybe we should log a warning if called more than once?
        if (this.wasDestroyed.compareAndSet(false, true)) {
            // This decrement always matches the initial count of 1 given at creation time.
            if (this.callCounter.decrementAndGet() == 0L) {
                cleanable?.clean()
            }
        }
    }

    @Synchronized
    override fun close() {
        this.destroy()
    }

    internal inline fun <R> callWithHandle(block: (handle: Long) -> R): R {
        // Check and increment the call counter, to keep the object alive.
        // This needs a compare-and-set retry loop in case of concurrent updates.
        do {
            val c = this.callCounter.get()
            if (c == 0L) {
                throw IllegalStateException("${this.javaClass.simpleName} object has already been destroyed")
            }
            if (c == Long.MAX_VALUE) {
                throw IllegalStateException("${this.javaClass.simpleName} call counter would overflow")
            }
        } while (! this.callCounter.compareAndSet(c, c + 1L))
        // Now we can safely do the method call without the handle being freed concurrently.
        try {
            return block(this.uniffiCloneHandle())
        } finally {
            // This decrement always matches the increment we performed above.
            if (this.callCounter.decrementAndGet() == 0L) {
                cleanable?.clean()
            }
        }
    }

    // Use a static inner class instead of a closure so as not to accidentally
    // capture `this` as part of the cleanable's action.
    private class UniffiCleanAction(private val handle: Long) : Runnable {
        override fun run() {
            if (handle == 0.toLong()) {
                // Fake object created with `NoHandle`, don't try to free.
                return;
            }
            uniffiRustCall { status ->
                UniffiLib.uniffi_suggest_fn_free_suggeststore(handle, status)
            }
        }
    }

    /**
     * @suppress
     */
    fun uniffiCloneHandle(): Long {
        if (handle == 0.toLong()) {
            throw InternalException("uniffiCloneHandle() called on NoHandle object");
        }
        return uniffiRustCall() { status ->
            UniffiLib.uniffi_suggest_fn_clone_suggeststore(handle, status)
        }
    }

    
    /**
     * Return whether any suggestions have been dismissed.
     */
    @Throws(SuggestApiException::class)override fun `anyDismissedSuggestions`(): kotlin.Boolean {
            return FfiConverterBoolean.lift(
    callWithHandle {
    uniffiRustCallWithError(SuggestApiException) { _status ->
    UniffiLib.uniffi_suggest_fn_method_suggeststore_any_dismissed_suggestions(
        it,
        _status)
}
    }
    )
    }
    

    
    /**
     * Removes all content from the database.
     */
    @Throws(SuggestApiException::class)override fun `clear`()
        = 
    callWithHandle {
    uniffiRustCallWithError(SuggestApiException) { _status ->
    UniffiLib.uniffi_suggest_fn_method_suggeststore_clear(
        it,
        _status)
}
    }
    
    

    
    /**
     * Clear dismissed suggestions
     */
    @Throws(SuggestApiException::class)override fun `clearDismissedSuggestions`()
        = 
    callWithHandle {
    uniffiRustCallWithError(SuggestApiException) { _status ->
    UniffiLib.uniffi_suggest_fn_method_suggeststore_clear_dismissed_suggestions(
        it,
        _status)
}
    }
    
    

    
    /**
     * Dismiss a suggestion by its dismissal key.
     *
     * Dismissed suggestions cannot be fetched again.
     *
     * Prefer [SuggestStore::dismiss_by_suggestion] if you have a
     * `crate::Suggestion`. This method is intended for cases where a
     * suggestion originates outside this component.
     */
    @Throws(SuggestApiException::class)override fun `dismissByKey`(`key`: kotlin.String)
        = 
    callWithHandle {
    uniffiRustCallWithError(SuggestApiException) { _status ->
    UniffiLib.uniffi_suggest_fn_method_suggeststore_dismiss_by_key(
        it,
        FfiConverterString.lower(`key`),_status)
}
    }
    
    

    
    /**
     * Dismiss a suggestion.
     *
     * Dismissed suggestions cannot be fetched again.
     */
    @Throws(SuggestApiException::class)override fun `dismissBySuggestion`(`suggestion`: Suggestion)
        = 
    callWithHandle {
    uniffiRustCallWithError(SuggestApiException) { _status ->
    UniffiLib.uniffi_suggest_fn_method_suggeststore_dismiss_by_suggestion(
        it,
        FfiConverterTypeSuggestion.lower(`suggestion`),_status)
}
    }
    
    

    
    /**
     * Deprecated, use [SuggestStore::dismiss_by_suggestion] or
     * [SuggestStore::dismiss_by_key] instead.
     *
     * Dismiss a suggestion
     *
     * Dismissed suggestions will not be returned again
     */
    @Throws(SuggestApiException::class)override fun `dismissSuggestion`(`suggestionUrl`: kotlin.String)
        = 
    callWithHandle {
    uniffiRustCallWithError(SuggestApiException) { _status ->
    UniffiLib.uniffi_suggest_fn_method_suggeststore_dismiss_suggestion(
        it,
        FfiConverterString.lower(`suggestionUrl`),_status)
}
    }
    
    

    
    /**
     * Fetches a geoname's names stored in the database.
     *
     * See `fetch_geoname_alternates` in `geoname.rs` for documentation.
     */
    @Throws(SuggestApiException::class)override fun `fetchGeonameAlternates`(`geoname`: Geoname): GeonameAlternates {
            return FfiConverterTypeGeonameAlternates.lift(
    callWithHandle {
    uniffiRustCallWithError(SuggestApiException) { _status ->
    UniffiLib.uniffi_suggest_fn_method_suggeststore_fetch_geoname_alternates(
        it,
        FfiConverterTypeGeoname.lower(`geoname`),_status)
}
    }
    )
    }
    

    
    /**
     * Fetches geonames stored in the database. A geoname represents a
     * geographic place.
     *
     * See `fetch_geonames` in `geoname.rs` for documentation.
     */
    @Throws(SuggestApiException::class)override fun `fetchGeonames`(`query`: kotlin.String, `matchNamePrefix`: kotlin.Boolean, `filter`: List<Geoname>?): List<GeonameMatch> {
            return FfiConverterSequenceTypeGeonameMatch.lift(
    callWithHandle {
    uniffiRustCallWithError(SuggestApiException) { _status ->
    UniffiLib.uniffi_suggest_fn_method_suggeststore_fetch_geonames(
        it,
        FfiConverterString.lower(`query`),FfiConverterBoolean.lower(`matchNamePrefix`),FfiConverterOptionalSequenceTypeGeoname.lower(`filter`),_status)
}
    }
    )
    }
    

    
    /**
     * Returns global Suggest configuration data.
     */
    @Throws(SuggestApiException::class)override fun `fetchGlobalConfig`(): SuggestGlobalConfig {
            return FfiConverterTypeSuggestGlobalConfig.lift(
    callWithHandle {
    uniffiRustCallWithError(SuggestApiException) { _status ->
    UniffiLib.uniffi_suggest_fn_method_suggeststore_fetch_global_config(
        it,
        _status)
}
    }
    )
    }
    

    
    /**
     * Returns per-provider Suggest configuration data.
     */
    @Throws(SuggestApiException::class)override fun `fetchProviderConfig`(`provider`: SuggestionProvider): SuggestProviderConfig? {
            return FfiConverterOptionalTypeSuggestProviderConfig.lift(
    callWithHandle {
    uniffiRustCallWithError(SuggestApiException) { _status ->
    UniffiLib.uniffi_suggest_fn_method_suggeststore_fetch_provider_config(
        it,
        FfiConverterTypeSuggestionProvider.lower(`provider`),_status)
}
    }
    )
    }
    

    
    /**
     * Ingests new suggestions from Remote Settings.
     */
    @Throws(SuggestApiException::class)override fun `ingest`(`constraints`: SuggestIngestionConstraints): SuggestIngestionMetrics {
            return FfiConverterTypeSuggestIngestionMetrics.lift(
    callWithHandle {
    uniffiRustCallWithError(SuggestApiException) { _status ->
    UniffiLib.uniffi_suggest_fn_method_suggeststore_ingest(
        it,
        FfiConverterTypeSuggestIngestionConstraints.lower(`constraints`),_status)
}
    }
    )
    }
    

    
    /**
     * Interrupts any ongoing queries.
     *
     * This should be called when the user types new input into the address
     * bar, to ensure that they see fresh suggestions as they type. This
     * method does not interrupt any ongoing ingests.
     */override fun `interrupt`(`kind`: InterruptKind?)
        = 
    callWithHandle {
    uniffiRustCall() { _status ->
    UniffiLib.uniffi_suggest_fn_method_suggeststore_interrupt(
        it,
        FfiConverterOptionalTypeInterruptKind.lower(`kind`),_status)
}
    }
    
    

    
    /**
     * Return whether a suggestion has been dismissed given its dismissal key.
     *
     * [SuggestStore::query] will never return dismissed suggestions, so
     * normally you never need to know whether a suggestion has been dismissed.
     * This method is intended for cases where a dismissal key originates
     * outside this component.
     */
    @Throws(SuggestApiException::class)override fun `isDismissedByKey`(`key`: kotlin.String): kotlin.Boolean {
            return FfiConverterBoolean.lift(
    callWithHandle {
    uniffiRustCallWithError(SuggestApiException) { _status ->
    UniffiLib.uniffi_suggest_fn_method_suggeststore_is_dismissed_by_key(
        it,
        FfiConverterString.lower(`key`),_status)
}
    }
    )
    }
    

    
    /**
     * Return whether a suggestion has been dismissed.
     *
     * [SuggestStore::query] will never return dismissed suggestions, so
     * normally you never need to know whether a `Suggestion` has been
     * dismissed, but this method can be used to do so.
     */
    @Throws(SuggestApiException::class)override fun `isDismissedBySuggestion`(`suggestion`: Suggestion): kotlin.Boolean {
            return FfiConverterBoolean.lift(
    callWithHandle {
    uniffiRustCallWithError(SuggestApiException) { _status ->
    UniffiLib.uniffi_suggest_fn_method_suggeststore_is_dismissed_by_suggestion(
        it,
        FfiConverterTypeSuggestion.lower(`suggestion`),_status)
}
    }
    )
    }
    

    
    /**
     * Queries the database for suggestions.
     */
    @Throws(SuggestApiException::class)override fun `query`(`query`: SuggestionQuery): List<Suggestion> {
            return FfiConverterSequenceTypeSuggestion.lift(
    callWithHandle {
    uniffiRustCallWithError(SuggestApiException) { _status ->
    UniffiLib.uniffi_suggest_fn_method_suggeststore_query(
        it,
        FfiConverterTypeSuggestionQuery.lower(`query`),_status)
}
    }
    )
    }
    

    
    /**
     * Queries the database for suggestions.
     */
    @Throws(SuggestApiException::class)override fun `queryWithMetrics`(`query`: SuggestionQuery): QueryWithMetricsResult {
            return FfiConverterTypeQueryWithMetricsResult.lift(
    callWithHandle {
    uniffiRustCallWithError(SuggestApiException) { _status ->
    UniffiLib.uniffi_suggest_fn_method_suggeststore_query_with_metrics(
        it,
        FfiConverterTypeSuggestionQuery.lower(`query`),_status)
}
    }
    )
    }
    

    

    


    
    
    /**
     * @suppress
     */
    companion object
    
}


/**
 * @suppress
 */
public object FfiConverterTypeSuggestStore: FfiConverter<SuggestStore, Long> {
    override fun lower(value: SuggestStore): Long {
        return value.uniffiCloneHandle()
    }

    override fun lift(value: Long): SuggestStore {
        return SuggestStore(UniffiWithHandle, value)
    }

    override fun read(buf: ByteBuffer): SuggestStore {
        return lift(buf.getLong())
    }

    override fun allocationSize(value: SuggestStore) = 8UL

    override fun write(value: SuggestStore, buf: ByteBuffer) {
        buf.putLong(lower(value))
    }
}


// This template implements a class for working with a Rust struct via a handle
// to the live Rust struct on the other side of the FFI.
//
// There's some subtlety here, because we have to be careful not to operate on a Rust
// struct after it has been dropped, and because we must expose a public API for freeing
// theq Kotlin wrapper object in lieu of reliable finalizers. The core requirements are:
//
//   * Each instance holds an opaque handle to the underlying Rust struct.
//     Method calls need to read this handle from the object's state and pass it in to
//     the Rust FFI.
//
//   * When an instance is no longer needed, its handle should be passed to a
//     special destructor function provided by the Rust FFI, which will drop the
//     underlying Rust struct.
//
//   * Given an instance, calling code is expected to call the special
//     `destroy` method in order to free it after use, either by calling it explicitly
//     or by using a higher-level helper like the `use` method. Failing to do so risks
//     leaking the underlying Rust struct.
//
//   * We can't assume that calling code will do the right thing, and must be prepared
//     to handle Kotlin method calls executing concurrently with or even after a call to
//     `destroy`, and to handle multiple (possibly concurrent!) calls to `destroy`.
//
//   * We must never allow Rust code to operate on the underlying Rust struct after
//     the destructor has been called, and must never call the destructor more than once.
//     Doing so may trigger memory unsafety.
//
//   * To mitigate many of the risks of leaking memory and use-after-free unsafety, a `Cleaner`
//     is implemented to call the destructor when the Kotlin object becomes unreachable.
//     This is done in a background thread. This is not a panacea, and client code should be aware that
//      1. the thread may starve if some there are objects that have poorly performing
//     `drop` methods or do significant work in their `drop` methods.
//      2. the thread is shared across the whole library. This can be tuned by using `android_cleaner = true`,
//         or `android = true` in the [`kotlin` section of the `uniffi.toml` file](https://mozilla.github.io/uniffi-rs/kotlin/configuration.html).
//
// If we try to implement this with mutual exclusion on access to the handle, there is the
// possibility of a race between a method call and a concurrent call to `destroy`:
//
//    * Thread A starts a method call, reads the value of the handle, but is interrupted
//      before it can pass the handle over the FFI to Rust.
//    * Thread B calls `destroy` and frees the underlying Rust struct.
//    * Thread A resumes, passing the already-read handle value to Rust and triggering
//      a use-after-free.
//
// One possible solution would be to use a `ReadWriteLock`, with each method call taking
// a read lock (and thus allowed to run concurrently) and the special `destroy` method
// taking a write lock (and thus blocking on live method calls). However, we aim not to
// generate methods with any hidden blocking semantics, and a `destroy` method that might
// block if called incorrectly seems to meet that bar.
//
// So, we achieve our goals by giving each instance an associated `AtomicLong` counter to track
// the number of in-flight method calls, and an `AtomicBoolean` flag to indicate whether `destroy`
// has been called. These are updated according to the following rules:
//
//    * The initial value of the counter is 1, indicating a live object with no in-flight calls.
//      The initial value for the flag is false.
//
//    * At the start of each method call, we atomically check the counter.
//      If it is 0 then the underlying Rust struct has already been destroyed and the call is aborted.
//      If it is nonzero them we atomically increment it by 1 and proceed with the method call.
//
//    * At the end of each method call, we atomically decrement and check the counter.
//      If it has reached zero then we destroy the underlying Rust struct.
//
//    * When `destroy` is called, we atomically flip the flag from false to true.
//      If the flag was already true we silently fail.
//      Otherwise we atomically decrement and check the counter.
//      If it has reached zero then we destroy the underlying Rust struct.
//
// Astute readers may observe that this all sounds very similar to the way that Rust's `Arc<T>` works,
// and indeed it is, with the addition of a flag to guard against multiple calls to `destroy`.
//
// The overall effect is that the underlying Rust struct is destroyed only when `destroy` has been
// called *and* all in-flight method calls have completed, avoiding violating any of the expectations
// of the underlying Rust code.
//
// This makes a cleaner a better alternative to _not_ calling `destroy()` as
// and when the object is finished with, but the abstraction is not perfect: if the Rust object's `drop`
// method is slow, and/or there are many objects to cleanup, and it's on a low end Android device, then the cleaner
// thread may be starved, and the app will leak memory.
//
// In this case, `destroy`ing manually may be a better solution.
//
// The cleaner can live side by side with the manual calling of `destroy`. In the order of responsiveness, uniffi objects
// with Rust peers are reclaimed:
//
// 1. By calling the `destroy` method of the object, which calls `rustObject.free()`. If that doesn't happen:
// 2. When the object becomes unreachable, AND the Cleaner thread gets to call `rustObject.free()`. If the thread is starved then:
// 3. The memory is reclaimed when the process terminates.
//
// [1] https://stackoverflow.com/questions/24376768/can-java-finalize-an-object-when-it-is-still-in-scope/24380219
//


/**
 * Builder for [SuggestStore]
 *
 * Using a builder is preferred to calling the constructor directly since it's harder to confuse
 * the data_path and cache_path strings.
 */
public interface SuggestStoreBuilderInterface {
    
    fun `build`(): SuggestStore
    
    /**
     * Deprecated: this is no longer used by the suggest component.
     */
    fun `cachePath`(`path`: kotlin.String): SuggestStoreBuilder
    
    fun `dataPath`(`path`: kotlin.String): SuggestStoreBuilder
    
    /**
     * Add an sqlite3 extension to load
     *
     * library_name should be the name of the library without any extension, for example `libmozsqlite3`.
     * entrypoint should be the entry point, for example `sqlite3_fts5_init`.  If `null` (the default)
     * entry point will be used (see https://sqlite.org/loadext.html for details).
     */
    fun `loadExtension`(`library`: kotlin.String, `entryPoint`: kotlin.String?): SuggestStoreBuilder
    
    fun `remoteSettingsBucketName`(`bucketName`: kotlin.String): SuggestStoreBuilder
    
    fun `remoteSettingsServer`(`server`: RemoteSettingsServer): SuggestStoreBuilder
    
    fun `remoteSettingsService`(`rsService`: RemoteSettingsService): SuggestStoreBuilder
    
    companion object
}

/**
 * Builder for [SuggestStore]
 *
 * Using a builder is preferred to calling the constructor directly since it's harder to confuse
 * the data_path and cache_path strings.
 */
open class SuggestStoreBuilder: Disposable, AutoCloseable, SuggestStoreBuilderInterface
{

    @Suppress("UNUSED_PARAMETER")
    /**
     * @suppress
     */
    constructor(withHandle: UniffiWithHandle, handle: Long) {
        this.handle = handle
        this.cleanable = UniffiLib.CLEANER.register(this, UniffiCleanAction(handle))
    }

    /**
     * @suppress
     *
     * This constructor can be used to instantiate a fake object. Only used for tests. Any
     * attempt to actually use an object constructed this way will fail as there is no
     * connected Rust object.
     */
    @Suppress("UNUSED_PARAMETER")
    constructor(noHandle: NoHandle) {
        this.handle = 0
        this.cleanable = null
    }
    constructor() :
        this(UniffiWithHandle, 
    uniffiRustCall() { _status ->
    UniffiLib.uniffi_suggest_fn_constructor_suggeststorebuilder_new(
    
        _status)
}
    )

    protected val handle: Long
    protected val cleanable: UniffiCleaner.Cleanable?

    private val wasDestroyed = AtomicBoolean(false)
    private val callCounter = AtomicLong(1)

    override fun destroy() {
        // Only allow a single call to this method.
        // TODO: maybe we should log a warning if called more than once?
        if (this.wasDestroyed.compareAndSet(false, true)) {
            // This decrement always matches the initial count of 1 given at creation time.
            if (this.callCounter.decrementAndGet() == 0L) {
                cleanable?.clean()
            }
        }
    }

    @Synchronized
    override fun close() {
        this.destroy()
    }

    internal inline fun <R> callWithHandle(block: (handle: Long) -> R): R {
        // Check and increment the call counter, to keep the object alive.
        // This needs a compare-and-set retry loop in case of concurrent updates.
        do {
            val c = this.callCounter.get()
            if (c == 0L) {
                throw IllegalStateException("${this.javaClass.simpleName} object has already been destroyed")
            }
            if (c == Long.MAX_VALUE) {
                throw IllegalStateException("${this.javaClass.simpleName} call counter would overflow")
            }
        } while (! this.callCounter.compareAndSet(c, c + 1L))
        // Now we can safely do the method call without the handle being freed concurrently.
        try {
            return block(this.uniffiCloneHandle())
        } finally {
            // This decrement always matches the increment we performed above.
            if (this.callCounter.decrementAndGet() == 0L) {
                cleanable?.clean()
            }
        }
    }

    // Use a static inner class instead of a closure so as not to accidentally
    // capture `this` as part of the cleanable's action.
    private class UniffiCleanAction(private val handle: Long) : Runnable {
        override fun run() {
            if (handle == 0.toLong()) {
                // Fake object created with `NoHandle`, don't try to free.
                return;
            }
            uniffiRustCall { status ->
                UniffiLib.uniffi_suggest_fn_free_suggeststorebuilder(handle, status)
            }
        }
    }

    /**
     * @suppress
     */
    fun uniffiCloneHandle(): Long {
        if (handle == 0.toLong()) {
            throw InternalException("uniffiCloneHandle() called on NoHandle object");
        }
        return uniffiRustCall() { status ->
            UniffiLib.uniffi_suggest_fn_clone_suggeststorebuilder(handle, status)
        }
    }

    
    @Throws(SuggestApiException::class)override fun `build`(): SuggestStore {
            return FfiConverterTypeSuggestStore.lift(
    callWithHandle {
    uniffiRustCallWithError(SuggestApiException) { _status ->
    UniffiLib.uniffi_suggest_fn_method_suggeststorebuilder_build(
        it,
        _status)
}
    }
    )
    }
    

    
    /**
     * Deprecated: this is no longer used by the suggest component.
     */override fun `cachePath`(`path`: kotlin.String): SuggestStoreBuilder {
            return FfiConverterTypeSuggestStoreBuilder.lift(
    callWithHandle {
    uniffiRustCall() { _status ->
    UniffiLib.uniffi_suggest_fn_method_suggeststorebuilder_cache_path(
        it,
        FfiConverterString.lower(`path`),_status)
}
    }
    )
    }
    

    override fun `dataPath`(`path`: kotlin.String): SuggestStoreBuilder {
            return FfiConverterTypeSuggestStoreBuilder.lift(
    callWithHandle {
    uniffiRustCall() { _status ->
    UniffiLib.uniffi_suggest_fn_method_suggeststorebuilder_data_path(
        it,
        FfiConverterString.lower(`path`),_status)
}
    }
    )
    }
    

    
    /**
     * Add an sqlite3 extension to load
     *
     * library_name should be the name of the library without any extension, for example `libmozsqlite3`.
     * entrypoint should be the entry point, for example `sqlite3_fts5_init`.  If `null` (the default)
     * entry point will be used (see https://sqlite.org/loadext.html for details).
     */override fun `loadExtension`(`library`: kotlin.String, `entryPoint`: kotlin.String?): SuggestStoreBuilder {
            return FfiConverterTypeSuggestStoreBuilder.lift(
    callWithHandle {
    uniffiRustCall() { _status ->
    UniffiLib.uniffi_suggest_fn_method_suggeststorebuilder_load_extension(
        it,
        FfiConverterString.lower(`library`),FfiConverterOptionalString.lower(`entryPoint`),_status)
}
    }
    )
    }
    

    override fun `remoteSettingsBucketName`(`bucketName`: kotlin.String): SuggestStoreBuilder {
            return FfiConverterTypeSuggestStoreBuilder.lift(
    callWithHandle {
    uniffiRustCall() { _status ->
    UniffiLib.uniffi_suggest_fn_method_suggeststorebuilder_remote_settings_bucket_name(
        it,
        FfiConverterString.lower(`bucketName`),_status)
}
    }
    )
    }
    

    override fun `remoteSettingsServer`(`server`: RemoteSettingsServer): SuggestStoreBuilder {
            return FfiConverterTypeSuggestStoreBuilder.lift(
    callWithHandle {
    uniffiRustCall() { _status ->
    UniffiLib.uniffi_suggest_fn_method_suggeststorebuilder_remote_settings_server(
        it,
        FfiConverterTypeRemoteSettingsServer.lower(`server`),_status)
}
    }
    )
    }
    

    override fun `remoteSettingsService`(`rsService`: RemoteSettingsService): SuggestStoreBuilder {
            return FfiConverterTypeSuggestStoreBuilder.lift(
    callWithHandle {
    uniffiRustCall() { _status ->
    UniffiLib.uniffi_suggest_fn_method_suggeststorebuilder_remote_settings_service(
        it,
        FfiConverterTypeRemoteSettingsService.lower(`rsService`),_status)
}
    }
    )
    }
    

    

    


    
    
    /**
     * @suppress
     */
    companion object
    
}


/**
 * @suppress
 */
public object FfiConverterTypeSuggestStoreBuilder: FfiConverter<SuggestStoreBuilder, Long> {
    override fun lower(value: SuggestStoreBuilder): Long {
        return value.uniffiCloneHandle()
    }

    override fun lift(value: Long): SuggestStoreBuilder {
        return SuggestStoreBuilder(UniffiWithHandle, value)
    }

    override fun read(buf: ByteBuffer): SuggestStoreBuilder {
        return lift(buf.getLong())
    }

    override fun allocationSize(value: SuggestStoreBuilder) = 8UL

    override fun write(value: SuggestStoreBuilder, buf: ByteBuffer) {
        buf.putLong(lower(value))
    }
}



/**
 * A set of names for a single entity.
 */
data class AlternateNames (
    /**
     * The entity's primary name. For a `Geoname`, this is `Geoname::name`.
     */
    var `primary`: kotlin.String
    , 
    /**
     * The entity's name in the language that was ingested according to the
     * locale in the remote settings context. If none exists and this
     * `AlternateNames` is for a `Geoname`, then this will be its primary name.
     */
    var `localized`: kotlin.String?
    , 
    /**
     * The entity's abbreviation, if any.
     */
    var `abbreviation`: kotlin.String?
    
){
    

    

    
    companion object
}

/**
 * @suppress
 */
public object FfiConverterTypeAlternateNames: FfiConverterRustBuffer<AlternateNames> {
    override fun read(buf: ByteBuffer): AlternateNames {
        return AlternateNames(
            FfiConverterString.read(buf),
            FfiConverterOptionalString.read(buf),
            FfiConverterOptionalString.read(buf),
        )
    }

    override fun allocationSize(value: AlternateNames) = (
            FfiConverterString.allocationSize(value.`primary`) +
            FfiConverterOptionalString.allocationSize(value.`localized`) +
            FfiConverterOptionalString.allocationSize(value.`abbreviation`)
    )

    override fun write(value: AlternateNames, buf: ByteBuffer) {
            FfiConverterString.write(value.`primary`, buf)
            FfiConverterOptionalString.write(value.`localized`, buf)
            FfiConverterOptionalString.write(value.`abbreviation`, buf)
    }
}



/**
 * Additional data about how an FTS match was made
 */
data class FtsMatchInfo (
    /**
     * Was this a prefix match (`water b` matched against `water bottle`)
     */
    var `prefix`: kotlin.Boolean
    , 
    /**
     * Did the match require stemming? (`run shoes` matched against `running shoes`)
     */
    var `stemming`: kotlin.Boolean
    
){
    

    

    
    companion object
}

/**
 * @suppress
 */
public object FfiConverterTypeFtsMatchInfo: FfiConverterRustBuffer<FtsMatchInfo> {
    override fun read(buf: ByteBuffer): FtsMatchInfo {
        return FtsMatchInfo(
            FfiConverterBoolean.read(buf),
            FfiConverterBoolean.read(buf),
        )
    }

    override fun allocationSize(value: FtsMatchInfo) = (
            FfiConverterBoolean.allocationSize(value.`prefix`) +
            FfiConverterBoolean.allocationSize(value.`stemming`)
    )

    override fun write(value: FtsMatchInfo, buf: ByteBuffer) {
            FfiConverterBoolean.write(value.`prefix`, buf)
            FfiConverterBoolean.write(value.`stemming`, buf)
    }
}



/**
 * A single geographic place.
 *
 * This corresponds to a single row in the main "geoname" table described in
 * the GeoNames documentation [1]. We exclude fields we don't need.
 *
 * [1]: https://download.geonames.org/export/dump/readme.txt
 */
data class Geoname (
    /**
     * The `geonameid` straight from the geoname table.
     */
    var `geonameId`: kotlin.Long
    , 
    /**
     * The geoname type. This is derived from `feature_class` and
     * `feature_code` as a more convenient representation of the type.
     */
    var `geonameType`: GeonameType
    , 
    /**
     * The place's primary name.
     */
    var `name`: kotlin.String
    , 
    /**
     * ISO-3166 two-letter uppercase country code, e.g., "US".
     */
    var `countryCode`: kotlin.String
    , 
    /**
     * Primary geoname category. Examples:
     *
     * "PCLI" - Independent political entity: country
     * "A" - Administrative division: state, province, borough, district, etc.
     * "P" - Populated place: city, village, etc.
     */
    var `featureClass`: kotlin.String
    , 
    /**
     * Secondary geoname category, depends on `feature_class`. Examples:
     *
     * "ADM1" - Administrative division 1
     * "PPL" - Populated place like a city
     */
    var `featureCode`: kotlin.String
    , 
    /**
     * Administrative divisions. This maps admin division levels (1-based) to
     * their corresponding codes. For example, Liverpool has two admin
     * divisions: "ENG" at level 1 and "H8" at level 2. They would be
     * represented in this map with entries `(1, "ENG")` and `(2, "H8")`.
     */
    var `adminDivisionCodes`: Map<kotlin.UByte, kotlin.String>
    , 
    /**
     * Population size.
     */
    var `population`: kotlin.ULong
    , 
    /**
     * Latitude in decimal degrees (as a string).
     */
    var `latitude`: kotlin.String
    , 
    /**
     * Longitude in decimal degrees (as a string).
     */
    var `longitude`: kotlin.String
    
){
    

    

    
    companion object
}

/**
 * @suppress
 */
public object FfiConverterTypeGeoname: FfiConverterRustBuffer<Geoname> {
    override fun read(buf: ByteBuffer): Geoname {
        return Geoname(
            FfiConverterLong.read(buf),
            FfiConverterTypeGeonameType.read(buf),
            FfiConverterString.read(buf),
            FfiConverterString.read(buf),
            FfiConverterString.read(buf),
            FfiConverterString.read(buf),
            FfiConverterMapUByteString.read(buf),
            FfiConverterULong.read(buf),
            FfiConverterString.read(buf),
            FfiConverterString.read(buf),
        )
    }

    override fun allocationSize(value: Geoname) = (
            FfiConverterLong.allocationSize(value.`geonameId`) +
            FfiConverterTypeGeonameType.allocationSize(value.`geonameType`) +
            FfiConverterString.allocationSize(value.`name`) +
            FfiConverterString.allocationSize(value.`countryCode`) +
            FfiConverterString.allocationSize(value.`featureClass`) +
            FfiConverterString.allocationSize(value.`featureCode`) +
            FfiConverterMapUByteString.allocationSize(value.`adminDivisionCodes`) +
            FfiConverterULong.allocationSize(value.`population`) +
            FfiConverterString.allocationSize(value.`latitude`) +
            FfiConverterString.allocationSize(value.`longitude`)
    )

    override fun write(value: Geoname, buf: ByteBuffer) {
            FfiConverterLong.write(value.`geonameId`, buf)
            FfiConverterTypeGeonameType.write(value.`geonameType`, buf)
            FfiConverterString.write(value.`name`, buf)
            FfiConverterString.write(value.`countryCode`, buf)
            FfiConverterString.write(value.`featureClass`, buf)
            FfiConverterString.write(value.`featureCode`, buf)
            FfiConverterMapUByteString.write(value.`adminDivisionCodes`, buf)
            FfiConverterULong.write(value.`population`, buf)
            FfiConverterString.write(value.`latitude`, buf)
            FfiConverterString.write(value.`longitude`, buf)
    }
}



/**
 * Alternate names for a geoname and its country and admin divisions.
 */
data class GeonameAlternates (
    /**
     * Names for the geoname itself.
     */
    var `geoname`: AlternateNames
    , 
    /**
     * Names for the geoname's country. This will be `Some` as long as the
     * country is also in the ingested data, which should typically be true.
     */
    var `country`: AlternateNames?
    , 
    /**
     * Names for the geoname's admin divisions. This is parallel to
     * `Geoname::admin_division_codes`. If there are no names in the ingested
     * data for an admin division, then it will be absent from this map.
     */
    var `adminDivisions`: Map<kotlin.UByte, AlternateNames>
    
){
    

    

    
    companion object
}

/**
 * @suppress
 */
public object FfiConverterTypeGeonameAlternates: FfiConverterRustBuffer<GeonameAlternates> {
    override fun read(buf: ByteBuffer): GeonameAlternates {
        return GeonameAlternates(
            FfiConverterTypeAlternateNames.read(buf),
            FfiConverterOptionalTypeAlternateNames.read(buf),
            FfiConverterMapUByteTypeAlternateNames.read(buf),
        )
    }

    override fun allocationSize(value: GeonameAlternates) = (
            FfiConverterTypeAlternateNames.allocationSize(value.`geoname`) +
            FfiConverterOptionalTypeAlternateNames.allocationSize(value.`country`) +
            FfiConverterMapUByteTypeAlternateNames.allocationSize(value.`adminDivisions`)
    )

    override fun write(value: GeonameAlternates, buf: ByteBuffer) {
            FfiConverterTypeAlternateNames.write(value.`geoname`, buf)
            FfiConverterOptionalTypeAlternateNames.write(value.`country`, buf)
            FfiConverterMapUByteTypeAlternateNames.write(value.`adminDivisions`, buf)
    }
}



/**
 * A fetched geoname with info on how it was matched.
 */
data class GeonameMatch (
    /**
     * The geoname that was matched.
     */
    var `geoname`: Geoname
    , 
    /**
     * The type of name that was matched.
     */
    var `matchType`: GeonameMatchType
    , 
    /**
     * Whether the name was matched by prefix.
     */
    var `prefix`: kotlin.Boolean
    
){
    

    

    
    companion object
}

/**
 * @suppress
 */
public object FfiConverterTypeGeonameMatch: FfiConverterRustBuffer<GeonameMatch> {
    override fun read(buf: ByteBuffer): GeonameMatch {
        return GeonameMatch(
            FfiConverterTypeGeoname.read(buf),
            FfiConverterTypeGeonameMatchType.read(buf),
            FfiConverterBoolean.read(buf),
        )
    }

    override fun allocationSize(value: GeonameMatch) = (
            FfiConverterTypeGeoname.allocationSize(value.`geoname`) +
            FfiConverterTypeGeonameMatchType.allocationSize(value.`matchType`) +
            FfiConverterBoolean.allocationSize(value.`prefix`)
    )

    override fun write(value: GeonameMatch, buf: ByteBuffer) {
            FfiConverterTypeGeoname.write(value.`geoname`, buf)
            FfiConverterTypeGeonameMatchType.write(value.`matchType`, buf)
            FfiConverterBoolean.write(value.`prefix`, buf)
    }
}



/**
 * Single sample for a Glean labeled_timing_distribution
 */
data class LabeledTimingSample (
    var `label`: kotlin.String
    , 
    /**
     * Time in microseconds
     */
    var `value`: kotlin.ULong
    
){
    

    

    
    companion object
}

/**
 * @suppress
 */
public object FfiConverterTypeLabeledTimingSample: FfiConverterRustBuffer<LabeledTimingSample> {
    override fun read(buf: ByteBuffer): LabeledTimingSample {
        return LabeledTimingSample(
            FfiConverterString.read(buf),
            FfiConverterULong.read(buf),
        )
    }

    override fun allocationSize(value: LabeledTimingSample) = (
            FfiConverterString.allocationSize(value.`label`) +
            FfiConverterULong.allocationSize(value.`value`)
    )

    override fun write(value: LabeledTimingSample, buf: ByteBuffer) {
            FfiConverterString.write(value.`label`, buf)
            FfiConverterULong.write(value.`value`, buf)
    }
}



data class QueryWithMetricsResult (
    var `suggestions`: List<Suggestion>
    , 
    /**
     * Samples for the `suggest.query_time` metric
     */
    var `queryTimes`: List<LabeledTimingSample>
    
){
    

    

    
    companion object
}

/**
 * @suppress
 */
public object FfiConverterTypeQueryWithMetricsResult: FfiConverterRustBuffer<QueryWithMetricsResult> {
    override fun read(buf: ByteBuffer): QueryWithMetricsResult {
        return QueryWithMetricsResult(
            FfiConverterSequenceTypeSuggestion.read(buf),
            FfiConverterSequenceTypeLabeledTimingSample.read(buf),
        )
    }

    override fun allocationSize(value: QueryWithMetricsResult) = (
            FfiConverterSequenceTypeSuggestion.allocationSize(value.`suggestions`) +
            FfiConverterSequenceTypeLabeledTimingSample.allocationSize(value.`queryTimes`)
    )

    override fun write(value: QueryWithMetricsResult, buf: ByteBuffer) {
            FfiConverterSequenceTypeSuggestion.write(value.`suggestions`, buf)
            FfiConverterSequenceTypeLabeledTimingSample.write(value.`queryTimes`, buf)
    }
}



/**
 * Global Suggest configuration data.
 */
data class SuggestGlobalConfig (
    var `showLessFrequentlyCap`: kotlin.Int
    
){
    

    

    
    companion object
}

/**
 * @suppress
 */
public object FfiConverterTypeSuggestGlobalConfig: FfiConverterRustBuffer<SuggestGlobalConfig> {
    override fun read(buf: ByteBuffer): SuggestGlobalConfig {
        return SuggestGlobalConfig(
            FfiConverterInt.read(buf),
        )
    }

    override fun allocationSize(value: SuggestGlobalConfig) = (
            FfiConverterInt.allocationSize(value.`showLessFrequentlyCap`)
    )

    override fun write(value: SuggestGlobalConfig, buf: ByteBuffer) {
            FfiConverterInt.write(value.`showLessFrequentlyCap`, buf)
    }
}



/**
 * Constraints limit which suggestions to ingest from Remote Settings.
 */
data class SuggestIngestionConstraints (
    var `providers`: List<SuggestionProvider>? = null 
    , 
    var `providerConstraints`: SuggestionProviderConstraints? = null 
    , 
    /**
     * Only run ingestion if the table `suggestions` is empty

     */
    var `emptyOnly`: kotlin.Boolean = false 
    
){
    

    

    
    companion object
}

/**
 * @suppress
 */
public object FfiConverterTypeSuggestIngestionConstraints: FfiConverterRustBuffer<SuggestIngestionConstraints> {
    override fun read(buf: ByteBuffer): SuggestIngestionConstraints {
        return SuggestIngestionConstraints(
            FfiConverterOptionalSequenceTypeSuggestionProvider.read(buf),
            FfiConverterOptionalTypeSuggestionProviderConstraints.read(buf),
            FfiConverterBoolean.read(buf),
        )
    }

    override fun allocationSize(value: SuggestIngestionConstraints) = (
            FfiConverterOptionalSequenceTypeSuggestionProvider.allocationSize(value.`providers`) +
            FfiConverterOptionalTypeSuggestionProviderConstraints.allocationSize(value.`providerConstraints`) +
            FfiConverterBoolean.allocationSize(value.`emptyOnly`)
    )

    override fun write(value: SuggestIngestionConstraints, buf: ByteBuffer) {
            FfiConverterOptionalSequenceTypeSuggestionProvider.write(value.`providers`, buf)
            FfiConverterOptionalTypeSuggestionProviderConstraints.write(value.`providerConstraints`, buf)
            FfiConverterBoolean.write(value.`emptyOnly`, buf)
    }
}



/**
 * Ingestion metrics
 *
 * These are recorded during [crate::Store::ingest] and returned to the consumer to record.
 */
data class SuggestIngestionMetrics (
    /**
     * Samples for the `suggest.ingestion_time` metric
     */
    var `ingestionTimes`: List<LabeledTimingSample>
    , 
    /**
     * Samples for the `suggest.ingestion_download_time` metric
     */
    var `downloadTimes`: List<LabeledTimingSample>
    
){
    

    

    
    companion object
}

/**
 * @suppress
 */
public object FfiConverterTypeSuggestIngestionMetrics: FfiConverterRustBuffer<SuggestIngestionMetrics> {
    override fun read(buf: ByteBuffer): SuggestIngestionMetrics {
        return SuggestIngestionMetrics(
            FfiConverterSequenceTypeLabeledTimingSample.read(buf),
            FfiConverterSequenceTypeLabeledTimingSample.read(buf),
        )
    }

    override fun allocationSize(value: SuggestIngestionMetrics) = (
            FfiConverterSequenceTypeLabeledTimingSample.allocationSize(value.`ingestionTimes`) +
            FfiConverterSequenceTypeLabeledTimingSample.allocationSize(value.`downloadTimes`)
    )

    override fun write(value: SuggestIngestionMetrics, buf: ByteBuffer) {
            FfiConverterSequenceTypeLabeledTimingSample.write(value.`ingestionTimes`, buf)
            FfiConverterSequenceTypeLabeledTimingSample.write(value.`downloadTimes`, buf)
    }
}



/**
 * Some providers manage multiple suggestion subtypes. Queries, ingests, and
 * other operations on those providers must be constrained to a desired subtype.
 */
data class SuggestionProviderConstraints (
    /**
     * Which dynamic suggestions should we fetch or ingest? Corresponds to the
     * `suggestion_type` value in dynamic suggestions remote settings records.
     */
    var `dynamicSuggestionTypes`: List<kotlin.String>? = null 
    , 
    /**
     * Which strategy should we use for the AMP queries?
     * Use None for the default strategy.
     */
    var `ampAlternativeMatching`: AmpMatchingStrategy? = null 
    
){
    

    

    
    companion object
}

/**
 * @suppress
 */
public object FfiConverterTypeSuggestionProviderConstraints: FfiConverterRustBuffer<SuggestionProviderConstraints> {
    override fun read(buf: ByteBuffer): SuggestionProviderConstraints {
        return SuggestionProviderConstraints(
            FfiConverterOptionalSequenceString.read(buf),
            FfiConverterOptionalTypeAmpMatchingStrategy.read(buf),
        )
    }

    override fun allocationSize(value: SuggestionProviderConstraints) = (
            FfiConverterOptionalSequenceString.allocationSize(value.`dynamicSuggestionTypes`) +
            FfiConverterOptionalTypeAmpMatchingStrategy.allocationSize(value.`ampAlternativeMatching`)
    )

    override fun write(value: SuggestionProviderConstraints, buf: ByteBuffer) {
            FfiConverterOptionalSequenceString.write(value.`dynamicSuggestionTypes`, buf)
            FfiConverterOptionalTypeAmpMatchingStrategy.write(value.`ampAlternativeMatching`, buf)
    }
}



/**
 * A query for suggestions to show in the address bar.
 */
data class SuggestionQuery (
    var `keyword`: kotlin.String
    , 
    var `providers`: List<SuggestionProvider>
    , 
    var `providerConstraints`: SuggestionProviderConstraints? = null 
    , 
    var `limit`: kotlin.Int? = null 
    
){
    

    

    
    companion object
}

/**
 * @suppress
 */
public object FfiConverterTypeSuggestionQuery: FfiConverterRustBuffer<SuggestionQuery> {
    override fun read(buf: ByteBuffer): SuggestionQuery {
        return SuggestionQuery(
            FfiConverterString.read(buf),
            FfiConverterSequenceTypeSuggestionProvider.read(buf),
            FfiConverterOptionalTypeSuggestionProviderConstraints.read(buf),
            FfiConverterOptionalInt.read(buf),
        )
    }

    override fun allocationSize(value: SuggestionQuery) = (
            FfiConverterString.allocationSize(value.`keyword`) +
            FfiConverterSequenceTypeSuggestionProvider.allocationSize(value.`providers`) +
            FfiConverterOptionalTypeSuggestionProviderConstraints.allocationSize(value.`providerConstraints`) +
            FfiConverterOptionalInt.allocationSize(value.`limit`)
    )

    override fun write(value: SuggestionQuery, buf: ByteBuffer) {
            FfiConverterString.write(value.`keyword`, buf)
            FfiConverterSequenceTypeSuggestionProvider.write(value.`providers`, buf)
            FfiConverterOptionalTypeSuggestionProviderConstraints.write(value.`providerConstraints`, buf)
            FfiConverterOptionalInt.write(value.`limit`, buf)
    }
}




enum class AmpMatchingStrategy {
    
    /**
     * Disable keywords added via keyword expansion.
     * This eliminates keywords that for terms related to the "real" keywords, for example
     * misspellings like "underarmor" instead of "under armor"'.
     */
    NO_KEYWORD_EXPANSION,
    /**
     * Use FTS matching against the full keywords, joined together.
     */
    FTS_AGAINST_FULL_KEYWORDS,
    /**
     * Use FTS matching against the title field
     */
    FTS_AGAINST_TITLE;

    


    companion object
}


/**
 * @suppress
 */
public object FfiConverterTypeAmpMatchingStrategy: FfiConverterRustBuffer<AmpMatchingStrategy> {
    override fun read(buf: ByteBuffer) = try {
        AmpMatchingStrategy.values()[buf.getInt() - 1]
    } catch (e: IndexOutOfBoundsException) {
        throw RuntimeException("invalid enum value, something is very wrong!!", e)
    }

    override fun allocationSize(value: AmpMatchingStrategy) = 4UL

    override fun write(value: AmpMatchingStrategy, buf: ByteBuffer) {
        buf.putInt(value.ordinal + 1)
    }
}






enum class GeonameMatchType {
    
    ABBREVIATION,
    AIRPORT_CODE,
    /**
     * This includes any names that aren't abbreviations or airport codes.
     */
    NAME;

    


    companion object
}


/**
 * @suppress
 */
public object FfiConverterTypeGeonameMatchType: FfiConverterRustBuffer<GeonameMatchType> {
    override fun read(buf: ByteBuffer) = try {
        GeonameMatchType.values()[buf.getInt() - 1]
    } catch (e: IndexOutOfBoundsException) {
        throw RuntimeException("invalid enum value, something is very wrong!!", e)
    }

    override fun allocationSize(value: GeonameMatchType) = 4UL

    override fun write(value: GeonameMatchType, buf: ByteBuffer) {
        buf.putInt(value.ordinal + 1)
    }
}





/**
 * The type of a geoname.
 */
sealed class GeonameType {
    
    object Country : GeonameType()
    
    
    /**
     * A state, province, prefecture, district, borough, etc.
     */
    data class AdminDivision(
        val `level`: kotlin.UByte) : GeonameType()
        
    {
        

        companion object
    }
    
    object AdminDivisionOther : GeonameType()
    
    
    /**
     * A city, town, village, populated place, etc.
     */
    object City : GeonameType()
    
    
    object Other : GeonameType()
    
    

    

    
    


    companion object
}

/**
 * @suppress
 */
public object FfiConverterTypeGeonameType : FfiConverterRustBuffer<GeonameType>{
    override fun read(buf: ByteBuffer): GeonameType {
        return when(buf.getInt()) {
            1 -> GeonameType.Country
            2 -> GeonameType.AdminDivision(
                FfiConverterUByte.read(buf),
                )
            3 -> GeonameType.AdminDivisionOther
            4 -> GeonameType.City
            5 -> GeonameType.Other
            else -> throw RuntimeException("invalid enum value, something is very wrong!!")
        }
    }

    override fun allocationSize(value: GeonameType) = when(value) {
        is GeonameType.Country -> {
            // Add the size for the Int that specifies the variant plus the size needed for all fields
            (
                4UL
            )
        }
        is GeonameType.AdminDivision -> {
            // Add the size for the Int that specifies the variant plus the size needed for all fields
            (
                4UL
                + FfiConverterUByte.allocationSize(value.`level`)
            )
        }
        is GeonameType.AdminDivisionOther -> {
            // Add the size for the Int that specifies the variant plus the size needed for all fields
            (
                4UL
            )
        }
        is GeonameType.City -> {
            // Add the size for the Int that specifies the variant plus the size needed for all fields
            (
                4UL
            )
        }
        is GeonameType.Other -> {
            // Add the size for the Int that specifies the variant plus the size needed for all fields
            (
                4UL
            )
        }
    }

    override fun write(value: GeonameType, buf: ByteBuffer) {
        when(value) {
            is GeonameType.Country -> {
                buf.putInt(1)
                Unit
            }
            is GeonameType.AdminDivision -> {
                buf.putInt(2)
                FfiConverterUByte.write(value.`level`, buf)
                Unit
            }
            is GeonameType.AdminDivisionOther -> {
                buf.putInt(3)
                Unit
            }
            is GeonameType.City -> {
                buf.putInt(4)
                Unit
            }
            is GeonameType.Other -> {
                buf.putInt(5)
                Unit
            }
        }.let { /* this makes the `when` an expression, which ensures it is exhaustive */ }
    }
}





/**
 * What should be interrupted when [SuggestStore::interrupt] is called?
 */

enum class InterruptKind {
    
    /**
     * Interrupt read operations like [SuggestStore::query]
     */
    READ,
    /**
     * Interrupt write operations.  This mostly means [SuggestStore::ingest], but
     * other operations may also be interrupted.
     */
    WRITE,
    /**
     * Interrupt both read and write operations,
     */
    READ_WRITE;

    


    companion object
}


/**
 * @suppress
 */
public object FfiConverterTypeInterruptKind: FfiConverterRustBuffer<InterruptKind> {
    override fun read(buf: ByteBuffer) = try {
        InterruptKind.values()[buf.getInt() - 1]
    } catch (e: IndexOutOfBoundsException) {
        throw RuntimeException("invalid enum value, something is very wrong!!", e)
    }

    override fun allocationSize(value: InterruptKind) = 4UL

    override fun write(value: InterruptKind, buf: ByteBuffer) {
        buf.putInt(value.ordinal + 1)
    }
}







/**
 * The error type for all Suggest component operations. These errors are
 * exposed to your application, which should handle them as needed.
 */
sealed class SuggestApiException: kotlin.Exception() {
    
    class Network(
        
        val `reason`: kotlin.String
        ) : SuggestApiException() {
        override val message
            get() = "reason=${ `reason` }"
    }
    
    /**
     * The server requested a backoff after too many requests
     */
    class Backoff(
        
        val `seconds`: kotlin.ULong
        ) : SuggestApiException() {
        override val message
            get() = "seconds=${ `seconds` }"
    }
    
    /**
     * An operation was interrupted by calling `SuggestStore.interrupt()`
     */
    class Interrupted(
        ) : SuggestApiException() {
        override val message
            get() = ""
    }
    
    class Other(
        
        val `reason`: kotlin.String
        ) : SuggestApiException() {
        override val message
            get() = "reason=${ `reason` }"
    }
    

    


    companion object ErrorHandler : UniffiRustCallStatusErrorHandler<SuggestApiException> {
        override fun lift(error_buf: RustBuffer.ByValue): SuggestApiException = FfiConverterTypeSuggestApiError.lift(error_buf)
    }

    
}

/**
 * @suppress
 */
public object FfiConverterTypeSuggestApiError : FfiConverterRustBuffer<SuggestApiException> {
    override fun read(buf: ByteBuffer): SuggestApiException {
        

        return when(buf.getInt()) {
            1 -> SuggestApiException.Network(
                FfiConverterString.read(buf),
                )
            2 -> SuggestApiException.Backoff(
                FfiConverterULong.read(buf),
                )
            3 -> SuggestApiException.Interrupted()
            4 -> SuggestApiException.Other(
                FfiConverterString.read(buf),
                )
            else -> throw RuntimeException("invalid error enum value, something is very wrong!!")
        }
    }

    override fun allocationSize(value: SuggestApiException): ULong {
        return when(value) {
            is SuggestApiException.Network -> (
                // Add the size for the Int that specifies the variant plus the size needed for all fields
                4UL
                + FfiConverterString.allocationSize(value.`reason`)
            )
            is SuggestApiException.Backoff -> (
                // Add the size for the Int that specifies the variant plus the size needed for all fields
                4UL
                + FfiConverterULong.allocationSize(value.`seconds`)
            )
            is SuggestApiException.Interrupted -> (
                // Add the size for the Int that specifies the variant plus the size needed for all fields
                4UL
            )
            is SuggestApiException.Other -> (
                // Add the size for the Int that specifies the variant plus the size needed for all fields
                4UL
                + FfiConverterString.allocationSize(value.`reason`)
            )
        }
    }

    override fun write(value: SuggestApiException, buf: ByteBuffer) {
        when(value) {
            is SuggestApiException.Network -> {
                buf.putInt(1)
                FfiConverterString.write(value.`reason`, buf)
                Unit
            }
            is SuggestApiException.Backoff -> {
                buf.putInt(2)
                FfiConverterULong.write(value.`seconds`, buf)
                Unit
            }
            is SuggestApiException.Interrupted -> {
                buf.putInt(3)
                Unit
            }
            is SuggestApiException.Other -> {
                buf.putInt(4)
                FfiConverterString.write(value.`reason`, buf)
                Unit
            }
        }.let { /* this makes the `when` an expression, which ensures it is exhaustive */ }
    }

}



/**
 * Per-provider configuration data.
 */
sealed class SuggestProviderConfig {
    
    data class Weather(
        /**
         * Weather suggestion score.
         */
        val `score`: kotlin.Double, 
        /**
         * Threshold for weather keyword prefix matching when a weather keyword
         * is the first term in a query. Zero means prefix matching is disabled
         * and weather keywords must be typed in full when they are first in
         * the query. (Ideally this would be an `Option` and `None` would mean
         * full keywords are required, but it's probably not worth the breaking
         * API change.) This threshold does not apply to city and region names.
         */
        val `minKeywordLength`: kotlin.Int) : SuggestProviderConfig()
        
    {
        

        companion object
    }
    

    

    
    


    companion object
}

/**
 * @suppress
 */
public object FfiConverterTypeSuggestProviderConfig : FfiConverterRustBuffer<SuggestProviderConfig>{
    override fun read(buf: ByteBuffer): SuggestProviderConfig {
        return when(buf.getInt()) {
            1 -> SuggestProviderConfig.Weather(
                FfiConverterDouble.read(buf),
                FfiConverterInt.read(buf),
                )
            else -> throw RuntimeException("invalid enum value, something is very wrong!!")
        }
    }

    override fun allocationSize(value: SuggestProviderConfig) = when(value) {
        is SuggestProviderConfig.Weather -> {
            // Add the size for the Int that specifies the variant plus the size needed for all fields
            (
                4UL
                + FfiConverterDouble.allocationSize(value.`score`)
                + FfiConverterInt.allocationSize(value.`minKeywordLength`)
            )
        }
    }

    override fun write(value: SuggestProviderConfig, buf: ByteBuffer) {
        when(value) {
            is SuggestProviderConfig.Weather -> {
                buf.putInt(1)
                FfiConverterDouble.write(value.`score`, buf)
                FfiConverterInt.write(value.`minKeywordLength`, buf)
                Unit
            }
        }.let { /* this makes the `when` an expression, which ensures it is exhaustive */ }
    }
}





/**
 * A suggestion from the database to show in the address bar.
 */
sealed class Suggestion {
    
    data class Amp(
        val `title`: kotlin.String, 
        val `url`: kotlin.String, 
        val `rawUrl`: kotlin.String, 
        val `icon`: kotlin.ByteArray?, 
        val `iconMimetype`: kotlin.String?, 
        val `fullKeyword`: kotlin.String, 
        val `blockId`: kotlin.Long, 
        val `advertiser`: kotlin.String, 
        val `iabCategory`: kotlin.String, 
        val `categories`: List<kotlin.Int>, 
        val `impressionUrl`: kotlin.String, 
        val `clickUrl`: kotlin.String, 
        val `rawClickUrl`: kotlin.String, 
        val `score`: kotlin.Double, 
        val `ftsMatchInfo`: mozilla.appservices.suggest.FtsMatchInfo?) : Suggestion()
        
    {
        

        companion object
    }
    
    data class Wikipedia(
        val `title`: kotlin.String, 
        val `url`: kotlin.String, 
        val `icon`: kotlin.ByteArray?, 
        val `iconMimetype`: kotlin.String?, 
        val `fullKeyword`: kotlin.String) : Suggestion()
        
    {
        

        companion object
    }
    
    data class Amo(
        val `title`: kotlin.String, 
        val `url`: kotlin.String, 
        val `iconUrl`: kotlin.String, 
        val `description`: kotlin.String, 
        val `rating`: kotlin.String?, 
        val `numberOfRatings`: kotlin.Long, 
        val `guid`: kotlin.String, 
        val `score`: kotlin.Double) : Suggestion()
        
    {
        

        companion object
    }
    
    data class Yelp(
        val `url`: kotlin.String, 
        val `title`: kotlin.String, 
        val `icon`: kotlin.ByteArray?, 
        val `iconMimetype`: kotlin.String?, 
        val `score`: kotlin.Double, 
        val `hasLocationSign`: kotlin.Boolean, 
        val `subjectExactMatch`: kotlin.Boolean, 
        val `subjectType`: mozilla.appservices.suggest.YelpSubjectType, 
        val `locationParam`: kotlin.String) : Suggestion()
        
    {
        

        companion object
    }
    
    data class Mdn(
        val `title`: kotlin.String, 
        val `url`: kotlin.String, 
        val `description`: kotlin.String, 
        val `score`: kotlin.Double) : Suggestion()
        
    {
        

        companion object
    }
    
    data class Weather(
        val `city`: mozilla.appservices.suggest.Geoname?, 
        val `score`: kotlin.Double) : Suggestion()
        
    {
        

        companion object
    }
    
    data class Dynamic(
        val `suggestionType`: kotlin.String, 
        val `data`: mozilla.appservices.suggest.JsonValue?, 
        /**
         * This value is optionally defined in the suggestion's remote settings
         * data and is an opaque token used for dismissing the suggestion in
         * lieu of a URL. If `Some`, the suggestion can be dismissed by passing
         * the wrapped string to [crate::SuggestStore::dismiss_suggestion].
         */
        val `dismissalKey`: kotlin.String?, 
        val `score`: kotlin.Double) : Suggestion()
        
    {
        

        companion object
    }
    

    

    
    


    companion object
}

/**
 * @suppress
 */
public object FfiConverterTypeSuggestion : FfiConverterRustBuffer<Suggestion>{
    override fun read(buf: ByteBuffer): Suggestion {
        return when(buf.getInt()) {
            1 -> Suggestion.Amp(
                FfiConverterString.read(buf),
                FfiConverterString.read(buf),
                FfiConverterString.read(buf),
                FfiConverterOptionalByteArray.read(buf),
                FfiConverterOptionalString.read(buf),
                FfiConverterString.read(buf),
                FfiConverterLong.read(buf),
                FfiConverterString.read(buf),
                FfiConverterString.read(buf),
                FfiConverterSequenceInt.read(buf),
                FfiConverterString.read(buf),
                FfiConverterString.read(buf),
                FfiConverterString.read(buf),
                FfiConverterDouble.read(buf),
                FfiConverterOptionalTypeFtsMatchInfo.read(buf),
                )
            2 -> Suggestion.Wikipedia(
                FfiConverterString.read(buf),
                FfiConverterString.read(buf),
                FfiConverterOptionalByteArray.read(buf),
                FfiConverterOptionalString.read(buf),
                FfiConverterString.read(buf),
                )
            3 -> Suggestion.Amo(
                FfiConverterString.read(buf),
                FfiConverterString.read(buf),
                FfiConverterString.read(buf),
                FfiConverterString.read(buf),
                FfiConverterOptionalString.read(buf),
                FfiConverterLong.read(buf),
                FfiConverterString.read(buf),
                FfiConverterDouble.read(buf),
                )
            4 -> Suggestion.Yelp(
                FfiConverterString.read(buf),
                FfiConverterString.read(buf),
                FfiConverterOptionalByteArray.read(buf),
                FfiConverterOptionalString.read(buf),
                FfiConverterDouble.read(buf),
                FfiConverterBoolean.read(buf),
                FfiConverterBoolean.read(buf),
                FfiConverterTypeYelpSubjectType.read(buf),
                FfiConverterString.read(buf),
                )
            5 -> Suggestion.Mdn(
                FfiConverterString.read(buf),
                FfiConverterString.read(buf),
                FfiConverterString.read(buf),
                FfiConverterDouble.read(buf),
                )
            6 -> Suggestion.Weather(
                FfiConverterOptionalTypeGeoname.read(buf),
                FfiConverterDouble.read(buf),
                )
            7 -> Suggestion.Dynamic(
                FfiConverterString.read(buf),
                FfiConverterOptionalTypeJsonValue.read(buf),
                FfiConverterOptionalString.read(buf),
                FfiConverterDouble.read(buf),
                )
            else -> throw RuntimeException("invalid enum value, something is very wrong!!")
        }
    }

    override fun allocationSize(value: Suggestion) = when(value) {
        is Suggestion.Amp -> {
            // Add the size for the Int that specifies the variant plus the size needed for all fields
            (
                4UL
                + FfiConverterString.allocationSize(value.`title`)
                + FfiConverterString.allocationSize(value.`url`)
                + FfiConverterString.allocationSize(value.`rawUrl`)
                + FfiConverterOptionalByteArray.allocationSize(value.`icon`)
                + FfiConverterOptionalString.allocationSize(value.`iconMimetype`)
                + FfiConverterString.allocationSize(value.`fullKeyword`)
                + FfiConverterLong.allocationSize(value.`blockId`)
                + FfiConverterString.allocationSize(value.`advertiser`)
                + FfiConverterString.allocationSize(value.`iabCategory`)
                + FfiConverterSequenceInt.allocationSize(value.`categories`)
                + FfiConverterString.allocationSize(value.`impressionUrl`)
                + FfiConverterString.allocationSize(value.`clickUrl`)
                + FfiConverterString.allocationSize(value.`rawClickUrl`)
                + FfiConverterDouble.allocationSize(value.`score`)
                + FfiConverterOptionalTypeFtsMatchInfo.allocationSize(value.`ftsMatchInfo`)
            )
        }
        is Suggestion.Wikipedia -> {
            // Add the size for the Int that specifies the variant plus the size needed for all fields
            (
                4UL
                + FfiConverterString.allocationSize(value.`title`)
                + FfiConverterString.allocationSize(value.`url`)
                + FfiConverterOptionalByteArray.allocationSize(value.`icon`)
                + FfiConverterOptionalString.allocationSize(value.`iconMimetype`)
                + FfiConverterString.allocationSize(value.`fullKeyword`)
            )
        }
        is Suggestion.Amo -> {
            // Add the size for the Int that specifies the variant plus the size needed for all fields
            (
                4UL
                + FfiConverterString.allocationSize(value.`title`)
                + FfiConverterString.allocationSize(value.`url`)
                + FfiConverterString.allocationSize(value.`iconUrl`)
                + FfiConverterString.allocationSize(value.`description`)
                + FfiConverterOptionalString.allocationSize(value.`rating`)
                + FfiConverterLong.allocationSize(value.`numberOfRatings`)
                + FfiConverterString.allocationSize(value.`guid`)
                + FfiConverterDouble.allocationSize(value.`score`)
            )
        }
        is Suggestion.Yelp -> {
            // Add the size for the Int that specifies the variant plus the size needed for all fields
            (
                4UL
                + FfiConverterString.allocationSize(value.`url`)
                + FfiConverterString.allocationSize(value.`title`)
                + FfiConverterOptionalByteArray.allocationSize(value.`icon`)
                + FfiConverterOptionalString.allocationSize(value.`iconMimetype`)
                + FfiConverterDouble.allocationSize(value.`score`)
                + FfiConverterBoolean.allocationSize(value.`hasLocationSign`)
                + FfiConverterBoolean.allocationSize(value.`subjectExactMatch`)
                + FfiConverterTypeYelpSubjectType.allocationSize(value.`subjectType`)
                + FfiConverterString.allocationSize(value.`locationParam`)
            )
        }
        is Suggestion.Mdn -> {
            // Add the size for the Int that specifies the variant plus the size needed for all fields
            (
                4UL
                + FfiConverterString.allocationSize(value.`title`)
                + FfiConverterString.allocationSize(value.`url`)
                + FfiConverterString.allocationSize(value.`description`)
                + FfiConverterDouble.allocationSize(value.`score`)
            )
        }
        is Suggestion.Weather -> {
            // Add the size for the Int that specifies the variant plus the size needed for all fields
            (
                4UL
                + FfiConverterOptionalTypeGeoname.allocationSize(value.`city`)
                + FfiConverterDouble.allocationSize(value.`score`)
            )
        }
        is Suggestion.Dynamic -> {
            // Add the size for the Int that specifies the variant plus the size needed for all fields
            (
                4UL
                + FfiConverterString.allocationSize(value.`suggestionType`)
                + FfiConverterOptionalTypeJsonValue.allocationSize(value.`data`)
                + FfiConverterOptionalString.allocationSize(value.`dismissalKey`)
                + FfiConverterDouble.allocationSize(value.`score`)
            )
        }
    }

    override fun write(value: Suggestion, buf: ByteBuffer) {
        when(value) {
            is Suggestion.Amp -> {
                buf.putInt(1)
                FfiConverterString.write(value.`title`, buf)
                FfiConverterString.write(value.`url`, buf)
                FfiConverterString.write(value.`rawUrl`, buf)
                FfiConverterOptionalByteArray.write(value.`icon`, buf)
                FfiConverterOptionalString.write(value.`iconMimetype`, buf)
                FfiConverterString.write(value.`fullKeyword`, buf)
                FfiConverterLong.write(value.`blockId`, buf)
                FfiConverterString.write(value.`advertiser`, buf)
                FfiConverterString.write(value.`iabCategory`, buf)
                FfiConverterSequenceInt.write(value.`categories`, buf)
                FfiConverterString.write(value.`impressionUrl`, buf)
                FfiConverterString.write(value.`clickUrl`, buf)
                FfiConverterString.write(value.`rawClickUrl`, buf)
                FfiConverterDouble.write(value.`score`, buf)
                FfiConverterOptionalTypeFtsMatchInfo.write(value.`ftsMatchInfo`, buf)
                Unit
            }
            is Suggestion.Wikipedia -> {
                buf.putInt(2)
                FfiConverterString.write(value.`title`, buf)
                FfiConverterString.write(value.`url`, buf)
                FfiConverterOptionalByteArray.write(value.`icon`, buf)
                FfiConverterOptionalString.write(value.`iconMimetype`, buf)
                FfiConverterString.write(value.`fullKeyword`, buf)
                Unit
            }
            is Suggestion.Amo -> {
                buf.putInt(3)
                FfiConverterString.write(value.`title`, buf)
                FfiConverterString.write(value.`url`, buf)
                FfiConverterString.write(value.`iconUrl`, buf)
                FfiConverterString.write(value.`description`, buf)
                FfiConverterOptionalString.write(value.`rating`, buf)
                FfiConverterLong.write(value.`numberOfRatings`, buf)
                FfiConverterString.write(value.`guid`, buf)
                FfiConverterDouble.write(value.`score`, buf)
                Unit
            }
            is Suggestion.Yelp -> {
                buf.putInt(4)
                FfiConverterString.write(value.`url`, buf)
                FfiConverterString.write(value.`title`, buf)
                FfiConverterOptionalByteArray.write(value.`icon`, buf)
                FfiConverterOptionalString.write(value.`iconMimetype`, buf)
                FfiConverterDouble.write(value.`score`, buf)
                FfiConverterBoolean.write(value.`hasLocationSign`, buf)
                FfiConverterBoolean.write(value.`subjectExactMatch`, buf)
                FfiConverterTypeYelpSubjectType.write(value.`subjectType`, buf)
                FfiConverterString.write(value.`locationParam`, buf)
                Unit
            }
            is Suggestion.Mdn -> {
                buf.putInt(5)
                FfiConverterString.write(value.`title`, buf)
                FfiConverterString.write(value.`url`, buf)
                FfiConverterString.write(value.`description`, buf)
                FfiConverterDouble.write(value.`score`, buf)
                Unit
            }
            is Suggestion.Weather -> {
                buf.putInt(6)
                FfiConverterOptionalTypeGeoname.write(value.`city`, buf)
                FfiConverterDouble.write(value.`score`, buf)
                Unit
            }
            is Suggestion.Dynamic -> {
                buf.putInt(7)
                FfiConverterString.write(value.`suggestionType`, buf)
                FfiConverterOptionalTypeJsonValue.write(value.`data`, buf)
                FfiConverterOptionalString.write(value.`dismissalKey`, buf)
                FfiConverterDouble.write(value.`score`, buf)
                Unit
            }
        }.let { /* this makes the `when` an expression, which ensures it is exhaustive */ }
    }
}





/**
 * A provider is a source of search suggestions.
 * Please preserve the integer values after removing or adding providers.
 * Provider configs are associated with integer keys stored in the database.
 */

enum class SuggestionProvider(val value: kotlin.UByte) {
    
    AMP(1u),
    WIKIPEDIA(2u),
    AMO(3u),
    YELP(5u),
    MDN(6u),
    WEATHER(7u),
    DYNAMIC(9u);

    


    companion object
}


/**
 * @suppress
 */
public object FfiConverterTypeSuggestionProvider: FfiConverterRustBuffer<SuggestionProvider> {
    override fun read(buf: ByteBuffer) = try {
        SuggestionProvider.values()[buf.getInt() - 1]
    } catch (e: IndexOutOfBoundsException) {
        throw RuntimeException("invalid enum value, something is very wrong!!", e)
    }

    override fun allocationSize(value: SuggestionProvider) = 4UL

    override fun write(value: SuggestionProvider, buf: ByteBuffer) {
        buf.putInt(value.ordinal + 1)
    }
}





/**
 * Subject type for Yelp suggestion.
 */

enum class YelpSubjectType(val value: kotlin.UByte) {
    
    SERVICE(0u),
    BUSINESS(1u);

    


    companion object
}


/**
 * @suppress
 */
public object FfiConverterTypeYelpSubjectType: FfiConverterRustBuffer<YelpSubjectType> {
    override fun read(buf: ByteBuffer) = try {
        YelpSubjectType.values()[buf.getInt() - 1]
    } catch (e: IndexOutOfBoundsException) {
        throw RuntimeException("invalid enum value, something is very wrong!!", e)
    }

    override fun allocationSize(value: YelpSubjectType) = 4UL

    override fun write(value: YelpSubjectType, buf: ByteBuffer) {
        buf.putInt(value.ordinal + 1)
    }
}






/**
 * @suppress
 */
public object FfiConverterOptionalInt: FfiConverterRustBuffer<kotlin.Int?> {
    override fun read(buf: ByteBuffer): kotlin.Int? {
        if (buf.get().toInt() == 0) {
            return null
        }
        return FfiConverterInt.read(buf)
    }

    override fun allocationSize(value: kotlin.Int?): ULong {
        if (value == null) {
            return 1UL
        } else {
            return 1UL + FfiConverterInt.allocationSize(value)
        }
    }

    override fun write(value: kotlin.Int?, buf: ByteBuffer) {
        if (value == null) {
            buf.put(0)
        } else {
            buf.put(1)
            FfiConverterInt.write(value, buf)
        }
    }
}




/**
 * @suppress
 */
public object FfiConverterOptionalString: FfiConverterRustBuffer<kotlin.String?> {
    override fun read(buf: ByteBuffer): kotlin.String? {
        if (buf.get().toInt() == 0) {
            return null
        }
        return FfiConverterString.read(buf)
    }

    override fun allocationSize(value: kotlin.String?): ULong {
        if (value == null) {
            return 1UL
        } else {
            return 1UL + FfiConverterString.allocationSize(value)
        }
    }

    override fun write(value: kotlin.String?, buf: ByteBuffer) {
        if (value == null) {
            buf.put(0)
        } else {
            buf.put(1)
            FfiConverterString.write(value, buf)
        }
    }
}




/**
 * @suppress
 */
public object FfiConverterOptionalByteArray: FfiConverterRustBuffer<kotlin.ByteArray?> {
    override fun read(buf: ByteBuffer): kotlin.ByteArray? {
        if (buf.get().toInt() == 0) {
            return null
        }
        return FfiConverterByteArray.read(buf)
    }

    override fun allocationSize(value: kotlin.ByteArray?): ULong {
        if (value == null) {
            return 1UL
        } else {
            return 1UL + FfiConverterByteArray.allocationSize(value)
        }
    }

    override fun write(value: kotlin.ByteArray?, buf: ByteBuffer) {
        if (value == null) {
            buf.put(0)
        } else {
            buf.put(1)
            FfiConverterByteArray.write(value, buf)
        }
    }
}




/**
 * @suppress
 */
public object FfiConverterOptionalTypeAlternateNames: FfiConverterRustBuffer<AlternateNames?> {
    override fun read(buf: ByteBuffer): AlternateNames? {
        if (buf.get().toInt() == 0) {
            return null
        }
        return FfiConverterTypeAlternateNames.read(buf)
    }

    override fun allocationSize(value: AlternateNames?): ULong {
        if (value == null) {
            return 1UL
        } else {
            return 1UL + FfiConverterTypeAlternateNames.allocationSize(value)
        }
    }

    override fun write(value: AlternateNames?, buf: ByteBuffer) {
        if (value == null) {
            buf.put(0)
        } else {
            buf.put(1)
            FfiConverterTypeAlternateNames.write(value, buf)
        }
    }
}




/**
 * @suppress
 */
public object FfiConverterOptionalTypeFtsMatchInfo: FfiConverterRustBuffer<FtsMatchInfo?> {
    override fun read(buf: ByteBuffer): FtsMatchInfo? {
        if (buf.get().toInt() == 0) {
            return null
        }
        return FfiConverterTypeFtsMatchInfo.read(buf)
    }

    override fun allocationSize(value: FtsMatchInfo?): ULong {
        if (value == null) {
            return 1UL
        } else {
            return 1UL + FfiConverterTypeFtsMatchInfo.allocationSize(value)
        }
    }

    override fun write(value: FtsMatchInfo?, buf: ByteBuffer) {
        if (value == null) {
            buf.put(0)
        } else {
            buf.put(1)
            FfiConverterTypeFtsMatchInfo.write(value, buf)
        }
    }
}




/**
 * @suppress
 */
public object FfiConverterOptionalTypeGeoname: FfiConverterRustBuffer<Geoname?> {
    override fun read(buf: ByteBuffer): Geoname? {
        if (buf.get().toInt() == 0) {
            return null
        }
        return FfiConverterTypeGeoname.read(buf)
    }

    override fun allocationSize(value: Geoname?): ULong {
        if (value == null) {
            return 1UL
        } else {
            return 1UL + FfiConverterTypeGeoname.allocationSize(value)
        }
    }

    override fun write(value: Geoname?, buf: ByteBuffer) {
        if (value == null) {
            buf.put(0)
        } else {
            buf.put(1)
            FfiConverterTypeGeoname.write(value, buf)
        }
    }
}




/**
 * @suppress
 */
public object FfiConverterOptionalTypeSuggestionProviderConstraints: FfiConverterRustBuffer<SuggestionProviderConstraints?> {
    override fun read(buf: ByteBuffer): SuggestionProviderConstraints? {
        if (buf.get().toInt() == 0) {
            return null
        }
        return FfiConverterTypeSuggestionProviderConstraints.read(buf)
    }

    override fun allocationSize(value: SuggestionProviderConstraints?): ULong {
        if (value == null) {
            return 1UL
        } else {
            return 1UL + FfiConverterTypeSuggestionProviderConstraints.allocationSize(value)
        }
    }

    override fun write(value: SuggestionProviderConstraints?, buf: ByteBuffer) {
        if (value == null) {
            buf.put(0)
        } else {
            buf.put(1)
            FfiConverterTypeSuggestionProviderConstraints.write(value, buf)
        }
    }
}




/**
 * @suppress
 */
public object FfiConverterOptionalTypeAmpMatchingStrategy: FfiConverterRustBuffer<AmpMatchingStrategy?> {
    override fun read(buf: ByteBuffer): AmpMatchingStrategy? {
        if (buf.get().toInt() == 0) {
            return null
        }
        return FfiConverterTypeAmpMatchingStrategy.read(buf)
    }

    override fun allocationSize(value: AmpMatchingStrategy?): ULong {
        if (value == null) {
            return 1UL
        } else {
            return 1UL + FfiConverterTypeAmpMatchingStrategy.allocationSize(value)
        }
    }

    override fun write(value: AmpMatchingStrategy?, buf: ByteBuffer) {
        if (value == null) {
            buf.put(0)
        } else {
            buf.put(1)
            FfiConverterTypeAmpMatchingStrategy.write(value, buf)
        }
    }
}




/**
 * @suppress
 */
public object FfiConverterOptionalTypeInterruptKind: FfiConverterRustBuffer<InterruptKind?> {
    override fun read(buf: ByteBuffer): InterruptKind? {
        if (buf.get().toInt() == 0) {
            return null
        }
        return FfiConverterTypeInterruptKind.read(buf)
    }

    override fun allocationSize(value: InterruptKind?): ULong {
        if (value == null) {
            return 1UL
        } else {
            return 1UL + FfiConverterTypeInterruptKind.allocationSize(value)
        }
    }

    override fun write(value: InterruptKind?, buf: ByteBuffer) {
        if (value == null) {
            buf.put(0)
        } else {
            buf.put(1)
            FfiConverterTypeInterruptKind.write(value, buf)
        }
    }
}




/**
 * @suppress
 */
public object FfiConverterOptionalTypeSuggestProviderConfig: FfiConverterRustBuffer<SuggestProviderConfig?> {
    override fun read(buf: ByteBuffer): SuggestProviderConfig? {
        if (buf.get().toInt() == 0) {
            return null
        }
        return FfiConverterTypeSuggestProviderConfig.read(buf)
    }

    override fun allocationSize(value: SuggestProviderConfig?): ULong {
        if (value == null) {
            return 1UL
        } else {
            return 1UL + FfiConverterTypeSuggestProviderConfig.allocationSize(value)
        }
    }

    override fun write(value: SuggestProviderConfig?, buf: ByteBuffer) {
        if (value == null) {
            buf.put(0)
        } else {
            buf.put(1)
            FfiConverterTypeSuggestProviderConfig.write(value, buf)
        }
    }
}




/**
 * @suppress
 */
public object FfiConverterOptionalSequenceString: FfiConverterRustBuffer<List<kotlin.String>?> {
    override fun read(buf: ByteBuffer): List<kotlin.String>? {
        if (buf.get().toInt() == 0) {
            return null
        }
        return FfiConverterSequenceString.read(buf)
    }

    override fun allocationSize(value: List<kotlin.String>?): ULong {
        if (value == null) {
            return 1UL
        } else {
            return 1UL + FfiConverterSequenceString.allocationSize(value)
        }
    }

    override fun write(value: List<kotlin.String>?, buf: ByteBuffer) {
        if (value == null) {
            buf.put(0)
        } else {
            buf.put(1)
            FfiConverterSequenceString.write(value, buf)
        }
    }
}




/**
 * @suppress
 */
public object FfiConverterOptionalSequenceTypeGeoname: FfiConverterRustBuffer<List<Geoname>?> {
    override fun read(buf: ByteBuffer): List<Geoname>? {
        if (buf.get().toInt() == 0) {
            return null
        }
        return FfiConverterSequenceTypeGeoname.read(buf)
    }

    override fun allocationSize(value: List<Geoname>?): ULong {
        if (value == null) {
            return 1UL
        } else {
            return 1UL + FfiConverterSequenceTypeGeoname.allocationSize(value)
        }
    }

    override fun write(value: List<Geoname>?, buf: ByteBuffer) {
        if (value == null) {
            buf.put(0)
        } else {
            buf.put(1)
            FfiConverterSequenceTypeGeoname.write(value, buf)
        }
    }
}




/**
 * @suppress
 */
public object FfiConverterOptionalSequenceTypeSuggestionProvider: FfiConverterRustBuffer<List<SuggestionProvider>?> {
    override fun read(buf: ByteBuffer): List<SuggestionProvider>? {
        if (buf.get().toInt() == 0) {
            return null
        }
        return FfiConverterSequenceTypeSuggestionProvider.read(buf)
    }

    override fun allocationSize(value: List<SuggestionProvider>?): ULong {
        if (value == null) {
            return 1UL
        } else {
            return 1UL + FfiConverterSequenceTypeSuggestionProvider.allocationSize(value)
        }
    }

    override fun write(value: List<SuggestionProvider>?, buf: ByteBuffer) {
        if (value == null) {
            buf.put(0)
        } else {
            buf.put(1)
            FfiConverterSequenceTypeSuggestionProvider.write(value, buf)
        }
    }
}




/**
 * @suppress
 */
public object FfiConverterOptionalTypeJsonValue: FfiConverterRustBuffer<JsonValue?> {
    override fun read(buf: ByteBuffer): JsonValue? {
        if (buf.get().toInt() == 0) {
            return null
        }
        return FfiConverterTypeJsonValue.read(buf)
    }

    override fun allocationSize(value: JsonValue?): ULong {
        if (value == null) {
            return 1UL
        } else {
            return 1UL + FfiConverterTypeJsonValue.allocationSize(value)
        }
    }

    override fun write(value: JsonValue?, buf: ByteBuffer) {
        if (value == null) {
            buf.put(0)
        } else {
            buf.put(1)
            FfiConverterTypeJsonValue.write(value, buf)
        }
    }
}




/**
 * @suppress
 */
public object FfiConverterSequenceInt: FfiConverterRustBuffer<List<kotlin.Int>> {
    override fun read(buf: ByteBuffer): List<kotlin.Int> {
        val len = buf.getInt()
        return List<kotlin.Int>(len) {
            FfiConverterInt.read(buf)
        }
    }

    override fun allocationSize(value: List<kotlin.Int>): ULong {
        val sizeForLength = 4UL
        val sizeForItems = value.map { FfiConverterInt.allocationSize(it) }.sum()
        return sizeForLength + sizeForItems
    }

    override fun write(value: List<kotlin.Int>, buf: ByteBuffer) {
        buf.putInt(value.size)
        value.iterator().forEach {
            FfiConverterInt.write(it, buf)
        }
    }
}




/**
 * @suppress
 */
public object FfiConverterSequenceString: FfiConverterRustBuffer<List<kotlin.String>> {
    override fun read(buf: ByteBuffer): List<kotlin.String> {
        val len = buf.getInt()
        return List<kotlin.String>(len) {
            FfiConverterString.read(buf)
        }
    }

    override fun allocationSize(value: List<kotlin.String>): ULong {
        val sizeForLength = 4UL
        val sizeForItems = value.map { FfiConverterString.allocationSize(it) }.sum()
        return sizeForLength + sizeForItems
    }

    override fun write(value: List<kotlin.String>, buf: ByteBuffer) {
        buf.putInt(value.size)
        value.iterator().forEach {
            FfiConverterString.write(it, buf)
        }
    }
}




/**
 * @suppress
 */
public object FfiConverterSequenceTypeGeoname: FfiConverterRustBuffer<List<Geoname>> {
    override fun read(buf: ByteBuffer): List<Geoname> {
        val len = buf.getInt()
        return List<Geoname>(len) {
            FfiConverterTypeGeoname.read(buf)
        }
    }

    override fun allocationSize(value: List<Geoname>): ULong {
        val sizeForLength = 4UL
        val sizeForItems = value.map { FfiConverterTypeGeoname.allocationSize(it) }.sum()
        return sizeForLength + sizeForItems
    }

    override fun write(value: List<Geoname>, buf: ByteBuffer) {
        buf.putInt(value.size)
        value.iterator().forEach {
            FfiConverterTypeGeoname.write(it, buf)
        }
    }
}




/**
 * @suppress
 */
public object FfiConverterSequenceTypeGeonameMatch: FfiConverterRustBuffer<List<GeonameMatch>> {
    override fun read(buf: ByteBuffer): List<GeonameMatch> {
        val len = buf.getInt()
        return List<GeonameMatch>(len) {
            FfiConverterTypeGeonameMatch.read(buf)
        }
    }

    override fun allocationSize(value: List<GeonameMatch>): ULong {
        val sizeForLength = 4UL
        val sizeForItems = value.map { FfiConverterTypeGeonameMatch.allocationSize(it) }.sum()
        return sizeForLength + sizeForItems
    }

    override fun write(value: List<GeonameMatch>, buf: ByteBuffer) {
        buf.putInt(value.size)
        value.iterator().forEach {
            FfiConverterTypeGeonameMatch.write(it, buf)
        }
    }
}




/**
 * @suppress
 */
public object FfiConverterSequenceTypeLabeledTimingSample: FfiConverterRustBuffer<List<LabeledTimingSample>> {
    override fun read(buf: ByteBuffer): List<LabeledTimingSample> {
        val len = buf.getInt()
        return List<LabeledTimingSample>(len) {
            FfiConverterTypeLabeledTimingSample.read(buf)
        }
    }

    override fun allocationSize(value: List<LabeledTimingSample>): ULong {
        val sizeForLength = 4UL
        val sizeForItems = value.map { FfiConverterTypeLabeledTimingSample.allocationSize(it) }.sum()
        return sizeForLength + sizeForItems
    }

    override fun write(value: List<LabeledTimingSample>, buf: ByteBuffer) {
        buf.putInt(value.size)
        value.iterator().forEach {
            FfiConverterTypeLabeledTimingSample.write(it, buf)
        }
    }
}




/**
 * @suppress
 */
public object FfiConverterSequenceTypeSuggestion: FfiConverterRustBuffer<List<Suggestion>> {
    override fun read(buf: ByteBuffer): List<Suggestion> {
        val len = buf.getInt()
        return List<Suggestion>(len) {
            FfiConverterTypeSuggestion.read(buf)
        }
    }

    override fun allocationSize(value: List<Suggestion>): ULong {
        val sizeForLength = 4UL
        val sizeForItems = value.map { FfiConverterTypeSuggestion.allocationSize(it) }.sum()
        return sizeForLength + sizeForItems
    }

    override fun write(value: List<Suggestion>, buf: ByteBuffer) {
        buf.putInt(value.size)
        value.iterator().forEach {
            FfiConverterTypeSuggestion.write(it, buf)
        }
    }
}




/**
 * @suppress
 */
public object FfiConverterSequenceTypeSuggestionProvider: FfiConverterRustBuffer<List<SuggestionProvider>> {
    override fun read(buf: ByteBuffer): List<SuggestionProvider> {
        val len = buf.getInt()
        return List<SuggestionProvider>(len) {
            FfiConverterTypeSuggestionProvider.read(buf)
        }
    }

    override fun allocationSize(value: List<SuggestionProvider>): ULong {
        val sizeForLength = 4UL
        val sizeForItems = value.map { FfiConverterTypeSuggestionProvider.allocationSize(it) }.sum()
        return sizeForLength + sizeForItems
    }

    override fun write(value: List<SuggestionProvider>, buf: ByteBuffer) {
        buf.putInt(value.size)
        value.iterator().forEach {
            FfiConverterTypeSuggestionProvider.write(it, buf)
        }
    }
}




/**
 * @suppress
 */
public object FfiConverterMapUByteString: FfiConverterRustBuffer<Map<kotlin.UByte, kotlin.String>> {
    override fun read(buf: ByteBuffer): Map<kotlin.UByte, kotlin.String> {
        val len = buf.getInt()
        return buildMap<kotlin.UByte, kotlin.String>(len) {
            repeat(len) {
                val k = FfiConverterUByte.read(buf)
                val v = FfiConverterString.read(buf)
                this[k] = v
            }
        }
    }

    override fun allocationSize(value: Map<kotlin.UByte, kotlin.String>): ULong {
        val spaceForMapSize = 4UL
        val spaceForChildren = value.map { (k, v) ->
            FfiConverterUByte.allocationSize(k) +
            FfiConverterString.allocationSize(v)
        }.sum()
        return spaceForMapSize + spaceForChildren
    }

    override fun write(value: Map<kotlin.UByte, kotlin.String>, buf: ByteBuffer) {
        buf.putInt(value.size)
        // The parens on `(k, v)` here ensure we're calling the right method,
        // which is important for compatibility with older android devices.
        // Ref https://blog.danlew.net/2017/03/16/kotlin-puzzler-whose-line-is-it-anyways/
        value.forEach { (k, v) ->
            FfiConverterUByte.write(k, buf)
            FfiConverterString.write(v, buf)
        }
    }
}




/**
 * @suppress
 */
public object FfiConverterMapUByteTypeAlternateNames: FfiConverterRustBuffer<Map<kotlin.UByte, AlternateNames>> {
    override fun read(buf: ByteBuffer): Map<kotlin.UByte, AlternateNames> {
        val len = buf.getInt()
        return buildMap<kotlin.UByte, AlternateNames>(len) {
            repeat(len) {
                val k = FfiConverterUByte.read(buf)
                val v = FfiConverterTypeAlternateNames.read(buf)
                this[k] = v
            }
        }
    }

    override fun allocationSize(value: Map<kotlin.UByte, AlternateNames>): ULong {
        val spaceForMapSize = 4UL
        val spaceForChildren = value.map { (k, v) ->
            FfiConverterUByte.allocationSize(k) +
            FfiConverterTypeAlternateNames.allocationSize(v)
        }.sum()
        return spaceForMapSize + spaceForChildren
    }

    override fun write(value: Map<kotlin.UByte, AlternateNames>, buf: ByteBuffer) {
        buf.putInt(value.size)
        // The parens on `(k, v)` here ensure we're calling the right method,
        // which is important for compatibility with older android devices.
        // Ref https://blog.danlew.net/2017/03/16/kotlin-puzzler-whose-line-is-it-anyways/
        value.forEach { (k, v) ->
            FfiConverterUByte.write(k, buf)
            FfiConverterTypeAlternateNames.write(v, buf)
        }
    }
}



/**
 * Typealias from the type name used in the UDL file to the builtin type.  This
 * is needed because the UDL type name is used in function/method signatures.
 * It's also what we have an external type that references a custom type.
 */
public typealias JsonValue = kotlin.String
public typealias FfiConverterTypeJsonValue = FfiConverterString




        /**
         * Determines whether a "raw" sponsored suggestion URL is equivalent to a
         * "cooked" URL. The two URLs are equivalent if they are identical except for
         * their replaced template parameters, which can be different.
         */ fun `rawSuggestionUrlMatches`(`rawUrl`: kotlin.String, `cookedUrl`: kotlin.String): kotlin.Boolean {
            return FfiConverterBoolean.lift(
    uniffiRustCall() { _status ->
    UniffiLib.uniffi_suggest_fn_func_raw_suggestion_url_matches(
    
        FfiConverterString.lower(`rawUrl`),FfiConverterString.lower(`cookedUrl`),_status)
}
    )
    }
    


