// 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 org.mozilla.experiments.nimbus.internal

// 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.FfiConverterTypeRemoteSettingsService
import mozilla.appservices.remotesettings.RemoteSettingsService
import org.json.JSONObject
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_nimbus_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_nimbus_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,)
}
internal interface UniffiCallbackInterfaceGeckoPrefHandlerMethod0 : com.sun.jna.Callback {
    fun callback(`uniffiHandle`: Long,`uniffiOutReturn`: RustBuffer,uniffiCallStatus: UniffiRustCallStatus,)
}
internal interface UniffiCallbackInterfaceGeckoPrefHandlerMethod1 : com.sun.jna.Callback {
    fun callback(`uniffiHandle`: Long,`originalGeckoPrefs`: RustBuffer.ByValue,`uniffiOutReturn`: Pointer,uniffiCallStatus: UniffiRustCallStatus,)
}
internal interface UniffiCallbackInterfaceGeckoPrefHandlerMethod2 : com.sun.jna.Callback {
    fun callback(`uniffiHandle`: Long,`newPrefsState`: RustBuffer.ByValue,`uniffiOutReturn`: Pointer,uniffiCallStatus: UniffiRustCallStatus,)
}
internal interface UniffiCallbackInterfaceMetricsHandlerMethod0 : com.sun.jna.Callback {
    fun callback(`uniffiHandle`: Long,`event`: RustBuffer.ByValue,`uniffiOutReturn`: Pointer,uniffiCallStatus: UniffiRustCallStatus,)
}
internal interface UniffiCallbackInterfaceMetricsHandlerMethod1 : com.sun.jna.Callback {
    fun callback(`uniffiHandle`: Long,`event`: RustBuffer.ByValue,`uniffiOutReturn`: Pointer,uniffiCallStatus: UniffiRustCallStatus,)
}
internal interface UniffiCallbackInterfaceMetricsHandlerMethod2 : com.sun.jna.Callback {
    fun callback(`uniffiHandle`: Long,`enrollmentStatusExtras`: RustBuffer.ByValue,`uniffiOutReturn`: Pointer,uniffiCallStatus: UniffiRustCallStatus,)
}
internal interface UniffiCallbackInterfaceMetricsHandlerMethod3 : com.sun.jna.Callback {
    fun callback(`uniffiHandle`: Long,`event`: RustBuffer.ByValue,`uniffiOutReturn`: Pointer,uniffiCallStatus: UniffiRustCallStatus,)
}
internal interface UniffiCallbackInterfaceMetricsHandlerMethod4 : com.sun.jna.Callback {
    fun callback(`uniffiHandle`: Long,`event`: RustBuffer.ByValue,`uniffiOutReturn`: Pointer,uniffiCallStatus: UniffiRustCallStatus,)
}
internal interface UniffiCallbackInterfaceMetricsHandlerMethod5 : com.sun.jna.Callback {
    fun callback(`uniffiHandle`: Long,`event`: RustBuffer.ByValue,`uniffiOutReturn`: Pointer,uniffiCallStatus: UniffiRustCallStatus,)
}
internal interface UniffiCallbackInterfaceMetricsHandlerMethod6 : com.sun.jna.Callback {
    fun callback(`uniffiHandle`: Long,`uniffiOutReturn`: Pointer,uniffiCallStatus: UniffiRustCallStatus,)
}
internal interface UniffiCallbackInterfaceRecordedContextMethod0 : com.sun.jna.Callback {
    fun callback(`uniffiHandle`: Long,`uniffiOutReturn`: RustBuffer,uniffiCallStatus: UniffiRustCallStatus,)
}
internal interface UniffiCallbackInterfaceRecordedContextMethod1 : com.sun.jna.Callback {
    fun callback(`uniffiHandle`: Long,`uniffiOutReturn`: Pointer,uniffiCallStatus: UniffiRustCallStatus,)
}
internal interface UniffiCallbackInterfaceRecordedContextMethod2 : com.sun.jna.Callback {
    fun callback(`uniffiHandle`: Long,`eventQueryValues`: RustBuffer.ByValue,`uniffiOutReturn`: Pointer,uniffiCallStatus: UniffiRustCallStatus,)
}
internal interface UniffiCallbackInterfaceRecordedContextMethod3 : com.sun.jna.Callback {
    fun callback(`uniffiHandle`: Long,`uniffiOutReturn`: RustBuffer,uniffiCallStatus: UniffiRustCallStatus,)
}
@Structure.FieldOrder("uniffiFree", "uniffiClone", "getPrefsWithState", "setGeckoPrefsOriginalValues", "setGeckoPrefsState")
internal open class UniffiVTableCallbackInterfaceGeckoPrefHandler(
    @JvmField internal var `uniffiFree`: UniffiCallbackInterfaceFree? = null,
    @JvmField internal var `uniffiClone`: UniffiCallbackInterfaceClone? = null,
    @JvmField internal var `getPrefsWithState`: UniffiCallbackInterfaceGeckoPrefHandlerMethod0? = null,
    @JvmField internal var `setGeckoPrefsOriginalValues`: UniffiCallbackInterfaceGeckoPrefHandlerMethod1? = null,
    @JvmField internal var `setGeckoPrefsState`: UniffiCallbackInterfaceGeckoPrefHandlerMethod2? = null,
) : Structure() {
    class UniffiByValue(
        `uniffiFree`: UniffiCallbackInterfaceFree? = null,
        `uniffiClone`: UniffiCallbackInterfaceClone? = null,
        `getPrefsWithState`: UniffiCallbackInterfaceGeckoPrefHandlerMethod0? = null,
        `setGeckoPrefsOriginalValues`: UniffiCallbackInterfaceGeckoPrefHandlerMethod1? = null,
        `setGeckoPrefsState`: UniffiCallbackInterfaceGeckoPrefHandlerMethod2? = null,
    ): UniffiVTableCallbackInterfaceGeckoPrefHandler(`uniffiFree`,`uniffiClone`,`getPrefsWithState`,`setGeckoPrefsOriginalValues`,`setGeckoPrefsState`,), Structure.ByValue

   internal fun uniffiSetValue(other: UniffiVTableCallbackInterfaceGeckoPrefHandler) {
        `uniffiFree` = other.`uniffiFree`
        `uniffiClone` = other.`uniffiClone`
        `getPrefsWithState` = other.`getPrefsWithState`
        `setGeckoPrefsOriginalValues` = other.`setGeckoPrefsOriginalValues`
        `setGeckoPrefsState` = other.`setGeckoPrefsState`
    }

}
@Structure.FieldOrder("uniffiFree", "uniffiClone", "recordDatabaseLoad", "recordDatabaseMigration", "recordEnrollmentStatuses", "recordFeatureActivation", "recordFeatureExposure", "recordMalformedFeatureConfig", "submitTargetingContext")
internal open class UniffiVTableCallbackInterfaceMetricsHandler(
    @JvmField internal var `uniffiFree`: UniffiCallbackInterfaceFree? = null,
    @JvmField internal var `uniffiClone`: UniffiCallbackInterfaceClone? = null,
    @JvmField internal var `recordDatabaseLoad`: UniffiCallbackInterfaceMetricsHandlerMethod0? = null,
    @JvmField internal var `recordDatabaseMigration`: UniffiCallbackInterfaceMetricsHandlerMethod1? = null,
    @JvmField internal var `recordEnrollmentStatuses`: UniffiCallbackInterfaceMetricsHandlerMethod2? = null,
    @JvmField internal var `recordFeatureActivation`: UniffiCallbackInterfaceMetricsHandlerMethod3? = null,
    @JvmField internal var `recordFeatureExposure`: UniffiCallbackInterfaceMetricsHandlerMethod4? = null,
    @JvmField internal var `recordMalformedFeatureConfig`: UniffiCallbackInterfaceMetricsHandlerMethod5? = null,
    @JvmField internal var `submitTargetingContext`: UniffiCallbackInterfaceMetricsHandlerMethod6? = null,
) : Structure() {
    class UniffiByValue(
        `uniffiFree`: UniffiCallbackInterfaceFree? = null,
        `uniffiClone`: UniffiCallbackInterfaceClone? = null,
        `recordDatabaseLoad`: UniffiCallbackInterfaceMetricsHandlerMethod0? = null,
        `recordDatabaseMigration`: UniffiCallbackInterfaceMetricsHandlerMethod1? = null,
        `recordEnrollmentStatuses`: UniffiCallbackInterfaceMetricsHandlerMethod2? = null,
        `recordFeatureActivation`: UniffiCallbackInterfaceMetricsHandlerMethod3? = null,
        `recordFeatureExposure`: UniffiCallbackInterfaceMetricsHandlerMethod4? = null,
        `recordMalformedFeatureConfig`: UniffiCallbackInterfaceMetricsHandlerMethod5? = null,
        `submitTargetingContext`: UniffiCallbackInterfaceMetricsHandlerMethod6? = null,
    ): UniffiVTableCallbackInterfaceMetricsHandler(`uniffiFree`,`uniffiClone`,`recordDatabaseLoad`,`recordDatabaseMigration`,`recordEnrollmentStatuses`,`recordFeatureActivation`,`recordFeatureExposure`,`recordMalformedFeatureConfig`,`submitTargetingContext`,), Structure.ByValue

   internal fun uniffiSetValue(other: UniffiVTableCallbackInterfaceMetricsHandler) {
        `uniffiFree` = other.`uniffiFree`
        `uniffiClone` = other.`uniffiClone`
        `recordDatabaseLoad` = other.`recordDatabaseLoad`
        `recordDatabaseMigration` = other.`recordDatabaseMigration`
        `recordEnrollmentStatuses` = other.`recordEnrollmentStatuses`
        `recordFeatureActivation` = other.`recordFeatureActivation`
        `recordFeatureExposure` = other.`recordFeatureExposure`
        `recordMalformedFeatureConfig` = other.`recordMalformedFeatureConfig`
        `submitTargetingContext` = other.`submitTargetingContext`
    }

}
@Structure.FieldOrder("uniffiFree", "uniffiClone", "getEventQueries", "record", "setEventQueryValues", "toJson")
internal open class UniffiVTableCallbackInterfaceRecordedContext(
    @JvmField internal var `uniffiFree`: UniffiCallbackInterfaceFree? = null,
    @JvmField internal var `uniffiClone`: UniffiCallbackInterfaceClone? = null,
    @JvmField internal var `getEventQueries`: UniffiCallbackInterfaceRecordedContextMethod0? = null,
    @JvmField internal var `record`: UniffiCallbackInterfaceRecordedContextMethod1? = null,
    @JvmField internal var `setEventQueryValues`: UniffiCallbackInterfaceRecordedContextMethod2? = null,
    @JvmField internal var `toJson`: UniffiCallbackInterfaceRecordedContextMethod3? = null,
) : Structure() {
    class UniffiByValue(
        `uniffiFree`: UniffiCallbackInterfaceFree? = null,
        `uniffiClone`: UniffiCallbackInterfaceClone? = null,
        `getEventQueries`: UniffiCallbackInterfaceRecordedContextMethod0? = null,
        `record`: UniffiCallbackInterfaceRecordedContextMethod1? = null,
        `setEventQueryValues`: UniffiCallbackInterfaceRecordedContextMethod2? = null,
        `toJson`: UniffiCallbackInterfaceRecordedContextMethod3? = null,
    ): UniffiVTableCallbackInterfaceRecordedContext(`uniffiFree`,`uniffiClone`,`getEventQueries`,`record`,`setEventQueryValues`,`toJson`,), Structure.ByValue

   internal fun uniffiSetValue(other: UniffiVTableCallbackInterfaceRecordedContext) {
        `uniffiFree` = other.`uniffiFree`
        `uniffiClone` = other.`uniffiClone`
        `getEventQueries` = other.`getEventQueries`
        `record` = other.`record`
        `setEventQueryValues` = other.`setEventQueryValues`
        `toJson` = other.`toJson`
    }

}

// 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 = "nimbus"))
        uniffiCheckContractApiVersion(this)
    }
    external fun uniffi_nimbus_checksum_func_get_calculated_attributes(
    ): Short
    external fun uniffi_nimbus_checksum_func_validate_event_queries(
    ): Short
    external fun uniffi_nimbus_checksum_method_geckoprefhandler_get_prefs_with_state(
    ): Short
    external fun uniffi_nimbus_checksum_method_geckoprefhandler_set_gecko_prefs_original_values(
    ): Short
    external fun uniffi_nimbus_checksum_method_geckoprefhandler_set_gecko_prefs_state(
    ): Short
    external fun uniffi_nimbus_checksum_method_metricshandler_record_database_load(
    ): Short
    external fun uniffi_nimbus_checksum_method_metricshandler_record_database_migration(
    ): Short
    external fun uniffi_nimbus_checksum_method_metricshandler_record_enrollment_statuses(
    ): Short
    external fun uniffi_nimbus_checksum_method_metricshandler_record_feature_activation(
    ): Short
    external fun uniffi_nimbus_checksum_method_metricshandler_record_feature_exposure(
    ): Short
    external fun uniffi_nimbus_checksum_method_metricshandler_record_malformed_feature_config(
    ): Short
    external fun uniffi_nimbus_checksum_method_metricshandler_submit_targeting_context(
    ): Short
    external fun uniffi_nimbus_checksum_method_nimbusclient_advance_event_time(
    ): Short
    external fun uniffi_nimbus_checksum_method_nimbusclient_apply_pending_experiments(
    ): Short
    external fun uniffi_nimbus_checksum_method_nimbusclient_clear_events(
    ): Short
    external fun uniffi_nimbus_checksum_method_nimbusclient_create_string_helper(
    ): Short
    external fun uniffi_nimbus_checksum_method_nimbusclient_create_targeting_helper(
    ): Short
    external fun uniffi_nimbus_checksum_method_nimbusclient_dump_state_to_log(
    ): Short
    external fun uniffi_nimbus_checksum_method_nimbusclient_enroll_in_firefox_lab(
    ): Short
    external fun uniffi_nimbus_checksum_method_nimbusclient_fetch_experiments(
    ): Short
    external fun uniffi_nimbus_checksum_method_nimbusclient_get_active_experiments(
    ): Short
    external fun uniffi_nimbus_checksum_method_nimbusclient_get_available_experiments(
    ): Short
    external fun uniffi_nimbus_checksum_method_nimbusclient_get_available_firefox_labs(
    ): Short
    external fun uniffi_nimbus_checksum_method_nimbusclient_get_experiment_branch(
    ): Short
    external fun uniffi_nimbus_checksum_method_nimbusclient_get_experiment_branches(
    ): Short
    external fun uniffi_nimbus_checksum_method_nimbusclient_get_experiment_participation(
    ): Short
    external fun uniffi_nimbus_checksum_method_nimbusclient_get_feature_config_variables(
    ): Short
    external fun uniffi_nimbus_checksum_method_nimbusclient_get_previous_gecko_pref_states(
    ): Short
    external fun uniffi_nimbus_checksum_method_nimbusclient_get_rollout_participation(
    ): Short
    external fun uniffi_nimbus_checksum_method_nimbusclient_initialize(
    ): Short
    external fun uniffi_nimbus_checksum_method_nimbusclient_is_fetch_enabled(
    ): Short
    external fun uniffi_nimbus_checksum_method_nimbusclient_opt_in_with_branch(
    ): Short
    external fun uniffi_nimbus_checksum_method_nimbusclient_opt_out(
    ): Short
    external fun uniffi_nimbus_checksum_method_nimbusclient_record_event(
    ): Short
    external fun uniffi_nimbus_checksum_method_nimbusclient_record_feature_exposure(
    ): Short
    external fun uniffi_nimbus_checksum_method_nimbusclient_record_malformed_feature_config(
    ): Short
    external fun uniffi_nimbus_checksum_method_nimbusclient_record_past_event(
    ): Short
    external fun uniffi_nimbus_checksum_method_nimbusclient_register_previous_gecko_pref_states(
    ): Short
    external fun uniffi_nimbus_checksum_method_nimbusclient_reset_enrollments(
    ): Short
    external fun uniffi_nimbus_checksum_method_nimbusclient_reset_telemetry_identifiers(
    ): Short
    external fun uniffi_nimbus_checksum_method_nimbusclient_set_experiment_participation(
    ): Short
    external fun uniffi_nimbus_checksum_method_nimbusclient_set_experiments_locally(
    ): Short
    external fun uniffi_nimbus_checksum_method_nimbusclient_set_fetch_enabled(
    ): Short
    external fun uniffi_nimbus_checksum_method_nimbusclient_set_rollout_participation(
    ): Short
    external fun uniffi_nimbus_checksum_method_nimbusclient_unenroll_for_gecko_pref(
    ): Short
    external fun uniffi_nimbus_checksum_method_nimbusclient_unenroll_from_all_firefox_labs(
    ): Short
    external fun uniffi_nimbus_checksum_method_nimbusclient_unenroll_from_firefox_lab(
    ): Short
    external fun uniffi_nimbus_checksum_method_nimbusstringhelper_get_uuid(
    ): Short
    external fun uniffi_nimbus_checksum_method_nimbusstringhelper_string_format(
    ): Short
    external fun uniffi_nimbus_checksum_method_nimbustargetinghelper_eval_jexl(
    ): Short
    external fun uniffi_nimbus_checksum_method_nimbustargetinghelper_eval_jexl_debug(
    ): Short
    external fun uniffi_nimbus_checksum_method_recordedcontext_get_event_queries(
    ): Short
    external fun uniffi_nimbus_checksum_method_recordedcontext_record(
    ): Short
    external fun uniffi_nimbus_checksum_method_recordedcontext_set_event_query_values(
    ): Short
    external fun uniffi_nimbus_checksum_method_recordedcontext_to_json(
    ): Short
    external fun uniffi_nimbus_checksum_constructor_nimbusclient_new(
    ): Short
    external fun ffi_nimbus_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 = "nimbus"))
        uniffiCallbackInterfaceGeckoPrefHandler.register(this)
        uniffiCallbackInterfaceMetricsHandler.register(this)
        uniffiCallbackInterfaceRecordedContext.register(this)
        mozilla.appservices.remotesettings.uniffiEnsureInitialized()
        
    }
    external fun uniffi_nimbus_fn_clone_geckoprefhandler(`handle`: Long,uniffi_out_err: UniffiRustCallStatus, 
): Long
external fun uniffi_nimbus_fn_free_geckoprefhandler(`handle`: Long,uniffi_out_err: UniffiRustCallStatus, 
): Unit
external fun uniffi_nimbus_fn_init_callback_vtable_geckoprefhandler(`vtable`: UniffiVTableCallbackInterfaceGeckoPrefHandler,
): Unit
external fun uniffi_nimbus_fn_method_geckoprefhandler_get_prefs_with_state(`ptr`: Long,uniffi_out_err: UniffiRustCallStatus, 
): RustBuffer.ByValue
external fun uniffi_nimbus_fn_method_geckoprefhandler_set_gecko_prefs_original_values(`ptr`: Long,`originalGeckoPrefs`: RustBuffer.ByValue,uniffi_out_err: UniffiRustCallStatus, 
): Unit
external fun uniffi_nimbus_fn_method_geckoprefhandler_set_gecko_prefs_state(`ptr`: Long,`newPrefsState`: RustBuffer.ByValue,uniffi_out_err: UniffiRustCallStatus, 
): Unit
external fun uniffi_nimbus_fn_clone_metricshandler(`handle`: Long,uniffi_out_err: UniffiRustCallStatus, 
): Long
external fun uniffi_nimbus_fn_free_metricshandler(`handle`: Long,uniffi_out_err: UniffiRustCallStatus, 
): Unit
external fun uniffi_nimbus_fn_init_callback_vtable_metricshandler(`vtable`: UniffiVTableCallbackInterfaceMetricsHandler,
): Unit
external fun uniffi_nimbus_fn_method_metricshandler_record_database_load(`ptr`: Long,`event`: RustBuffer.ByValue,uniffi_out_err: UniffiRustCallStatus, 
): Unit
external fun uniffi_nimbus_fn_method_metricshandler_record_database_migration(`ptr`: Long,`event`: RustBuffer.ByValue,uniffi_out_err: UniffiRustCallStatus, 
): Unit
external fun uniffi_nimbus_fn_method_metricshandler_record_enrollment_statuses(`ptr`: Long,`enrollmentStatusExtras`: RustBuffer.ByValue,uniffi_out_err: UniffiRustCallStatus, 
): Unit
external fun uniffi_nimbus_fn_method_metricshandler_record_feature_activation(`ptr`: Long,`event`: RustBuffer.ByValue,uniffi_out_err: UniffiRustCallStatus, 
): Unit
external fun uniffi_nimbus_fn_method_metricshandler_record_feature_exposure(`ptr`: Long,`event`: RustBuffer.ByValue,uniffi_out_err: UniffiRustCallStatus, 
): Unit
external fun uniffi_nimbus_fn_method_metricshandler_record_malformed_feature_config(`ptr`: Long,`event`: RustBuffer.ByValue,uniffi_out_err: UniffiRustCallStatus, 
): Unit
external fun uniffi_nimbus_fn_method_metricshandler_submit_targeting_context(`ptr`: Long,uniffi_out_err: UniffiRustCallStatus, 
): Unit
external fun uniffi_nimbus_fn_clone_nimbusclient(`handle`: Long,uniffi_out_err: UniffiRustCallStatus, 
): Long
external fun uniffi_nimbus_fn_free_nimbusclient(`handle`: Long,uniffi_out_err: UniffiRustCallStatus, 
): Unit
external fun uniffi_nimbus_fn_constructor_nimbusclient_new(`appCtx`: RustBuffer.ByValue,`recordedContext`: RustBuffer.ByValue,`coenrollingFeatureIds`: RustBuffer.ByValue,`dbpath`: RustBuffer.ByValue,`metricsHandler`: Long,`geckoPrefHandler`: RustBuffer.ByValue,`remoteSettingsInfo`: RustBuffer.ByValue,uniffi_out_err: UniffiRustCallStatus, 
): Long
external fun uniffi_nimbus_fn_method_nimbusclient_advance_event_time(`ptr`: Long,`bySeconds`: Long,uniffi_out_err: UniffiRustCallStatus, 
): Unit
external fun uniffi_nimbus_fn_method_nimbusclient_apply_pending_experiments(`ptr`: Long,uniffi_out_err: UniffiRustCallStatus, 
): RustBuffer.ByValue
external fun uniffi_nimbus_fn_method_nimbusclient_clear_events(`ptr`: Long,uniffi_out_err: UniffiRustCallStatus, 
): Unit
external fun uniffi_nimbus_fn_method_nimbusclient_create_string_helper(`ptr`: Long,`additionalContext`: RustBuffer.ByValue,uniffi_out_err: UniffiRustCallStatus, 
): Long
external fun uniffi_nimbus_fn_method_nimbusclient_create_targeting_helper(`ptr`: Long,`additionalContext`: RustBuffer.ByValue,uniffi_out_err: UniffiRustCallStatus, 
): Long
external fun uniffi_nimbus_fn_method_nimbusclient_dump_state_to_log(`ptr`: Long,uniffi_out_err: UniffiRustCallStatus, 
): Unit
external fun uniffi_nimbus_fn_method_nimbusclient_enroll_in_firefox_lab(`ptr`: Long,`slug`: RustBuffer.ByValue,uniffi_out_err: UniffiRustCallStatus, 
): RustBuffer.ByValue
external fun uniffi_nimbus_fn_method_nimbusclient_fetch_experiments(`ptr`: Long,uniffi_out_err: UniffiRustCallStatus, 
): Unit
external fun uniffi_nimbus_fn_method_nimbusclient_get_active_experiments(`ptr`: Long,uniffi_out_err: UniffiRustCallStatus, 
): RustBuffer.ByValue
external fun uniffi_nimbus_fn_method_nimbusclient_get_available_experiments(`ptr`: Long,uniffi_out_err: UniffiRustCallStatus, 
): RustBuffer.ByValue
external fun uniffi_nimbus_fn_method_nimbusclient_get_available_firefox_labs(`ptr`: Long,uniffi_out_err: UniffiRustCallStatus, 
): RustBuffer.ByValue
external fun uniffi_nimbus_fn_method_nimbusclient_get_experiment_branch(`ptr`: Long,`id`: RustBuffer.ByValue,uniffi_out_err: UniffiRustCallStatus, 
): RustBuffer.ByValue
external fun uniffi_nimbus_fn_method_nimbusclient_get_experiment_branches(`ptr`: Long,`experimentSlug`: RustBuffer.ByValue,uniffi_out_err: UniffiRustCallStatus, 
): RustBuffer.ByValue
external fun uniffi_nimbus_fn_method_nimbusclient_get_experiment_participation(`ptr`: Long,uniffi_out_err: UniffiRustCallStatus, 
): Byte
external fun uniffi_nimbus_fn_method_nimbusclient_get_feature_config_variables(`ptr`: Long,`featureId`: RustBuffer.ByValue,uniffi_out_err: UniffiRustCallStatus, 
): RustBuffer.ByValue
external fun uniffi_nimbus_fn_method_nimbusclient_get_previous_gecko_pref_states(`ptr`: Long,`experimentSlug`: RustBuffer.ByValue,uniffi_out_err: UniffiRustCallStatus, 
): RustBuffer.ByValue
external fun uniffi_nimbus_fn_method_nimbusclient_get_rollout_participation(`ptr`: Long,uniffi_out_err: UniffiRustCallStatus, 
): Byte
external fun uniffi_nimbus_fn_method_nimbusclient_initialize(`ptr`: Long,uniffi_out_err: UniffiRustCallStatus, 
): Unit
external fun uniffi_nimbus_fn_method_nimbusclient_is_fetch_enabled(`ptr`: Long,uniffi_out_err: UniffiRustCallStatus, 
): Byte
external fun uniffi_nimbus_fn_method_nimbusclient_opt_in_with_branch(`ptr`: Long,`experimentSlug`: RustBuffer.ByValue,`branch`: RustBuffer.ByValue,uniffi_out_err: UniffiRustCallStatus, 
): RustBuffer.ByValue
external fun uniffi_nimbus_fn_method_nimbusclient_opt_out(`ptr`: Long,`experimentSlug`: RustBuffer.ByValue,uniffi_out_err: UniffiRustCallStatus, 
): RustBuffer.ByValue
external fun uniffi_nimbus_fn_method_nimbusclient_record_event(`ptr`: Long,`eventId`: RustBuffer.ByValue,`count`: Long,uniffi_out_err: UniffiRustCallStatus, 
): Unit
external fun uniffi_nimbus_fn_method_nimbusclient_record_feature_exposure(`ptr`: Long,`featureId`: RustBuffer.ByValue,`slug`: RustBuffer.ByValue,uniffi_out_err: UniffiRustCallStatus, 
): Unit
external fun uniffi_nimbus_fn_method_nimbusclient_record_malformed_feature_config(`ptr`: Long,`featureId`: RustBuffer.ByValue,`partId`: RustBuffer.ByValue,uniffi_out_err: UniffiRustCallStatus, 
): Unit
external fun uniffi_nimbus_fn_method_nimbusclient_record_past_event(`ptr`: Long,`eventId`: RustBuffer.ByValue,`secondsAgo`: Long,`count`: Long,uniffi_out_err: UniffiRustCallStatus, 
): Unit
external fun uniffi_nimbus_fn_method_nimbusclient_register_previous_gecko_pref_states(`ptr`: Long,`geckoPrefStates`: RustBuffer.ByValue,uniffi_out_err: UniffiRustCallStatus, 
): Unit
external fun uniffi_nimbus_fn_method_nimbusclient_reset_enrollments(`ptr`: Long,uniffi_out_err: UniffiRustCallStatus, 
): Unit
external fun uniffi_nimbus_fn_method_nimbusclient_reset_telemetry_identifiers(`ptr`: Long,uniffi_out_err: UniffiRustCallStatus, 
): RustBuffer.ByValue
external fun uniffi_nimbus_fn_method_nimbusclient_set_experiment_participation(`ptr`: Long,`optIn`: Byte,uniffi_out_err: UniffiRustCallStatus, 
): RustBuffer.ByValue
external fun uniffi_nimbus_fn_method_nimbusclient_set_experiments_locally(`ptr`: Long,`experimentsJson`: RustBuffer.ByValue,uniffi_out_err: UniffiRustCallStatus, 
): Unit
external fun uniffi_nimbus_fn_method_nimbusclient_set_fetch_enabled(`ptr`: Long,`flag`: Byte,uniffi_out_err: UniffiRustCallStatus, 
): Unit
external fun uniffi_nimbus_fn_method_nimbusclient_set_rollout_participation(`ptr`: Long,`optIn`: Byte,uniffi_out_err: UniffiRustCallStatus, 
): RustBuffer.ByValue
external fun uniffi_nimbus_fn_method_nimbusclient_unenroll_for_gecko_pref(`ptr`: Long,`prefState`: RustBuffer.ByValue,`prefUnenrollReason`: RustBuffer.ByValue,uniffi_out_err: UniffiRustCallStatus, 
): RustBuffer.ByValue
external fun uniffi_nimbus_fn_method_nimbusclient_unenroll_from_all_firefox_labs(`ptr`: Long,uniffi_out_err: UniffiRustCallStatus, 
): RustBuffer.ByValue
external fun uniffi_nimbus_fn_method_nimbusclient_unenroll_from_firefox_lab(`ptr`: Long,`slug`: RustBuffer.ByValue,uniffi_out_err: UniffiRustCallStatus, 
): RustBuffer.ByValue
external fun uniffi_nimbus_fn_clone_nimbusstringhelper(`handle`: Long,uniffi_out_err: UniffiRustCallStatus, 
): Long
external fun uniffi_nimbus_fn_free_nimbusstringhelper(`handle`: Long,uniffi_out_err: UniffiRustCallStatus, 
): Unit
external fun uniffi_nimbus_fn_method_nimbusstringhelper_get_uuid(`ptr`: Long,`template`: RustBuffer.ByValue,uniffi_out_err: UniffiRustCallStatus, 
): RustBuffer.ByValue
external fun uniffi_nimbus_fn_method_nimbusstringhelper_string_format(`ptr`: Long,`template`: RustBuffer.ByValue,`uuid`: RustBuffer.ByValue,uniffi_out_err: UniffiRustCallStatus, 
): RustBuffer.ByValue
external fun uniffi_nimbus_fn_clone_nimbustargetinghelper(`handle`: Long,uniffi_out_err: UniffiRustCallStatus, 
): Long
external fun uniffi_nimbus_fn_free_nimbustargetinghelper(`handle`: Long,uniffi_out_err: UniffiRustCallStatus, 
): Unit
external fun uniffi_nimbus_fn_method_nimbustargetinghelper_eval_jexl(`ptr`: Long,`expression`: RustBuffer.ByValue,uniffi_out_err: UniffiRustCallStatus, 
): Byte
external fun uniffi_nimbus_fn_method_nimbustargetinghelper_eval_jexl_debug(`ptr`: Long,`expression`: RustBuffer.ByValue,uniffi_out_err: UniffiRustCallStatus, 
): RustBuffer.ByValue
external fun uniffi_nimbus_fn_clone_recordedcontext(`handle`: Long,uniffi_out_err: UniffiRustCallStatus, 
): Long
external fun uniffi_nimbus_fn_free_recordedcontext(`handle`: Long,uniffi_out_err: UniffiRustCallStatus, 
): Unit
external fun uniffi_nimbus_fn_init_callback_vtable_recordedcontext(`vtable`: UniffiVTableCallbackInterfaceRecordedContext,
): Unit
external fun uniffi_nimbus_fn_method_recordedcontext_get_event_queries(`ptr`: Long,uniffi_out_err: UniffiRustCallStatus, 
): RustBuffer.ByValue
external fun uniffi_nimbus_fn_method_recordedcontext_record(`ptr`: Long,uniffi_out_err: UniffiRustCallStatus, 
): Unit
external fun uniffi_nimbus_fn_method_recordedcontext_set_event_query_values(`ptr`: Long,`eventQueryValues`: RustBuffer.ByValue,uniffi_out_err: UniffiRustCallStatus, 
): Unit
external fun uniffi_nimbus_fn_method_recordedcontext_to_json(`ptr`: Long,uniffi_out_err: UniffiRustCallStatus, 
): RustBuffer.ByValue
external fun uniffi_nimbus_fn_func_get_calculated_attributes(`installationDate`: RustBuffer.ByValue,`dbPath`: RustBuffer.ByValue,`locale`: RustBuffer.ByValue,uniffi_out_err: UniffiRustCallStatus, 
): RustBuffer.ByValue
external fun uniffi_nimbus_fn_func_validate_event_queries(`recordedContext`: Long,uniffi_out_err: UniffiRustCallStatus, 
): Unit
external fun ffi_nimbus_rustbuffer_alloc(`size`: Long,uniffi_out_err: UniffiRustCallStatus, 
): RustBuffer.ByValue
external fun ffi_nimbus_rustbuffer_from_bytes(`bytes`: ForeignBytes.ByValue,uniffi_out_err: UniffiRustCallStatus, 
): RustBuffer.ByValue
external fun ffi_nimbus_rustbuffer_free(`buf`: RustBuffer.ByValue,uniffi_out_err: UniffiRustCallStatus, 
): Unit
external fun ffi_nimbus_rustbuffer_reserve(`buf`: RustBuffer.ByValue,`additional`: Long,uniffi_out_err: UniffiRustCallStatus, 
): RustBuffer.ByValue
external fun ffi_nimbus_rust_future_poll_u8(`handle`: Long,`callback`: UniffiRustFutureContinuationCallback,`callbackData`: Long,
): Unit
external fun ffi_nimbus_rust_future_cancel_u8(`handle`: Long,
): Unit
external fun ffi_nimbus_rust_future_free_u8(`handle`: Long,
): Unit
external fun ffi_nimbus_rust_future_complete_u8(`handle`: Long,uniffi_out_err: UniffiRustCallStatus, 
): Byte
external fun ffi_nimbus_rust_future_poll_i8(`handle`: Long,`callback`: UniffiRustFutureContinuationCallback,`callbackData`: Long,
): Unit
external fun ffi_nimbus_rust_future_cancel_i8(`handle`: Long,
): Unit
external fun ffi_nimbus_rust_future_free_i8(`handle`: Long,
): Unit
external fun ffi_nimbus_rust_future_complete_i8(`handle`: Long,uniffi_out_err: UniffiRustCallStatus, 
): Byte
external fun ffi_nimbus_rust_future_poll_u16(`handle`: Long,`callback`: UniffiRustFutureContinuationCallback,`callbackData`: Long,
): Unit
external fun ffi_nimbus_rust_future_cancel_u16(`handle`: Long,
): Unit
external fun ffi_nimbus_rust_future_free_u16(`handle`: Long,
): Unit
external fun ffi_nimbus_rust_future_complete_u16(`handle`: Long,uniffi_out_err: UniffiRustCallStatus, 
): Short
external fun ffi_nimbus_rust_future_poll_i16(`handle`: Long,`callback`: UniffiRustFutureContinuationCallback,`callbackData`: Long,
): Unit
external fun ffi_nimbus_rust_future_cancel_i16(`handle`: Long,
): Unit
external fun ffi_nimbus_rust_future_free_i16(`handle`: Long,
): Unit
external fun ffi_nimbus_rust_future_complete_i16(`handle`: Long,uniffi_out_err: UniffiRustCallStatus, 
): Short
external fun ffi_nimbus_rust_future_poll_u32(`handle`: Long,`callback`: UniffiRustFutureContinuationCallback,`callbackData`: Long,
): Unit
external fun ffi_nimbus_rust_future_cancel_u32(`handle`: Long,
): Unit
external fun ffi_nimbus_rust_future_free_u32(`handle`: Long,
): Unit
external fun ffi_nimbus_rust_future_complete_u32(`handle`: Long,uniffi_out_err: UniffiRustCallStatus, 
): Int
external fun ffi_nimbus_rust_future_poll_i32(`handle`: Long,`callback`: UniffiRustFutureContinuationCallback,`callbackData`: Long,
): Unit
external fun ffi_nimbus_rust_future_cancel_i32(`handle`: Long,
): Unit
external fun ffi_nimbus_rust_future_free_i32(`handle`: Long,
): Unit
external fun ffi_nimbus_rust_future_complete_i32(`handle`: Long,uniffi_out_err: UniffiRustCallStatus, 
): Int
external fun ffi_nimbus_rust_future_poll_u64(`handle`: Long,`callback`: UniffiRustFutureContinuationCallback,`callbackData`: Long,
): Unit
external fun ffi_nimbus_rust_future_cancel_u64(`handle`: Long,
): Unit
external fun ffi_nimbus_rust_future_free_u64(`handle`: Long,
): Unit
external fun ffi_nimbus_rust_future_complete_u64(`handle`: Long,uniffi_out_err: UniffiRustCallStatus, 
): Long
external fun ffi_nimbus_rust_future_poll_i64(`handle`: Long,`callback`: UniffiRustFutureContinuationCallback,`callbackData`: Long,
): Unit
external fun ffi_nimbus_rust_future_cancel_i64(`handle`: Long,
): Unit
external fun ffi_nimbus_rust_future_free_i64(`handle`: Long,
): Unit
external fun ffi_nimbus_rust_future_complete_i64(`handle`: Long,uniffi_out_err: UniffiRustCallStatus, 
): Long
external fun ffi_nimbus_rust_future_poll_f32(`handle`: Long,`callback`: UniffiRustFutureContinuationCallback,`callbackData`: Long,
): Unit
external fun ffi_nimbus_rust_future_cancel_f32(`handle`: Long,
): Unit
external fun ffi_nimbus_rust_future_free_f32(`handle`: Long,
): Unit
external fun ffi_nimbus_rust_future_complete_f32(`handle`: Long,uniffi_out_err: UniffiRustCallStatus, 
): Float
external fun ffi_nimbus_rust_future_poll_f64(`handle`: Long,`callback`: UniffiRustFutureContinuationCallback,`callbackData`: Long,
): Unit
external fun ffi_nimbus_rust_future_cancel_f64(`handle`: Long,
): Unit
external fun ffi_nimbus_rust_future_free_f64(`handle`: Long,
): Unit
external fun ffi_nimbus_rust_future_complete_f64(`handle`: Long,uniffi_out_err: UniffiRustCallStatus, 
): Double
external fun ffi_nimbus_rust_future_poll_rust_buffer(`handle`: Long,`callback`: UniffiRustFutureContinuationCallback,`callbackData`: Long,
): Unit
external fun ffi_nimbus_rust_future_cancel_rust_buffer(`handle`: Long,
): Unit
external fun ffi_nimbus_rust_future_free_rust_buffer(`handle`: Long,
): Unit
external fun ffi_nimbus_rust_future_complete_rust_buffer(`handle`: Long,uniffi_out_err: UniffiRustCallStatus, 
): RustBuffer.ByValue
external fun ffi_nimbus_rust_future_poll_void(`handle`: Long,`callback`: UniffiRustFutureContinuationCallback,`callbackData`: Long,
): Unit
external fun ffi_nimbus_rust_future_cancel_void(`handle`: Long,
): Unit
external fun ffi_nimbus_rust_future_free_void(`handle`: Long,
): Unit
external fun ffi_nimbus_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_nimbus_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// Magic number for the Rust proxy to call using the same mechanism as every other method,
// to free the callback once it's dropped by Rust.
internal const val IDX_CALLBACK_FREE = 0
// Callback return codes
internal const val UNIFFI_CALLBACK_SUCCESS = 0
internal const val UNIFFI_CALLBACK_ERROR = 1
internal const val UNIFFI_CALLBACK_UNEXPECTED_ERROR = 2

/**
 * @suppress
 */
public abstract class FfiConverterCallbackInterface<CallbackInterface: Any>: FfiConverter<CallbackInterface, Long> {
    internal val handleMap = UniffiHandleMap<CallbackInterface>()

    internal fun drop(handle: Long) {
        handleMap.remove(handle)
    }

    override fun lift(value: Long): CallbackInterface {
        return handleMap.get(value)
    }

    override fun read(buf: ByteBuffer) = lift(buf.getLong())

    override fun lower(value: CallbackInterface) = handleMap.insert(value)

    override fun allocationSize(value: CallbackInterface) = 8UL

    override fun write(value: CallbackInterface, buf: ByteBuffer) {
        buf.putLong(lower(value))
    }
}
/**
 * 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 FfiConverterUShort: FfiConverter<UShort, Short> {
    override fun lift(value: Short): UShort {
        return value.toUShort()
    }

    override fun read(buf: ByteBuffer): UShort {
        return lift(buf.getShort())
    }

    override fun lower(value: UShort): Short {
        return value.toShort()
    }

    override fun allocationSize(value: UShort) = 2UL

    override fun write(value: UShort, buf: ByteBuffer) {
        buf.putShort(value.toShort())
    }
}

/**
 * @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 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)
    }
}


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


public interface GeckoPrefHandler {
    
    fun `getPrefsWithState`(): Map<kotlin.String, Map<kotlin.String, GeckoPrefState>>
    
    fun `setGeckoPrefsOriginalValues`(`originalGeckoPrefs`: List<OriginalGeckoPref>)
    
    fun `setGeckoPrefsState`(`newPrefsState`: List<GeckoPrefState>)
    
    companion object
}

open class GeckoPrefHandlerImpl: Disposable, AutoCloseable, GeckoPrefHandler
{

    @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
    }

    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_nimbus_fn_free_geckoprefhandler(handle, status)
            }
        }
    }

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

    override fun `getPrefsWithState`(): Map<kotlin.String, Map<kotlin.String, GeckoPrefState>> {
            return FfiConverterMapStringMapStringTypeGeckoPrefState.lift(
    callWithHandle {
    uniffiRustCall() { _status ->
    UniffiLib.uniffi_nimbus_fn_method_geckoprefhandler_get_prefs_with_state(
        it,
        _status)
}
    }
    )
    }
    

    override fun `setGeckoPrefsOriginalValues`(`originalGeckoPrefs`: List<OriginalGeckoPref>)
        = 
    callWithHandle {
    uniffiRustCall() { _status ->
    UniffiLib.uniffi_nimbus_fn_method_geckoprefhandler_set_gecko_prefs_original_values(
        it,
        FfiConverterSequenceTypeOriginalGeckoPref.lower(`originalGeckoPrefs`),_status)
}
    }
    
    

    override fun `setGeckoPrefsState`(`newPrefsState`: List<GeckoPrefState>)
        = 
    callWithHandle {
    uniffiRustCall() { _status ->
    UniffiLib.uniffi_nimbus_fn_method_geckoprefhandler_set_gecko_prefs_state(
        it,
        FfiConverterSequenceTypeGeckoPrefState.lower(`newPrefsState`),_status)
}
    }
    
    

    

    


    
    
    /**
     * @suppress
     */
    companion object
    
}



// Put the implementation in an object so we don't pollute the top-level namespace
internal object uniffiCallbackInterfaceGeckoPrefHandler {
    internal object `getPrefsWithState`: UniffiCallbackInterfaceGeckoPrefHandlerMethod0 {
        override fun callback(`uniffiHandle`: Long,`uniffiOutReturn`: RustBuffer,uniffiCallStatus: UniffiRustCallStatus,) {
            val uniffiObj = FfiConverterTypeGeckoPrefHandler.handleMap.get(uniffiHandle)
            val makeCall = { ->
                uniffiObj.`getPrefsWithState`(
                )
            }
            val writeReturn = { value: Map<kotlin.String, Map<kotlin.String, GeckoPrefState>> -> uniffiOutReturn.setValue(FfiConverterMapStringMapStringTypeGeckoPrefState.lower(value)) }
            uniffiTraitInterfaceCall(uniffiCallStatus, makeCall, writeReturn)
        }
    }
    internal object `setGeckoPrefsOriginalValues`: UniffiCallbackInterfaceGeckoPrefHandlerMethod1 {
        override fun callback(`uniffiHandle`: Long,`originalGeckoPrefs`: RustBuffer.ByValue,`uniffiOutReturn`: Pointer,uniffiCallStatus: UniffiRustCallStatus,) {
            val uniffiObj = FfiConverterTypeGeckoPrefHandler.handleMap.get(uniffiHandle)
            val makeCall = { ->
                uniffiObj.`setGeckoPrefsOriginalValues`(
                    FfiConverterSequenceTypeOriginalGeckoPref.lift(`originalGeckoPrefs`),
                )
            }
            val writeReturn = { _: Unit -> Unit }
            uniffiTraitInterfaceCall(uniffiCallStatus, makeCall, writeReturn)
        }
    }
    internal object `setGeckoPrefsState`: UniffiCallbackInterfaceGeckoPrefHandlerMethod2 {
        override fun callback(`uniffiHandle`: Long,`newPrefsState`: RustBuffer.ByValue,`uniffiOutReturn`: Pointer,uniffiCallStatus: UniffiRustCallStatus,) {
            val uniffiObj = FfiConverterTypeGeckoPrefHandler.handleMap.get(uniffiHandle)
            val makeCall = { ->
                uniffiObj.`setGeckoPrefsState`(
                    FfiConverterSequenceTypeGeckoPrefState.lift(`newPrefsState`),
                )
            }
            val writeReturn = { _: Unit -> Unit }
            uniffiTraitInterfaceCall(uniffiCallStatus, makeCall, writeReturn)
        }
    }

    internal object uniffiFree: UniffiCallbackInterfaceFree {
        override fun callback(handle: Long) {
            FfiConverterTypeGeckoPrefHandler.handleMap.remove(handle)
        }
    }

    internal object uniffiClone: UniffiCallbackInterfaceClone {
        override fun callback(handle: Long): Long {
            return FfiConverterTypeGeckoPrefHandler.handleMap.clone(handle)
        }
    }

    internal var vtable = UniffiVTableCallbackInterfaceGeckoPrefHandler.UniffiByValue(
        uniffiFree,
        uniffiClone,
        `getPrefsWithState`,
        `setGeckoPrefsOriginalValues`,
        `setGeckoPrefsState`,
    )

    // Registers the foreign callback with the Rust side.
    // This method is generated for each callback interface.
    internal fun register(lib: UniffiLib) {
        lib.uniffi_nimbus_fn_init_callback_vtable_geckoprefhandler(vtable)
    }
}

/**
 * @suppress
 */
public object FfiConverterTypeGeckoPrefHandler: FfiConverter<GeckoPrefHandler, Long> {
    internal val handleMap = UniffiHandleMap<GeckoPrefHandler>()

    override fun lower(value: GeckoPrefHandler): Long {
        if (value is GeckoPrefHandlerImpl) {
             // Rust-implemented object.  Clone the handle and return it
            return value.uniffiCloneHandle()
         } else {
            // Kotlin object, generate a new vtable handle and return that.
            return handleMap.insert(value)
         }
    }

    override fun lift(value: Long): GeckoPrefHandler {
        if ((value and 1.toLong()) == 0.toLong()) {
            // Rust-generated handle, construct a new class that uses the handle to implement the
            // interface
            return GeckoPrefHandlerImpl(UniffiWithHandle, value)
        } else {
            // Kotlin-generated handle, get the object from the handle map
            return handleMap.remove(value)
        }
    }

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

    override fun allocationSize(value: GeckoPrefHandler) = 8UL

    override fun write(value: GeckoPrefHandler, 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
//


public interface MetricsHandler {
    
    fun `recordDatabaseLoad`(`event`: DatabaseLoadExtraDef)
    
    fun `recordDatabaseMigration`(`event`: DatabaseMigrationExtraDef)
    
    fun `recordEnrollmentStatuses`(`enrollmentStatusExtras`: List<EnrollmentStatusExtraDef>)
    
    /**
     * Feature activation is the pre-cursor to feature exposure: it is defined as the first time
     * the feature configuration is asked for.
     */
    fun `recordFeatureActivation`(`event`: FeatureExposureExtraDef)
    
    fun `recordFeatureExposure`(`event`: FeatureExposureExtraDef)
    
    fun `recordMalformedFeatureConfig`(`event`: MalformedFeatureConfigExtraDef)
    
    fun `submitTargetingContext`()
    
    companion object
}

open class MetricsHandlerImpl: Disposable, AutoCloseable, MetricsHandler
{

    @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
    }

    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_nimbus_fn_free_metricshandler(handle, status)
            }
        }
    }

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

    override fun `recordDatabaseLoad`(`event`: DatabaseLoadExtraDef)
        = 
    callWithHandle {
    uniffiRustCall() { _status ->
    UniffiLib.uniffi_nimbus_fn_method_metricshandler_record_database_load(
        it,
        FfiConverterTypeDatabaseLoadExtraDef.lower(`event`),_status)
}
    }
    
    

    override fun `recordDatabaseMigration`(`event`: DatabaseMigrationExtraDef)
        = 
    callWithHandle {
    uniffiRustCall() { _status ->
    UniffiLib.uniffi_nimbus_fn_method_metricshandler_record_database_migration(
        it,
        FfiConverterTypeDatabaseMigrationExtraDef.lower(`event`),_status)
}
    }
    
    

    override fun `recordEnrollmentStatuses`(`enrollmentStatusExtras`: List<EnrollmentStatusExtraDef>)
        = 
    callWithHandle {
    uniffiRustCall() { _status ->
    UniffiLib.uniffi_nimbus_fn_method_metricshandler_record_enrollment_statuses(
        it,
        FfiConverterSequenceTypeEnrollmentStatusExtraDef.lower(`enrollmentStatusExtras`),_status)
}
    }
    
    

    
    /**
     * Feature activation is the pre-cursor to feature exposure: it is defined as the first time
     * the feature configuration is asked for.
     */override fun `recordFeatureActivation`(`event`: FeatureExposureExtraDef)
        = 
    callWithHandle {
    uniffiRustCall() { _status ->
    UniffiLib.uniffi_nimbus_fn_method_metricshandler_record_feature_activation(
        it,
        FfiConverterTypeFeatureExposureExtraDef.lower(`event`),_status)
}
    }
    
    

    override fun `recordFeatureExposure`(`event`: FeatureExposureExtraDef)
        = 
    callWithHandle {
    uniffiRustCall() { _status ->
    UniffiLib.uniffi_nimbus_fn_method_metricshandler_record_feature_exposure(
        it,
        FfiConverterTypeFeatureExposureExtraDef.lower(`event`),_status)
}
    }
    
    

    override fun `recordMalformedFeatureConfig`(`event`: MalformedFeatureConfigExtraDef)
        = 
    callWithHandle {
    uniffiRustCall() { _status ->
    UniffiLib.uniffi_nimbus_fn_method_metricshandler_record_malformed_feature_config(
        it,
        FfiConverterTypeMalformedFeatureConfigExtraDef.lower(`event`),_status)
}
    }
    
    

    override fun `submitTargetingContext`()
        = 
    callWithHandle {
    uniffiRustCall() { _status ->
    UniffiLib.uniffi_nimbus_fn_method_metricshandler_submit_targeting_context(
        it,
        _status)
}
    }
    
    

    

    


    
    
    /**
     * @suppress
     */
    companion object
    
}



// Put the implementation in an object so we don't pollute the top-level namespace
internal object uniffiCallbackInterfaceMetricsHandler {
    internal object `recordDatabaseLoad`: UniffiCallbackInterfaceMetricsHandlerMethod0 {
        override fun callback(`uniffiHandle`: Long,`event`: RustBuffer.ByValue,`uniffiOutReturn`: Pointer,uniffiCallStatus: UniffiRustCallStatus,) {
            val uniffiObj = FfiConverterTypeMetricsHandler.handleMap.get(uniffiHandle)
            val makeCall = { ->
                uniffiObj.`recordDatabaseLoad`(
                    FfiConverterTypeDatabaseLoadExtraDef.lift(`event`),
                )
            }
            val writeReturn = { _: Unit -> Unit }
            uniffiTraitInterfaceCall(uniffiCallStatus, makeCall, writeReturn)
        }
    }
    internal object `recordDatabaseMigration`: UniffiCallbackInterfaceMetricsHandlerMethod1 {
        override fun callback(`uniffiHandle`: Long,`event`: RustBuffer.ByValue,`uniffiOutReturn`: Pointer,uniffiCallStatus: UniffiRustCallStatus,) {
            val uniffiObj = FfiConverterTypeMetricsHandler.handleMap.get(uniffiHandle)
            val makeCall = { ->
                uniffiObj.`recordDatabaseMigration`(
                    FfiConverterTypeDatabaseMigrationExtraDef.lift(`event`),
                )
            }
            val writeReturn = { _: Unit -> Unit }
            uniffiTraitInterfaceCall(uniffiCallStatus, makeCall, writeReturn)
        }
    }
    internal object `recordEnrollmentStatuses`: UniffiCallbackInterfaceMetricsHandlerMethod2 {
        override fun callback(`uniffiHandle`: Long,`enrollmentStatusExtras`: RustBuffer.ByValue,`uniffiOutReturn`: Pointer,uniffiCallStatus: UniffiRustCallStatus,) {
            val uniffiObj = FfiConverterTypeMetricsHandler.handleMap.get(uniffiHandle)
            val makeCall = { ->
                uniffiObj.`recordEnrollmentStatuses`(
                    FfiConverterSequenceTypeEnrollmentStatusExtraDef.lift(`enrollmentStatusExtras`),
                )
            }
            val writeReturn = { _: Unit -> Unit }
            uniffiTraitInterfaceCall(uniffiCallStatus, makeCall, writeReturn)
        }
    }
    internal object `recordFeatureActivation`: UniffiCallbackInterfaceMetricsHandlerMethod3 {
        override fun callback(`uniffiHandle`: Long,`event`: RustBuffer.ByValue,`uniffiOutReturn`: Pointer,uniffiCallStatus: UniffiRustCallStatus,) {
            val uniffiObj = FfiConverterTypeMetricsHandler.handleMap.get(uniffiHandle)
            val makeCall = { ->
                uniffiObj.`recordFeatureActivation`(
                    FfiConverterTypeFeatureExposureExtraDef.lift(`event`),
                )
            }
            val writeReturn = { _: Unit -> Unit }
            uniffiTraitInterfaceCall(uniffiCallStatus, makeCall, writeReturn)
        }
    }
    internal object `recordFeatureExposure`: UniffiCallbackInterfaceMetricsHandlerMethod4 {
        override fun callback(`uniffiHandle`: Long,`event`: RustBuffer.ByValue,`uniffiOutReturn`: Pointer,uniffiCallStatus: UniffiRustCallStatus,) {
            val uniffiObj = FfiConverterTypeMetricsHandler.handleMap.get(uniffiHandle)
            val makeCall = { ->
                uniffiObj.`recordFeatureExposure`(
                    FfiConverterTypeFeatureExposureExtraDef.lift(`event`),
                )
            }
            val writeReturn = { _: Unit -> Unit }
            uniffiTraitInterfaceCall(uniffiCallStatus, makeCall, writeReturn)
        }
    }
    internal object `recordMalformedFeatureConfig`: UniffiCallbackInterfaceMetricsHandlerMethod5 {
        override fun callback(`uniffiHandle`: Long,`event`: RustBuffer.ByValue,`uniffiOutReturn`: Pointer,uniffiCallStatus: UniffiRustCallStatus,) {
            val uniffiObj = FfiConverterTypeMetricsHandler.handleMap.get(uniffiHandle)
            val makeCall = { ->
                uniffiObj.`recordMalformedFeatureConfig`(
                    FfiConverterTypeMalformedFeatureConfigExtraDef.lift(`event`),
                )
            }
            val writeReturn = { _: Unit -> Unit }
            uniffiTraitInterfaceCall(uniffiCallStatus, makeCall, writeReturn)
        }
    }
    internal object `submitTargetingContext`: UniffiCallbackInterfaceMetricsHandlerMethod6 {
        override fun callback(`uniffiHandle`: Long,`uniffiOutReturn`: Pointer,uniffiCallStatus: UniffiRustCallStatus,) {
            val uniffiObj = FfiConverterTypeMetricsHandler.handleMap.get(uniffiHandle)
            val makeCall = { ->
                uniffiObj.`submitTargetingContext`(
                )
            }
            val writeReturn = { _: Unit -> Unit }
            uniffiTraitInterfaceCall(uniffiCallStatus, makeCall, writeReturn)
        }
    }

    internal object uniffiFree: UniffiCallbackInterfaceFree {
        override fun callback(handle: Long) {
            FfiConverterTypeMetricsHandler.handleMap.remove(handle)
        }
    }

    internal object uniffiClone: UniffiCallbackInterfaceClone {
        override fun callback(handle: Long): Long {
            return FfiConverterTypeMetricsHandler.handleMap.clone(handle)
        }
    }

    internal var vtable = UniffiVTableCallbackInterfaceMetricsHandler.UniffiByValue(
        uniffiFree,
        uniffiClone,
        `recordDatabaseLoad`,
        `recordDatabaseMigration`,
        `recordEnrollmentStatuses`,
        `recordFeatureActivation`,
        `recordFeatureExposure`,
        `recordMalformedFeatureConfig`,
        `submitTargetingContext`,
    )

    // Registers the foreign callback with the Rust side.
    // This method is generated for each callback interface.
    internal fun register(lib: UniffiLib) {
        lib.uniffi_nimbus_fn_init_callback_vtable_metricshandler(vtable)
    }
}

/**
 * @suppress
 */
public object FfiConverterTypeMetricsHandler: FfiConverter<MetricsHandler, Long> {
    internal val handleMap = UniffiHandleMap<MetricsHandler>()

    override fun lower(value: MetricsHandler): Long {
        if (value is MetricsHandlerImpl) {
             // Rust-implemented object.  Clone the handle and return it
            return value.uniffiCloneHandle()
         } else {
            // Kotlin object, generate a new vtable handle and return that.
            return handleMap.insert(value)
         }
    }

    override fun lift(value: Long): MetricsHandler {
        if ((value and 1.toLong()) == 0.toLong()) {
            // Rust-generated handle, construct a new class that uses the handle to implement the
            // interface
            return MetricsHandlerImpl(UniffiWithHandle, value)
        } else {
            // Kotlin-generated handle, get the object from the handle map
            return handleMap.remove(value)
        }
    }

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

    override fun allocationSize(value: MetricsHandler) = 8UL

    override fun write(value: MetricsHandler, 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
//


public interface NimbusClientInterface {
    
    /**
     * Advances what the event store thinks is now.
     * This, and `record_past_event` are useful for testing.
     * `by_seconds` must be positive.
     */
    fun `advanceEventTime`(`bySeconds`: kotlin.Long)
    
    /**
     * Apply the updated experiments from the last fetch.
     * After calling this, the list of active experiments might change
     * (there might be new experiments, or old experiments might have expired).
     */
    fun `applyPendingExperiments`(): List<EnrollmentChangeEvent>
    
    fun `clearEvents`()
    
    /**
     * This provides a unified String interpolation library which exposes the application context.
     * It's first use is in the messaging helper, to add extra parameters to URLs.
     */
    fun `createStringHelper`(`additionalContext`: JsonObject? = null): NimbusStringHelper
    
    /**
     * This provides low level access to the targeting machinery for other uses by the application (e.g. messages)
     * Additional parameters can be added via the optional JSON object. This allows for many JEXL expressions
     * to be run across the same context.
     */
    fun `createTargetingHelper`(`additionalContext`: JsonObject? = null): NimbusTargetingHelper
    
    fun `dumpStateToLog`()
    
    fun `enrollInFirefoxLab`(`slug`: kotlin.String): FirefoxLabsEnrollResult
    
    /**
     * Fetches the list of experiments from the server. This does not affect the list
     * of active experiments or experiment enrolment.
     * Fetched experiments are not applied until `apply_pending_updates()` is called.
     */
    fun `fetchExperiments`()
    
    /**
     * Returns a list of experiments this user is enrolled in.
     */
    fun `getActiveExperiments`(): List<EnrolledExperiment>
    
    /**
     * Returns a list of experiments for this `app_name`, as specified in the `AppContext`.
     * It is not intended to be used to be used for user facing applications.
     */
    fun `getAvailableExperiments`(): List<AvailableExperiment>
    
    fun `getAvailableFirefoxLabs`(): List<FirefoxLabsMetadata>
    
    /**
     * Returns the branch allocated for a given slug or id.
     */
    fun `getExperimentBranch`(`id`: kotlin.String): kotlin.String?
    
    /**
     * Returns a list of experiment branches for a given experiment ID.
     */
    fun `getExperimentBranches`(`experimentSlug`: kotlin.String): List<ExperimentBranch>
    
    /**
     * Getter and setter for user's participation in experiments only.
     * Possible values are:
     * * `true`: the user will enroll in experiments as usual.
     * * `false`: the user will not enroll in new experiments, and opt out of all existing ones.
     */
    fun `getExperimentParticipation`(): kotlin.Boolean
    
    fun `getFeatureConfigVariables`(`featureId`: kotlin.String): kotlin.String?
    
    fun `getPreviousGeckoPrefStates`(`experimentSlug`: kotlin.String): List<PreviousGeckoPrefState>?
    
    /**
     * Getter and setter for user's participation in rollouts.
     * Possible values are:
     * * `true`: the user will enroll in rollouts as usual.
     * * `false`: the user will not enroll in new rollouts, and opt out of all existing ones.
     */
    fun `getRolloutParticipation`(): kotlin.Boolean
    
    /**
     * Initializes the database and caches enough information so that the
     * non-blocking API functions (eg, `get_experiment_branch()`) can
     * return accurate results rather than throwing a "not initialized" error.
     * It's not strictly necessary to call this function - any function that
     * wants to use the database will implicitly initialize too - this exists
     * so that the consuming application can have confidence the non-blocking
     * functions will return data instead of returning an error, and will do
     * the minimum amount of work to achieve that.
     */
    fun `initialize`()
    
    fun `isFetchEnabled`(): kotlin.Boolean
    
    /**
     * Opt in to a specific branch on a specific experiment. Useful for
     * developers to test their app's interaction with the experiment.
     */
    fun `optInWithBranch`(`experimentSlug`: kotlin.String, `branch`: kotlin.String): List<EnrollmentChangeEvent>
    
    /**
     * Opt out of a specific experiment.
     */
    fun `optOut`(`experimentSlug`: kotlin.String): List<EnrollmentChangeEvent>
    
    /**
     * Records an event for the purposes of behavioral targeting.
     * This function is used to record and persist data used for the behavioral
     * targeting such as "core-active" user targeting.
     */
    fun `recordEvent`(`eventId`: kotlin.String, `count`: kotlin.Long = 1L)
    
    /**
     * Records a Glean event that this feature has been exposed.
     * If the feature is not involved in an experiment, then the event is suppressed.
     * If the feature is only involved in a rollout, then the event is suppressed.
     * If the feature is involved in an experiment, then record the experiment slug
     * and branch.
     * If the feature is involved in an experiment and a rollout, then record only the
     * experiment slug and branch.
     * If the slug is specified, then use this as the experiment, and use it to look up
     * the branch. This is useful for coenrolling features.
     */
    fun `recordFeatureExposure`(`featureId`: kotlin.String, `slug`: kotlin.String?)
    
    /**
     * Records a Glean event that this feature configuration is malformed.
     * Accepts a part_id to give the experiment owner or feature implementer
     * clues where to look.
     * The Glean event will always fire, but the content of that event will
     * vary depending on whether then feature is part of an experiment or rollout
     * or not.
     */
    fun `recordMalformedFeatureConfig`(`featureId`: kotlin.String, `partId`: kotlin.String)
    
    /**
     * Records an event as if it were in the past.
     * This, and `advance_event_time` are useful for testing.
     * `seconds_ago` must be positive.
     */
    fun `recordPastEvent`(`eventId`: kotlin.String, `secondsAgo`: kotlin.Long, `count`: kotlin.Long = 1L)
    
    fun `registerPreviousGeckoPrefStates`(`geckoPrefStates`: List<GeckoPrefState>)
    
    /**
     * These are test-only functions and should never be exposed to production
     * users, as they mess with the "statistical requirements" of the SDK.
     * Reset the enrollments and experiments in the database to an empty state.
     */
    fun `resetEnrollments`()
    
    /**
     * Reset internal state in response to application-level telemetry reset.
     *
     * Consumers should call this method when the user resets the telemetry state of the
     * consuming application, such as by opting out of submitting telemetry. It resets the
     * internal state of the Nimbus client to create a clean break between data collected
     * before and after the reset, including:
     *
     *    * clearing any unique identifiers used internally, so they will reset to
     *      new random values on next use.
     *    * accepting new randomization units, based on application-level ids that
     *      may have also changed.
     *    * disqualifying this client out of any active experiments, to avoid submitting
     *      misleading incomplete data.

     */
    fun `resetTelemetryIdentifiers`(): List<EnrollmentChangeEvent>
    
    fun `setExperimentParticipation`(`optIn`: kotlin.Boolean): List<EnrollmentChangeEvent>
    
    /**
     * A convenience method for apps to set the experiments from a local source
     * for either testing, or before the first fetch has finished.
     *
     * Experiments set with this method are not applied until `apply_pending_updates()` is called.
     */
    fun `setExperimentsLocally`(`experimentsJson`: kotlin.String)
    
    /**
     * Toggles the enablement of the fetch. If `false`, then calling `fetch_experiments`
     * returns immediately, having not done any fetching from remote settings.
     * This is only useful for QA, and should not be used in production: use
     * `set_experiment_participation` or `set_rollout_participation` instead.
     */
    fun `setFetchEnabled`(`flag`: kotlin.Boolean)
    
    fun `setRolloutParticipation`(`optIn`: kotlin.Boolean): List<EnrollmentChangeEvent>
    
    fun `unenrollForGeckoPref`(`prefState`: GeckoPrefState, `prefUnenrollReason`: PrefUnenrollReason): List<EnrollmentChangeEvent>
    
    fun `unenrollFromAllFirefoxLabs`(): List<EnrollmentChangeEvent>
    
    fun `unenrollFromFirefoxLab`(`slug`: kotlin.String): FirefoxLabsUnenrollResult
    
    companion object
}

open class NimbusClient: Disposable, AutoCloseable, NimbusClientInterface
{

    @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(`appCtx`: AppContext, `recordedContext`: RecordedContext?, `coenrollingFeatureIds`: List<kotlin.String>, `dbpath`: kotlin.String, `metricsHandler`: MetricsHandler, `geckoPrefHandler`: GeckoPrefHandler?, `remoteSettingsInfo`: NimbusServerSettings?) :
        this(UniffiWithHandle, 
    uniffiRustCallWithError(NimbusException) { _status ->
    UniffiLib.uniffi_nimbus_fn_constructor_nimbusclient_new(
    
        FfiConverterTypeAppContext.lower(`appCtx`),FfiConverterOptionalTypeRecordedContext.lower(`recordedContext`),FfiConverterSequenceString.lower(`coenrollingFeatureIds`),FfiConverterString.lower(`dbpath`),FfiConverterTypeMetricsHandler.lower(`metricsHandler`),FfiConverterOptionalTypeGeckoPrefHandler.lower(`geckoPrefHandler`),FfiConverterOptionalTypeNimbusServerSettings.lower(`remoteSettingsInfo`),_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_nimbus_fn_free_nimbusclient(handle, status)
            }
        }
    }

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

    
    /**
     * Advances what the event store thinks is now.
     * This, and `record_past_event` are useful for testing.
     * `by_seconds` must be positive.
     */
    @Throws(NimbusException::class)override fun `advanceEventTime`(`bySeconds`: kotlin.Long)
        = 
    callWithHandle {
    uniffiRustCallWithError(NimbusException) { _status ->
    UniffiLib.uniffi_nimbus_fn_method_nimbusclient_advance_event_time(
        it,
        FfiConverterLong.lower(`bySeconds`),_status)
}
    }
    
    

    
    /**
     * Apply the updated experiments from the last fetch.
     * After calling this, the list of active experiments might change
     * (there might be new experiments, or old experiments might have expired).
     */
    @Throws(NimbusException::class)override fun `applyPendingExperiments`(): List<EnrollmentChangeEvent> {
            return FfiConverterSequenceTypeEnrollmentChangeEvent.lift(
    callWithHandle {
    uniffiRustCallWithError(NimbusException) { _status ->
    UniffiLib.uniffi_nimbus_fn_method_nimbusclient_apply_pending_experiments(
        it,
        _status)
}
    }
    )
    }
    

    
    @Throws(NimbusException::class)override fun `clearEvents`()
        = 
    callWithHandle {
    uniffiRustCallWithError(NimbusException) { _status ->
    UniffiLib.uniffi_nimbus_fn_method_nimbusclient_clear_events(
        it,
        _status)
}
    }
    
    

    
    /**
     * This provides a unified String interpolation library which exposes the application context.
     * It's first use is in the messaging helper, to add extra parameters to URLs.
     */
    @Throws(NimbusException::class)override fun `createStringHelper`(`additionalContext`: JsonObject?): NimbusStringHelper {
            return FfiConverterTypeNimbusStringHelper.lift(
    callWithHandle {
    uniffiRustCallWithError(NimbusException) { _status ->
    UniffiLib.uniffi_nimbus_fn_method_nimbusclient_create_string_helper(
        it,
        FfiConverterOptionalTypeJsonObject.lower(`additionalContext`),_status)
}
    }
    )
    }
    

    
    /**
     * This provides low level access to the targeting machinery for other uses by the application (e.g. messages)
     * Additional parameters can be added via the optional JSON object. This allows for many JEXL expressions
     * to be run across the same context.
     */
    @Throws(NimbusException::class)override fun `createTargetingHelper`(`additionalContext`: JsonObject?): NimbusTargetingHelper {
            return FfiConverterTypeNimbusTargetingHelper.lift(
    callWithHandle {
    uniffiRustCallWithError(NimbusException) { _status ->
    UniffiLib.uniffi_nimbus_fn_method_nimbusclient_create_targeting_helper(
        it,
        FfiConverterOptionalTypeJsonObject.lower(`additionalContext`),_status)
}
    }
    )
    }
    

    
    @Throws(NimbusException::class)override fun `dumpStateToLog`()
        = 
    callWithHandle {
    uniffiRustCallWithError(NimbusException) { _status ->
    UniffiLib.uniffi_nimbus_fn_method_nimbusclient_dump_state_to_log(
        it,
        _status)
}
    }
    
    

    
    @Throws(NimbusException::class)override fun `enrollInFirefoxLab`(`slug`: kotlin.String): FirefoxLabsEnrollResult {
            return FfiConverterTypeFirefoxLabsEnrollResult.lift(
    callWithHandle {
    uniffiRustCallWithError(NimbusException) { _status ->
    UniffiLib.uniffi_nimbus_fn_method_nimbusclient_enroll_in_firefox_lab(
        it,
        FfiConverterString.lower(`slug`),_status)
}
    }
    )
    }
    

    
    /**
     * Fetches the list of experiments from the server. This does not affect the list
     * of active experiments or experiment enrolment.
     * Fetched experiments are not applied until `apply_pending_updates()` is called.
     */
    @Throws(NimbusException::class)override fun `fetchExperiments`()
        = 
    callWithHandle {
    uniffiRustCallWithError(NimbusException) { _status ->
    UniffiLib.uniffi_nimbus_fn_method_nimbusclient_fetch_experiments(
        it,
        _status)
}
    }
    
    

    
    /**
     * Returns a list of experiments this user is enrolled in.
     */
    @Throws(NimbusException::class)override fun `getActiveExperiments`(): List<EnrolledExperiment> {
            return FfiConverterSequenceTypeEnrolledExperiment.lift(
    callWithHandle {
    uniffiRustCallWithError(NimbusException) { _status ->
    UniffiLib.uniffi_nimbus_fn_method_nimbusclient_get_active_experiments(
        it,
        _status)
}
    }
    )
    }
    

    
    /**
     * Returns a list of experiments for this `app_name`, as specified in the `AppContext`.
     * It is not intended to be used to be used for user facing applications.
     */
    @Throws(NimbusException::class)override fun `getAvailableExperiments`(): List<AvailableExperiment> {
            return FfiConverterSequenceTypeAvailableExperiment.lift(
    callWithHandle {
    uniffiRustCallWithError(NimbusException) { _status ->
    UniffiLib.uniffi_nimbus_fn_method_nimbusclient_get_available_experiments(
        it,
        _status)
}
    }
    )
    }
    

    
    @Throws(NimbusException::class)override fun `getAvailableFirefoxLabs`(): List<FirefoxLabsMetadata> {
            return FfiConverterSequenceTypeFirefoxLabsMetadata.lift(
    callWithHandle {
    uniffiRustCallWithError(NimbusException) { _status ->
    UniffiLib.uniffi_nimbus_fn_method_nimbusclient_get_available_firefox_labs(
        it,
        _status)
}
    }
    )
    }
    

    
    /**
     * Returns the branch allocated for a given slug or id.
     */
    @Throws(NimbusException::class)override fun `getExperimentBranch`(`id`: kotlin.String): kotlin.String? {
            return FfiConverterOptionalString.lift(
    callWithHandle {
    uniffiRustCallWithError(NimbusException) { _status ->
    UniffiLib.uniffi_nimbus_fn_method_nimbusclient_get_experiment_branch(
        it,
        FfiConverterString.lower(`id`),_status)
}
    }
    )
    }
    

    
    /**
     * Returns a list of experiment branches for a given experiment ID.
     */
    @Throws(NimbusException::class)override fun `getExperimentBranches`(`experimentSlug`: kotlin.String): List<ExperimentBranch> {
            return FfiConverterSequenceTypeExperimentBranch.lift(
    callWithHandle {
    uniffiRustCallWithError(NimbusException) { _status ->
    UniffiLib.uniffi_nimbus_fn_method_nimbusclient_get_experiment_branches(
        it,
        FfiConverterString.lower(`experimentSlug`),_status)
}
    }
    )
    }
    

    
    /**
     * Getter and setter for user's participation in experiments only.
     * Possible values are:
     * * `true`: the user will enroll in experiments as usual.
     * * `false`: the user will not enroll in new experiments, and opt out of all existing ones.
     */
    @Throws(NimbusException::class)override fun `getExperimentParticipation`(): kotlin.Boolean {
            return FfiConverterBoolean.lift(
    callWithHandle {
    uniffiRustCallWithError(NimbusException) { _status ->
    UniffiLib.uniffi_nimbus_fn_method_nimbusclient_get_experiment_participation(
        it,
        _status)
}
    }
    )
    }
    

    
    @Throws(NimbusException::class)override fun `getFeatureConfigVariables`(`featureId`: kotlin.String): kotlin.String? {
            return FfiConverterOptionalString.lift(
    callWithHandle {
    uniffiRustCallWithError(NimbusException) { _status ->
    UniffiLib.uniffi_nimbus_fn_method_nimbusclient_get_feature_config_variables(
        it,
        FfiConverterString.lower(`featureId`),_status)
}
    }
    )
    }
    

    
    @Throws(NimbusException::class)override fun `getPreviousGeckoPrefStates`(`experimentSlug`: kotlin.String): List<PreviousGeckoPrefState>? {
            return FfiConverterOptionalSequenceTypePreviousGeckoPrefState.lift(
    callWithHandle {
    uniffiRustCallWithError(NimbusException) { _status ->
    UniffiLib.uniffi_nimbus_fn_method_nimbusclient_get_previous_gecko_pref_states(
        it,
        FfiConverterString.lower(`experimentSlug`),_status)
}
    }
    )
    }
    

    
    /**
     * Getter and setter for user's participation in rollouts.
     * Possible values are:
     * * `true`: the user will enroll in rollouts as usual.
     * * `false`: the user will not enroll in new rollouts, and opt out of all existing ones.
     */
    @Throws(NimbusException::class)override fun `getRolloutParticipation`(): kotlin.Boolean {
            return FfiConverterBoolean.lift(
    callWithHandle {
    uniffiRustCallWithError(NimbusException) { _status ->
    UniffiLib.uniffi_nimbus_fn_method_nimbusclient_get_rollout_participation(
        it,
        _status)
}
    }
    )
    }
    

    
    /**
     * Initializes the database and caches enough information so that the
     * non-blocking API functions (eg, `get_experiment_branch()`) can
     * return accurate results rather than throwing a "not initialized" error.
     * It's not strictly necessary to call this function - any function that
     * wants to use the database will implicitly initialize too - this exists
     * so that the consuming application can have confidence the non-blocking
     * functions will return data instead of returning an error, and will do
     * the minimum amount of work to achieve that.
     */
    @Throws(NimbusException::class)override fun `initialize`()
        = 
    callWithHandle {
    uniffiRustCallWithError(NimbusException) { _status ->
    UniffiLib.uniffi_nimbus_fn_method_nimbusclient_initialize(
        it,
        _status)
}
    }
    
    

    
    @Throws(NimbusException::class)override fun `isFetchEnabled`(): kotlin.Boolean {
            return FfiConverterBoolean.lift(
    callWithHandle {
    uniffiRustCallWithError(NimbusException) { _status ->
    UniffiLib.uniffi_nimbus_fn_method_nimbusclient_is_fetch_enabled(
        it,
        _status)
}
    }
    )
    }
    

    
    /**
     * Opt in to a specific branch on a specific experiment. Useful for
     * developers to test their app's interaction with the experiment.
     */
    @Throws(NimbusException::class)override fun `optInWithBranch`(`experimentSlug`: kotlin.String, `branch`: kotlin.String): List<EnrollmentChangeEvent> {
            return FfiConverterSequenceTypeEnrollmentChangeEvent.lift(
    callWithHandle {
    uniffiRustCallWithError(NimbusException) { _status ->
    UniffiLib.uniffi_nimbus_fn_method_nimbusclient_opt_in_with_branch(
        it,
        FfiConverterString.lower(`experimentSlug`),FfiConverterString.lower(`branch`),_status)
}
    }
    )
    }
    

    
    /**
     * Opt out of a specific experiment.
     */
    @Throws(NimbusException::class)override fun `optOut`(`experimentSlug`: kotlin.String): List<EnrollmentChangeEvent> {
            return FfiConverterSequenceTypeEnrollmentChangeEvent.lift(
    callWithHandle {
    uniffiRustCallWithError(NimbusException) { _status ->
    UniffiLib.uniffi_nimbus_fn_method_nimbusclient_opt_out(
        it,
        FfiConverterString.lower(`experimentSlug`),_status)
}
    }
    )
    }
    

    
    /**
     * Records an event for the purposes of behavioral targeting.
     * This function is used to record and persist data used for the behavioral
     * targeting such as "core-active" user targeting.
     */
    @Throws(NimbusException::class)override fun `recordEvent`(`eventId`: kotlin.String, `count`: kotlin.Long)
        = 
    callWithHandle {
    uniffiRustCallWithError(NimbusException) { _status ->
    UniffiLib.uniffi_nimbus_fn_method_nimbusclient_record_event(
        it,
        FfiConverterString.lower(`eventId`),FfiConverterLong.lower(`count`),_status)
}
    }
    
    

    
    /**
     * Records a Glean event that this feature has been exposed.
     * If the feature is not involved in an experiment, then the event is suppressed.
     * If the feature is only involved in a rollout, then the event is suppressed.
     * If the feature is involved in an experiment, then record the experiment slug
     * and branch.
     * If the feature is involved in an experiment and a rollout, then record only the
     * experiment slug and branch.
     * If the slug is specified, then use this as the experiment, and use it to look up
     * the branch. This is useful for coenrolling features.
     */override fun `recordFeatureExposure`(`featureId`: kotlin.String, `slug`: kotlin.String?)
        = 
    callWithHandle {
    uniffiRustCall() { _status ->
    UniffiLib.uniffi_nimbus_fn_method_nimbusclient_record_feature_exposure(
        it,
        FfiConverterString.lower(`featureId`),FfiConverterOptionalString.lower(`slug`),_status)
}
    }
    
    

    
    /**
     * Records a Glean event that this feature configuration is malformed.
     * Accepts a part_id to give the experiment owner or feature implementer
     * clues where to look.
     * The Glean event will always fire, but the content of that event will
     * vary depending on whether then feature is part of an experiment or rollout
     * or not.
     */override fun `recordMalformedFeatureConfig`(`featureId`: kotlin.String, `partId`: kotlin.String)
        = 
    callWithHandle {
    uniffiRustCall() { _status ->
    UniffiLib.uniffi_nimbus_fn_method_nimbusclient_record_malformed_feature_config(
        it,
        FfiConverterString.lower(`featureId`),FfiConverterString.lower(`partId`),_status)
}
    }
    
    

    
    /**
     * Records an event as if it were in the past.
     * This, and `advance_event_time` are useful for testing.
     * `seconds_ago` must be positive.
     */
    @Throws(NimbusException::class)override fun `recordPastEvent`(`eventId`: kotlin.String, `secondsAgo`: kotlin.Long, `count`: kotlin.Long)
        = 
    callWithHandle {
    uniffiRustCallWithError(NimbusException) { _status ->
    UniffiLib.uniffi_nimbus_fn_method_nimbusclient_record_past_event(
        it,
        FfiConverterString.lower(`eventId`),FfiConverterLong.lower(`secondsAgo`),FfiConverterLong.lower(`count`),_status)
}
    }
    
    

    
    @Throws(NimbusException::class)override fun `registerPreviousGeckoPrefStates`(`geckoPrefStates`: List<GeckoPrefState>)
        = 
    callWithHandle {
    uniffiRustCallWithError(NimbusException) { _status ->
    UniffiLib.uniffi_nimbus_fn_method_nimbusclient_register_previous_gecko_pref_states(
        it,
        FfiConverterSequenceTypeGeckoPrefState.lower(`geckoPrefStates`),_status)
}
    }
    
    

    
    /**
     * These are test-only functions and should never be exposed to production
     * users, as they mess with the "statistical requirements" of the SDK.
     * Reset the enrollments and experiments in the database to an empty state.
     */
    @Throws(NimbusException::class)override fun `resetEnrollments`()
        = 
    callWithHandle {
    uniffiRustCallWithError(NimbusException) { _status ->
    UniffiLib.uniffi_nimbus_fn_method_nimbusclient_reset_enrollments(
        it,
        _status)
}
    }
    
    

    
    /**
     * Reset internal state in response to application-level telemetry reset.
     *
     * Consumers should call this method when the user resets the telemetry state of the
     * consuming application, such as by opting out of submitting telemetry. It resets the
     * internal state of the Nimbus client to create a clean break between data collected
     * before and after the reset, including:
     *
     *    * clearing any unique identifiers used internally, so they will reset to
     *      new random values on next use.
     *    * accepting new randomization units, based on application-level ids that
     *      may have also changed.
     *    * disqualifying this client out of any active experiments, to avoid submitting
     *      misleading incomplete data.

     */
    @Throws(NimbusException::class)override fun `resetTelemetryIdentifiers`(): List<EnrollmentChangeEvent> {
            return FfiConverterSequenceTypeEnrollmentChangeEvent.lift(
    callWithHandle {
    uniffiRustCallWithError(NimbusException) { _status ->
    UniffiLib.uniffi_nimbus_fn_method_nimbusclient_reset_telemetry_identifiers(
        it,
        _status)
}
    }
    )
    }
    

    
    @Throws(NimbusException::class)override fun `setExperimentParticipation`(`optIn`: kotlin.Boolean): List<EnrollmentChangeEvent> {
            return FfiConverterSequenceTypeEnrollmentChangeEvent.lift(
    callWithHandle {
    uniffiRustCallWithError(NimbusException) { _status ->
    UniffiLib.uniffi_nimbus_fn_method_nimbusclient_set_experiment_participation(
        it,
        FfiConverterBoolean.lower(`optIn`),_status)
}
    }
    )
    }
    

    
    /**
     * A convenience method for apps to set the experiments from a local source
     * for either testing, or before the first fetch has finished.
     *
     * Experiments set with this method are not applied until `apply_pending_updates()` is called.
     */
    @Throws(NimbusException::class)override fun `setExperimentsLocally`(`experimentsJson`: kotlin.String)
        = 
    callWithHandle {
    uniffiRustCallWithError(NimbusException) { _status ->
    UniffiLib.uniffi_nimbus_fn_method_nimbusclient_set_experiments_locally(
        it,
        FfiConverterString.lower(`experimentsJson`),_status)
}
    }
    
    

    
    /**
     * Toggles the enablement of the fetch. If `false`, then calling `fetch_experiments`
     * returns immediately, having not done any fetching from remote settings.
     * This is only useful for QA, and should not be used in production: use
     * `set_experiment_participation` or `set_rollout_participation` instead.
     */
    @Throws(NimbusException::class)override fun `setFetchEnabled`(`flag`: kotlin.Boolean)
        = 
    callWithHandle {
    uniffiRustCallWithError(NimbusException) { _status ->
    UniffiLib.uniffi_nimbus_fn_method_nimbusclient_set_fetch_enabled(
        it,
        FfiConverterBoolean.lower(`flag`),_status)
}
    }
    
    

    
    @Throws(NimbusException::class)override fun `setRolloutParticipation`(`optIn`: kotlin.Boolean): List<EnrollmentChangeEvent> {
            return FfiConverterSequenceTypeEnrollmentChangeEvent.lift(
    callWithHandle {
    uniffiRustCallWithError(NimbusException) { _status ->
    UniffiLib.uniffi_nimbus_fn_method_nimbusclient_set_rollout_participation(
        it,
        FfiConverterBoolean.lower(`optIn`),_status)
}
    }
    )
    }
    

    
    @Throws(NimbusException::class)override fun `unenrollForGeckoPref`(`prefState`: GeckoPrefState, `prefUnenrollReason`: PrefUnenrollReason): List<EnrollmentChangeEvent> {
            return FfiConverterSequenceTypeEnrollmentChangeEvent.lift(
    callWithHandle {
    uniffiRustCallWithError(NimbusException) { _status ->
    UniffiLib.uniffi_nimbus_fn_method_nimbusclient_unenroll_for_gecko_pref(
        it,
        FfiConverterTypeGeckoPrefState.lower(`prefState`),FfiConverterTypePrefUnenrollReason.lower(`prefUnenrollReason`),_status)
}
    }
    )
    }
    

    
    @Throws(NimbusException::class)override fun `unenrollFromAllFirefoxLabs`(): List<EnrollmentChangeEvent> {
            return FfiConverterSequenceTypeEnrollmentChangeEvent.lift(
    callWithHandle {
    uniffiRustCallWithError(NimbusException) { _status ->
    UniffiLib.uniffi_nimbus_fn_method_nimbusclient_unenroll_from_all_firefox_labs(
        it,
        _status)
}
    }
    )
    }
    

    
    @Throws(NimbusException::class)override fun `unenrollFromFirefoxLab`(`slug`: kotlin.String): FirefoxLabsUnenrollResult {
            return FfiConverterTypeFirefoxLabsUnenrollResult.lift(
    callWithHandle {
    uniffiRustCallWithError(NimbusException) { _status ->
    UniffiLib.uniffi_nimbus_fn_method_nimbusclient_unenroll_from_firefox_lab(
        it,
        FfiConverterString.lower(`slug`),_status)
}
    }
    )
    }
    

    

    


    
    
    /**
     * @suppress
     */
    companion object
    
}


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

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

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

    override fun allocationSize(value: NimbusClient) = 8UL

    override fun write(value: NimbusClient, 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
//


public interface NimbusStringHelperInterface {
    
    /**
     * Generates an optional UUID to be passed into the `string_format` method.
     * If the return is not null, then it should be recorded with Glean as a UuidMetricType.
     */
    fun `getUuid`(`template`: kotlin.String): kotlin.String?
    
    /**
     * Take the given template and find patterns that match the regular expression `{\w+}`.
     * Any matches are used as keys into the application context, the `additional_context` or the special case `uuid`.
     */
    fun `stringFormat`(`template`: kotlin.String, `uuid`: kotlin.String? = null): kotlin.String
    
    companion object
}

open class NimbusStringHelper: Disposable, AutoCloseable, NimbusStringHelperInterface
{

    @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
    }

    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_nimbus_fn_free_nimbusstringhelper(handle, status)
            }
        }
    }

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

    
    /**
     * Generates an optional UUID to be passed into the `string_format` method.
     * If the return is not null, then it should be recorded with Glean as a UuidMetricType.
     */override fun `getUuid`(`template`: kotlin.String): kotlin.String? {
            return FfiConverterOptionalString.lift(
    callWithHandle {
    uniffiRustCall() { _status ->
    UniffiLib.uniffi_nimbus_fn_method_nimbusstringhelper_get_uuid(
        it,
        FfiConverterString.lower(`template`),_status)
}
    }
    )
    }
    

    
    /**
     * Take the given template and find patterns that match the regular expression `{\w+}`.
     * Any matches are used as keys into the application context, the `additional_context` or the special case `uuid`.
     */override fun `stringFormat`(`template`: kotlin.String, `uuid`: kotlin.String?): kotlin.String {
            return FfiConverterString.lift(
    callWithHandle {
    uniffiRustCall() { _status ->
    UniffiLib.uniffi_nimbus_fn_method_nimbusstringhelper_string_format(
        it,
        FfiConverterString.lower(`template`),FfiConverterOptionalString.lower(`uuid`),_status)
}
    }
    )
    }
    

    

    


    
    
    /**
     * @suppress
     */
    companion object
    
}


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

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

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

    override fun allocationSize(value: NimbusStringHelper) = 8UL

    override fun write(value: NimbusStringHelper, 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
//


public interface NimbusTargetingHelperInterface {
    
    /**
     * Execute the given jexl expression and evaluate against the existing targeting parameters and context passed to
     * the helper at construction.
     */
    fun `evalJexl`(`expression`: kotlin.String): kotlin.Boolean
    
    /**
     * Evaluate a JEXL expression and return debug results as JSON.
     * For CLI testing and debugging.
     */
    fun `evalJexlDebug`(`expression`: kotlin.String): kotlin.String
    
    companion object
}

open class NimbusTargetingHelper: Disposable, AutoCloseable, NimbusTargetingHelperInterface
{

    @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
    }

    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_nimbus_fn_free_nimbustargetinghelper(handle, status)
            }
        }
    }

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

    
    /**
     * Execute the given jexl expression and evaluate against the existing targeting parameters and context passed to
     * the helper at construction.
     */
    @Throws(NimbusException::class)override fun `evalJexl`(`expression`: kotlin.String): kotlin.Boolean {
            return FfiConverterBoolean.lift(
    callWithHandle {
    uniffiRustCallWithError(NimbusException) { _status ->
    UniffiLib.uniffi_nimbus_fn_method_nimbustargetinghelper_eval_jexl(
        it,
        FfiConverterString.lower(`expression`),_status)
}
    }
    )
    }
    

    
    /**
     * Evaluate a JEXL expression and return debug results as JSON.
     * For CLI testing and debugging.
     */
    @Throws(NimbusException::class)override fun `evalJexlDebug`(`expression`: kotlin.String): kotlin.String {
            return FfiConverterString.lift(
    callWithHandle {
    uniffiRustCallWithError(NimbusException) { _status ->
    UniffiLib.uniffi_nimbus_fn_method_nimbustargetinghelper_eval_jexl_debug(
        it,
        FfiConverterString.lower(`expression`),_status)
}
    }
    )
    }
    

    

    


    
    
    /**
     * @suppress
     */
    companion object
    
}


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

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

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

    override fun allocationSize(value: NimbusTargetingHelper) = 8UL

    override fun write(value: NimbusTargetingHelper, 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
//


public interface RecordedContext {
    
    fun `getEventQueries`(): Map<kotlin.String, kotlin.String>
    
    fun `record`()
    
    fun `setEventQueryValues`(`eventQueryValues`: Map<kotlin.String, kotlin.Double>)
    
    fun `toJson`(): JsonObject
    
    companion object
}

open class RecordedContextImpl: Disposable, AutoCloseable, RecordedContext
{

    @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
    }

    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_nimbus_fn_free_recordedcontext(handle, status)
            }
        }
    }

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

    override fun `getEventQueries`(): Map<kotlin.String, kotlin.String> {
            return FfiConverterMapStringString.lift(
    callWithHandle {
    uniffiRustCall() { _status ->
    UniffiLib.uniffi_nimbus_fn_method_recordedcontext_get_event_queries(
        it,
        _status)
}
    }
    )
    }
    

    override fun `record`()
        = 
    callWithHandle {
    uniffiRustCall() { _status ->
    UniffiLib.uniffi_nimbus_fn_method_recordedcontext_record(
        it,
        _status)
}
    }
    
    

    override fun `setEventQueryValues`(`eventQueryValues`: Map<kotlin.String, kotlin.Double>)
        = 
    callWithHandle {
    uniffiRustCall() { _status ->
    UniffiLib.uniffi_nimbus_fn_method_recordedcontext_set_event_query_values(
        it,
        FfiConverterMapStringDouble.lower(`eventQueryValues`),_status)
}
    }
    
    

    override fun `toJson`(): JsonObject {
            return FfiConverterTypeJsonObject.lift(
    callWithHandle {
    uniffiRustCall() { _status ->
    UniffiLib.uniffi_nimbus_fn_method_recordedcontext_to_json(
        it,
        _status)
}
    }
    )
    }
    

    

    


    
    
    /**
     * @suppress
     */
    companion object
    
}



// Put the implementation in an object so we don't pollute the top-level namespace
internal object uniffiCallbackInterfaceRecordedContext {
    internal object `getEventQueries`: UniffiCallbackInterfaceRecordedContextMethod0 {
        override fun callback(`uniffiHandle`: Long,`uniffiOutReturn`: RustBuffer,uniffiCallStatus: UniffiRustCallStatus,) {
            val uniffiObj = FfiConverterTypeRecordedContext.handleMap.get(uniffiHandle)
            val makeCall = { ->
                uniffiObj.`getEventQueries`(
                )
            }
            val writeReturn = { value: Map<kotlin.String, kotlin.String> -> uniffiOutReturn.setValue(FfiConverterMapStringString.lower(value)) }
            uniffiTraitInterfaceCall(uniffiCallStatus, makeCall, writeReturn)
        }
    }
    internal object `record`: UniffiCallbackInterfaceRecordedContextMethod1 {
        override fun callback(`uniffiHandle`: Long,`uniffiOutReturn`: Pointer,uniffiCallStatus: UniffiRustCallStatus,) {
            val uniffiObj = FfiConverterTypeRecordedContext.handleMap.get(uniffiHandle)
            val makeCall = { ->
                uniffiObj.`record`(
                )
            }
            val writeReturn = { _: Unit -> Unit }
            uniffiTraitInterfaceCall(uniffiCallStatus, makeCall, writeReturn)
        }
    }
    internal object `setEventQueryValues`: UniffiCallbackInterfaceRecordedContextMethod2 {
        override fun callback(`uniffiHandle`: Long,`eventQueryValues`: RustBuffer.ByValue,`uniffiOutReturn`: Pointer,uniffiCallStatus: UniffiRustCallStatus,) {
            val uniffiObj = FfiConverterTypeRecordedContext.handleMap.get(uniffiHandle)
            val makeCall = { ->
                uniffiObj.`setEventQueryValues`(
                    FfiConverterMapStringDouble.lift(`eventQueryValues`),
                )
            }
            val writeReturn = { _: Unit -> Unit }
            uniffiTraitInterfaceCall(uniffiCallStatus, makeCall, writeReturn)
        }
    }
    internal object `toJson`: UniffiCallbackInterfaceRecordedContextMethod3 {
        override fun callback(`uniffiHandle`: Long,`uniffiOutReturn`: RustBuffer,uniffiCallStatus: UniffiRustCallStatus,) {
            val uniffiObj = FfiConverterTypeRecordedContext.handleMap.get(uniffiHandle)
            val makeCall = { ->
                uniffiObj.`toJson`(
                )
            }
            val writeReturn = { value: JsonObject -> uniffiOutReturn.setValue(FfiConverterTypeJsonObject.lower(value)) }
            uniffiTraitInterfaceCall(uniffiCallStatus, makeCall, writeReturn)
        }
    }

    internal object uniffiFree: UniffiCallbackInterfaceFree {
        override fun callback(handle: Long) {
            FfiConverterTypeRecordedContext.handleMap.remove(handle)
        }
    }

    internal object uniffiClone: UniffiCallbackInterfaceClone {
        override fun callback(handle: Long): Long {
            return FfiConverterTypeRecordedContext.handleMap.clone(handle)
        }
    }

    internal var vtable = UniffiVTableCallbackInterfaceRecordedContext.UniffiByValue(
        uniffiFree,
        uniffiClone,
        `getEventQueries`,
        `record`,
        `setEventQueryValues`,
        `toJson`,
    )

    // Registers the foreign callback with the Rust side.
    // This method is generated for each callback interface.
    internal fun register(lib: UniffiLib) {
        lib.uniffi_nimbus_fn_init_callback_vtable_recordedcontext(vtable)
    }
}

/**
 * @suppress
 */
public object FfiConverterTypeRecordedContext: FfiConverter<RecordedContext, Long> {
    internal val handleMap = UniffiHandleMap<RecordedContext>()

    override fun lower(value: RecordedContext): Long {
        if (value is RecordedContextImpl) {
             // Rust-implemented object.  Clone the handle and return it
            return value.uniffiCloneHandle()
         } else {
            // Kotlin object, generate a new vtable handle and return that.
            return handleMap.insert(value)
         }
    }

    override fun lift(value: Long): RecordedContext {
        if ((value and 1.toLong()) == 0.toLong()) {
            // Rust-generated handle, construct a new class that uses the handle to implement the
            // interface
            return RecordedContextImpl(UniffiWithHandle, value)
        } else {
            // Kotlin-generated handle, get the object from the handle map
            return handleMap.remove(value)
        }
    }

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

    override fun allocationSize(value: RecordedContext) = 8UL

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



data class AppContext (
    var `appName`: kotlin.String
    , 
    var `appId`: kotlin.String
    , 
    var `channel`: kotlin.String
    , 
    var `appVersion`: kotlin.String?
    , 
    var `appBuild`: kotlin.String?
    , 
    var `architecture`: kotlin.String?
    , 
    var `deviceManufacturer`: kotlin.String?
    , 
    var `deviceModel`: kotlin.String?
    , 
    var `locale`: kotlin.String?
    , 
    var `os`: kotlin.String?
    , 
    var `osVersion`: kotlin.String?
    , 
    var `androidSdkVersion`: kotlin.String?
    , 
    var `debugTag`: kotlin.String?
    , 
    var `installationDate`: kotlin.Long?
    , 
    var `customTargetingAttributes`: JsonObject?
    
){
    

    

    
    companion object
}

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

    override fun allocationSize(value: AppContext) = (
            FfiConverterString.allocationSize(value.`appName`) +
            FfiConverterString.allocationSize(value.`appId`) +
            FfiConverterString.allocationSize(value.`channel`) +
            FfiConverterOptionalString.allocationSize(value.`appVersion`) +
            FfiConverterOptionalString.allocationSize(value.`appBuild`) +
            FfiConverterOptionalString.allocationSize(value.`architecture`) +
            FfiConverterOptionalString.allocationSize(value.`deviceManufacturer`) +
            FfiConverterOptionalString.allocationSize(value.`deviceModel`) +
            FfiConverterOptionalString.allocationSize(value.`locale`) +
            FfiConverterOptionalString.allocationSize(value.`os`) +
            FfiConverterOptionalString.allocationSize(value.`osVersion`) +
            FfiConverterOptionalString.allocationSize(value.`androidSdkVersion`) +
            FfiConverterOptionalString.allocationSize(value.`debugTag`) +
            FfiConverterOptionalLong.allocationSize(value.`installationDate`) +
            FfiConverterOptionalTypeJsonObject.allocationSize(value.`customTargetingAttributes`)
    )

    override fun write(value: AppContext, buf: ByteBuffer) {
            FfiConverterString.write(value.`appName`, buf)
            FfiConverterString.write(value.`appId`, buf)
            FfiConverterString.write(value.`channel`, buf)
            FfiConverterOptionalString.write(value.`appVersion`, buf)
            FfiConverterOptionalString.write(value.`appBuild`, buf)
            FfiConverterOptionalString.write(value.`architecture`, buf)
            FfiConverterOptionalString.write(value.`deviceManufacturer`, buf)
            FfiConverterOptionalString.write(value.`deviceModel`, buf)
            FfiConverterOptionalString.write(value.`locale`, buf)
            FfiConverterOptionalString.write(value.`os`, buf)
            FfiConverterOptionalString.write(value.`osVersion`, buf)
            FfiConverterOptionalString.write(value.`androidSdkVersion`, buf)
            FfiConverterOptionalString.write(value.`debugTag`, buf)
            FfiConverterOptionalLong.write(value.`installationDate`, buf)
            FfiConverterOptionalTypeJsonObject.write(value.`customTargetingAttributes`, buf)
    }
}



data class AvailableExperiment (
    var `slug`: kotlin.String
    , 
    var `userFacingName`: kotlin.String
    , 
    var `userFacingDescription`: kotlin.String
    , 
    var `branches`: List<ExperimentBranch>
    , 
    var `referenceBranch`: kotlin.String?
    
){
    

    

    
    companion object
}

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

    override fun allocationSize(value: AvailableExperiment) = (
            FfiConverterString.allocationSize(value.`slug`) +
            FfiConverterString.allocationSize(value.`userFacingName`) +
            FfiConverterString.allocationSize(value.`userFacingDescription`) +
            FfiConverterSequenceTypeExperimentBranch.allocationSize(value.`branches`) +
            FfiConverterOptionalString.allocationSize(value.`referenceBranch`)
    )

    override fun write(value: AvailableExperiment, buf: ByteBuffer) {
            FfiConverterString.write(value.`slug`, buf)
            FfiConverterString.write(value.`userFacingName`, buf)
            FfiConverterString.write(value.`userFacingDescription`, buf)
            FfiConverterSequenceTypeExperimentBranch.write(value.`branches`, buf)
            FfiConverterOptionalString.write(value.`referenceBranch`, buf)
    }
}



data class CalculatedAttributes (
    var `daysSinceInstall`: kotlin.Int?
    , 
    var `daysSinceUpdate`: kotlin.Int?
    , 
    var `language`: kotlin.String?
    , 
    var `region`: kotlin.String?
    
){
    

    

    
    companion object
}

/**
 * @suppress
 */
public object FfiConverterTypeCalculatedAttributes: FfiConverterRustBuffer<CalculatedAttributes> {
    override fun read(buf: ByteBuffer): CalculatedAttributes {
        return CalculatedAttributes(
            FfiConverterOptionalInt.read(buf),
            FfiConverterOptionalInt.read(buf),
            FfiConverterOptionalString.read(buf),
            FfiConverterOptionalString.read(buf),
        )
    }

    override fun allocationSize(value: CalculatedAttributes) = (
            FfiConverterOptionalInt.allocationSize(value.`daysSinceInstall`) +
            FfiConverterOptionalInt.allocationSize(value.`daysSinceUpdate`) +
            FfiConverterOptionalString.allocationSize(value.`language`) +
            FfiConverterOptionalString.allocationSize(value.`region`)
    )

    override fun write(value: CalculatedAttributes, buf: ByteBuffer) {
            FfiConverterOptionalInt.write(value.`daysSinceInstall`, buf)
            FfiConverterOptionalInt.write(value.`daysSinceUpdate`, buf)
            FfiConverterOptionalString.write(value.`language`, buf)
            FfiConverterOptionalString.write(value.`region`, buf)
    }
}



data class DatabaseLoadExtraDef (
    var `corrupt`: kotlin.Boolean?
    , 
    var `error`: kotlin.String?
    , 
    var `initialVersion`: kotlin.UShort?
    , 
    var `migratedVersion`: kotlin.UShort?
    , 
    var `migrationError`: kotlin.String?
    
){
    

    

    
    companion object
}

/**
 * @suppress
 */
public object FfiConverterTypeDatabaseLoadExtraDef: FfiConverterRustBuffer<DatabaseLoadExtraDef> {
    override fun read(buf: ByteBuffer): DatabaseLoadExtraDef {
        return DatabaseLoadExtraDef(
            FfiConverterOptionalBoolean.read(buf),
            FfiConverterOptionalString.read(buf),
            FfiConverterOptionalUShort.read(buf),
            FfiConverterOptionalUShort.read(buf),
            FfiConverterOptionalString.read(buf),
        )
    }

    override fun allocationSize(value: DatabaseLoadExtraDef) = (
            FfiConverterOptionalBoolean.allocationSize(value.`corrupt`) +
            FfiConverterOptionalString.allocationSize(value.`error`) +
            FfiConverterOptionalUShort.allocationSize(value.`initialVersion`) +
            FfiConverterOptionalUShort.allocationSize(value.`migratedVersion`) +
            FfiConverterOptionalString.allocationSize(value.`migrationError`)
    )

    override fun write(value: DatabaseLoadExtraDef, buf: ByteBuffer) {
            FfiConverterOptionalBoolean.write(value.`corrupt`, buf)
            FfiConverterOptionalString.write(value.`error`, buf)
            FfiConverterOptionalUShort.write(value.`initialVersion`, buf)
            FfiConverterOptionalUShort.write(value.`migratedVersion`, buf)
            FfiConverterOptionalString.write(value.`migrationError`, buf)
    }
}



data class DatabaseMigrationExtraDef (
    var `reason`: kotlin.String
    , 
    var `fromVersion`: kotlin.UShort
    , 
    var `toVersion`: kotlin.UShort
    , 
    var `error`: kotlin.String?
    
){
    

    

    
    companion object
}

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

    override fun allocationSize(value: DatabaseMigrationExtraDef) = (
            FfiConverterString.allocationSize(value.`reason`) +
            FfiConverterUShort.allocationSize(value.`fromVersion`) +
            FfiConverterUShort.allocationSize(value.`toVersion`) +
            FfiConverterOptionalString.allocationSize(value.`error`)
    )

    override fun write(value: DatabaseMigrationExtraDef, buf: ByteBuffer) {
            FfiConverterString.write(value.`reason`, buf)
            FfiConverterUShort.write(value.`fromVersion`, buf)
            FfiConverterUShort.write(value.`toVersion`, buf)
            FfiConverterOptionalString.write(value.`error`, buf)
    }
}



data class EnrolledExperiment (
    var `featureIds`: List<kotlin.String>
    , 
    var `slug`: kotlin.String
    , 
    var `userFacingName`: kotlin.String
    , 
    var `userFacingDescription`: kotlin.String
    , 
    var `branchSlug`: kotlin.String
    , 
    var `isRollout`: kotlin.Boolean
    
){
    

    

    
    companion object
}

/**
 * @suppress
 */
public object FfiConverterTypeEnrolledExperiment: FfiConverterRustBuffer<EnrolledExperiment> {
    override fun read(buf: ByteBuffer): EnrolledExperiment {
        return EnrolledExperiment(
            FfiConverterSequenceString.read(buf),
            FfiConverterString.read(buf),
            FfiConverterString.read(buf),
            FfiConverterString.read(buf),
            FfiConverterString.read(buf),
            FfiConverterBoolean.read(buf),
        )
    }

    override fun allocationSize(value: EnrolledExperiment) = (
            FfiConverterSequenceString.allocationSize(value.`featureIds`) +
            FfiConverterString.allocationSize(value.`slug`) +
            FfiConverterString.allocationSize(value.`userFacingName`) +
            FfiConverterString.allocationSize(value.`userFacingDescription`) +
            FfiConverterString.allocationSize(value.`branchSlug`) +
            FfiConverterBoolean.allocationSize(value.`isRollout`)
    )

    override fun write(value: EnrolledExperiment, buf: ByteBuffer) {
            FfiConverterSequenceString.write(value.`featureIds`, buf)
            FfiConverterString.write(value.`slug`, buf)
            FfiConverterString.write(value.`userFacingName`, buf)
            FfiConverterString.write(value.`userFacingDescription`, buf)
            FfiConverterString.write(value.`branchSlug`, buf)
            FfiConverterBoolean.write(value.`isRollout`, buf)
    }
}



data class EnrollmentChangeEvent (
    var `experimentSlug`: kotlin.String
    , 
    var `branchSlug`: kotlin.String
    , 
    var `reason`: kotlin.String?
    , 
    var `change`: EnrollmentChangeEventType
    , 
    var `featureIds`: List<kotlin.String>
    
){
    

    

    
    companion object
}

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

    override fun allocationSize(value: EnrollmentChangeEvent) = (
            FfiConverterString.allocationSize(value.`experimentSlug`) +
            FfiConverterString.allocationSize(value.`branchSlug`) +
            FfiConverterOptionalString.allocationSize(value.`reason`) +
            FfiConverterTypeEnrollmentChangeEventType.allocationSize(value.`change`) +
            FfiConverterSequenceString.allocationSize(value.`featureIds`)
    )

    override fun write(value: EnrollmentChangeEvent, buf: ByteBuffer) {
            FfiConverterString.write(value.`experimentSlug`, buf)
            FfiConverterString.write(value.`branchSlug`, buf)
            FfiConverterOptionalString.write(value.`reason`, buf)
            FfiConverterTypeEnrollmentChangeEventType.write(value.`change`, buf)
            FfiConverterSequenceString.write(value.`featureIds`, buf)
    }
}



data class EnrollmentStatusExtraDef (
    var `branch`: kotlin.String?
    , 
    var `conflictSlug`: kotlin.String?
    , 
    var `errorString`: kotlin.String?
    , 
    var `reason`: kotlin.String?
    , 
    var `slug`: kotlin.String?
    , 
    var `status`: kotlin.String?
    , 
    var `prevGeckoPrefStates`: List<PreviousGeckoPrefState>?
    
){
    

    

    
    companion object
}

/**
 * @suppress
 */
public object FfiConverterTypeEnrollmentStatusExtraDef: FfiConverterRustBuffer<EnrollmentStatusExtraDef> {
    override fun read(buf: ByteBuffer): EnrollmentStatusExtraDef {
        return EnrollmentStatusExtraDef(
            FfiConverterOptionalString.read(buf),
            FfiConverterOptionalString.read(buf),
            FfiConverterOptionalString.read(buf),
            FfiConverterOptionalString.read(buf),
            FfiConverterOptionalString.read(buf),
            FfiConverterOptionalString.read(buf),
            FfiConverterOptionalSequenceTypePreviousGeckoPrefState.read(buf),
        )
    }

    override fun allocationSize(value: EnrollmentStatusExtraDef) = (
            FfiConverterOptionalString.allocationSize(value.`branch`) +
            FfiConverterOptionalString.allocationSize(value.`conflictSlug`) +
            FfiConverterOptionalString.allocationSize(value.`errorString`) +
            FfiConverterOptionalString.allocationSize(value.`reason`) +
            FfiConverterOptionalString.allocationSize(value.`slug`) +
            FfiConverterOptionalString.allocationSize(value.`status`) +
            FfiConverterOptionalSequenceTypePreviousGeckoPrefState.allocationSize(value.`prevGeckoPrefStates`)
    )

    override fun write(value: EnrollmentStatusExtraDef, buf: ByteBuffer) {
            FfiConverterOptionalString.write(value.`branch`, buf)
            FfiConverterOptionalString.write(value.`conflictSlug`, buf)
            FfiConverterOptionalString.write(value.`errorString`, buf)
            FfiConverterOptionalString.write(value.`reason`, buf)
            FfiConverterOptionalString.write(value.`slug`, buf)
            FfiConverterOptionalString.write(value.`status`, buf)
            FfiConverterOptionalSequenceTypePreviousGeckoPrefState.write(value.`prevGeckoPrefStates`, buf)
    }
}



data class ExperimentBranch (
    var `slug`: kotlin.String
    , 
    var `ratio`: kotlin.Int
    
){
    

    

    
    companion object
}

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

    override fun allocationSize(value: ExperimentBranch) = (
            FfiConverterString.allocationSize(value.`slug`) +
            FfiConverterInt.allocationSize(value.`ratio`)
    )

    override fun write(value: ExperimentBranch, buf: ByteBuffer) {
            FfiConverterString.write(value.`slug`, buf)
            FfiConverterInt.write(value.`ratio`, buf)
    }
}



data class FeatureExposureExtraDef (
    var `branch`: kotlin.String?
    , 
    var `slug`: kotlin.String
    , 
    var `featureId`: kotlin.String
    
){
    

    

    
    companion object
}

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

    override fun allocationSize(value: FeatureExposureExtraDef) = (
            FfiConverterOptionalString.allocationSize(value.`branch`) +
            FfiConverterString.allocationSize(value.`slug`) +
            FfiConverterString.allocationSize(value.`featureId`)
    )

    override fun write(value: FeatureExposureExtraDef, buf: ByteBuffer) {
            FfiConverterOptionalString.write(value.`branch`, buf)
            FfiConverterString.write(value.`slug`, buf)
            FfiConverterString.write(value.`featureId`, buf)
    }
}



data class FirefoxLabsEnrollResult (
    var `status`: FirefoxLabsEnrollStatus
    , 
    var `enrollmentChangeEvents`: List<EnrollmentChangeEvent>
    
){
    

    

    
    companion object
}

/**
 * @suppress
 */
public object FfiConverterTypeFirefoxLabsEnrollResult: FfiConverterRustBuffer<FirefoxLabsEnrollResult> {
    override fun read(buf: ByteBuffer): FirefoxLabsEnrollResult {
        return FirefoxLabsEnrollResult(
            FfiConverterTypeFirefoxLabsEnrollStatus.read(buf),
            FfiConverterSequenceTypeEnrollmentChangeEvent.read(buf),
        )
    }

    override fun allocationSize(value: FirefoxLabsEnrollResult) = (
            FfiConverterTypeFirefoxLabsEnrollStatus.allocationSize(value.`status`) +
            FfiConverterSequenceTypeEnrollmentChangeEvent.allocationSize(value.`enrollmentChangeEvents`)
    )

    override fun write(value: FirefoxLabsEnrollResult, buf: ByteBuffer) {
            FfiConverterTypeFirefoxLabsEnrollStatus.write(value.`status`, buf)
            FfiConverterSequenceTypeEnrollmentChangeEvent.write(value.`enrollmentChangeEvents`, buf)
    }
}



data class FirefoxLabsMetadata (
    var `slug`: kotlin.String
    , 
    var `enrolled`: kotlin.Boolean
    , 
    var `titleStringId`: kotlin.String
    , 
    var `descriptionStringId`: kotlin.String
    , 
    var `requiresRestart`: kotlin.Boolean
    , 
    var `feedbackUrl`: kotlin.String?
    
){
    

    

    
    companion object
}

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

    override fun allocationSize(value: FirefoxLabsMetadata) = (
            FfiConverterString.allocationSize(value.`slug`) +
            FfiConverterBoolean.allocationSize(value.`enrolled`) +
            FfiConverterString.allocationSize(value.`titleStringId`) +
            FfiConverterString.allocationSize(value.`descriptionStringId`) +
            FfiConverterBoolean.allocationSize(value.`requiresRestart`) +
            FfiConverterOptionalString.allocationSize(value.`feedbackUrl`)
    )

    override fun write(value: FirefoxLabsMetadata, buf: ByteBuffer) {
            FfiConverterString.write(value.`slug`, buf)
            FfiConverterBoolean.write(value.`enrolled`, buf)
            FfiConverterString.write(value.`titleStringId`, buf)
            FfiConverterString.write(value.`descriptionStringId`, buf)
            FfiConverterBoolean.write(value.`requiresRestart`, buf)
            FfiConverterOptionalString.write(value.`feedbackUrl`, buf)
    }
}



data class FirefoxLabsUnenrollResult (
    var `status`: FirefoxLabsUnenrollStatus
    , 
    var `enrollmentChangeEvents`: List<EnrollmentChangeEvent>
    
){
    

    

    
    companion object
}

/**
 * @suppress
 */
public object FfiConverterTypeFirefoxLabsUnenrollResult: FfiConverterRustBuffer<FirefoxLabsUnenrollResult> {
    override fun read(buf: ByteBuffer): FirefoxLabsUnenrollResult {
        return FirefoxLabsUnenrollResult(
            FfiConverterTypeFirefoxLabsUnenrollStatus.read(buf),
            FfiConverterSequenceTypeEnrollmentChangeEvent.read(buf),
        )
    }

    override fun allocationSize(value: FirefoxLabsUnenrollResult) = (
            FfiConverterTypeFirefoxLabsUnenrollStatus.allocationSize(value.`status`) +
            FfiConverterSequenceTypeEnrollmentChangeEvent.allocationSize(value.`enrollmentChangeEvents`)
    )

    override fun write(value: FirefoxLabsUnenrollResult, buf: ByteBuffer) {
            FfiConverterTypeFirefoxLabsUnenrollStatus.write(value.`status`, buf)
            FfiConverterSequenceTypeEnrollmentChangeEvent.write(value.`enrollmentChangeEvents`, buf)
    }
}



data class GeckoPref (
    var `pref`: kotlin.String
    , 
    var `branch`: PrefBranch
    
){
    

    

    
    companion object
}

/**
 * @suppress
 */
public object FfiConverterTypeGeckoPref: FfiConverterRustBuffer<GeckoPref> {
    override fun read(buf: ByteBuffer): GeckoPref {
        return GeckoPref(
            FfiConverterString.read(buf),
            FfiConverterTypePrefBranch.read(buf),
        )
    }

    override fun allocationSize(value: GeckoPref) = (
            FfiConverterString.allocationSize(value.`pref`) +
            FfiConverterTypePrefBranch.allocationSize(value.`branch`)
    )

    override fun write(value: GeckoPref, buf: ByteBuffer) {
            FfiConverterString.write(value.`pref`, buf)
            FfiConverterTypePrefBranch.write(value.`branch`, buf)
    }
}



data class GeckoPrefState (
    var `geckoPref`: GeckoPref
    , 
    var `geckoValue`: PrefValue?
    , 
    var `enrollmentValue`: PrefEnrollmentData?
    , 
    var `isUserSet`: kotlin.Boolean
    
){
    

    

    
    companion object
}

/**
 * @suppress
 */
public object FfiConverterTypeGeckoPrefState: FfiConverterRustBuffer<GeckoPrefState> {
    override fun read(buf: ByteBuffer): GeckoPrefState {
        return GeckoPrefState(
            FfiConverterTypeGeckoPref.read(buf),
            FfiConverterOptionalTypePrefValue.read(buf),
            FfiConverterOptionalTypePrefEnrollmentData.read(buf),
            FfiConverterBoolean.read(buf),
        )
    }

    override fun allocationSize(value: GeckoPrefState) = (
            FfiConverterTypeGeckoPref.allocationSize(value.`geckoPref`) +
            FfiConverterOptionalTypePrefValue.allocationSize(value.`geckoValue`) +
            FfiConverterOptionalTypePrefEnrollmentData.allocationSize(value.`enrollmentValue`) +
            FfiConverterBoolean.allocationSize(value.`isUserSet`)
    )

    override fun write(value: GeckoPrefState, buf: ByteBuffer) {
            FfiConverterTypeGeckoPref.write(value.`geckoPref`, buf)
            FfiConverterOptionalTypePrefValue.write(value.`geckoValue`, buf)
            FfiConverterOptionalTypePrefEnrollmentData.write(value.`enrollmentValue`, buf)
            FfiConverterBoolean.write(value.`isUserSet`, buf)
    }
}



data class MalformedFeatureConfigExtraDef (
    var `branch`: kotlin.String?
    , 
    var `slug`: kotlin.String?
    , 
    var `featureId`: kotlin.String
    , 
    var `part`: kotlin.String
    
){
    

    

    
    companion object
}

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

    override fun allocationSize(value: MalformedFeatureConfigExtraDef) = (
            FfiConverterOptionalString.allocationSize(value.`branch`) +
            FfiConverterOptionalString.allocationSize(value.`slug`) +
            FfiConverterString.allocationSize(value.`featureId`) +
            FfiConverterString.allocationSize(value.`part`)
    )

    override fun write(value: MalformedFeatureConfigExtraDef, buf: ByteBuffer) {
            FfiConverterOptionalString.write(value.`branch`, buf)
            FfiConverterOptionalString.write(value.`slug`, buf)
            FfiConverterString.write(value.`featureId`, buf)
            FfiConverterString.write(value.`part`, buf)
    }
}



data class NimbusServerSettings (
    var `rsService`: RemoteSettingsService
    , 
    var `collectionName`: kotlin.String
    
): Disposable{
    

    

    
    @Suppress("UNNECESSARY_SAFE_CALL") // codegen is much simpler if we unconditionally emit safe calls here
    override fun destroy() {
        
    Disposable.destroy(
        this.`rsService`,
        this.`collectionName`
    )
    }
    
    companion object
}

/**
 * @suppress
 */
public object FfiConverterTypeNimbusServerSettings: FfiConverterRustBuffer<NimbusServerSettings> {
    override fun read(buf: ByteBuffer): NimbusServerSettings {
        return NimbusServerSettings(
            FfiConverterTypeRemoteSettingsService.read(buf),
            FfiConverterString.read(buf),
        )
    }

    override fun allocationSize(value: NimbusServerSettings) = (
            FfiConverterTypeRemoteSettingsService.allocationSize(value.`rsService`) +
            FfiConverterString.allocationSize(value.`collectionName`)
    )

    override fun write(value: NimbusServerSettings, buf: ByteBuffer) {
            FfiConverterTypeRemoteSettingsService.write(value.`rsService`, buf)
            FfiConverterString.write(value.`collectionName`, buf)
    }
}



data class OriginalGeckoPref (
    var `pref`: kotlin.String
    , 
    var `branch`: PrefBranch
    , 
    var `value`: PrefValue?
    
){
    

    

    
    companion object
}

/**
 * @suppress
 */
public object FfiConverterTypeOriginalGeckoPref: FfiConverterRustBuffer<OriginalGeckoPref> {
    override fun read(buf: ByteBuffer): OriginalGeckoPref {
        return OriginalGeckoPref(
            FfiConverterString.read(buf),
            FfiConverterTypePrefBranch.read(buf),
            FfiConverterOptionalTypePrefValue.read(buf),
        )
    }

    override fun allocationSize(value: OriginalGeckoPref) = (
            FfiConverterString.allocationSize(value.`pref`) +
            FfiConverterTypePrefBranch.allocationSize(value.`branch`) +
            FfiConverterOptionalTypePrefValue.allocationSize(value.`value`)
    )

    override fun write(value: OriginalGeckoPref, buf: ByteBuffer) {
            FfiConverterString.write(value.`pref`, buf)
            FfiConverterTypePrefBranch.write(value.`branch`, buf)
            FfiConverterOptionalTypePrefValue.write(value.`value`, buf)
    }
}



data class PrefEnrollmentData (
    var `experimentSlug`: kotlin.String
    , 
    var `prefValue`: PrefValue
    , 
    var `featureId`: kotlin.String
    , 
    var `variable`: kotlin.String
    
){
    

    

    
    companion object
}

/**
 * @suppress
 */
public object FfiConverterTypePrefEnrollmentData: FfiConverterRustBuffer<PrefEnrollmentData> {
    override fun read(buf: ByteBuffer): PrefEnrollmentData {
        return PrefEnrollmentData(
            FfiConverterString.read(buf),
            FfiConverterTypePrefValue.read(buf),
            FfiConverterString.read(buf),
            FfiConverterString.read(buf),
        )
    }

    override fun allocationSize(value: PrefEnrollmentData) = (
            FfiConverterString.allocationSize(value.`experimentSlug`) +
            FfiConverterTypePrefValue.allocationSize(value.`prefValue`) +
            FfiConverterString.allocationSize(value.`featureId`) +
            FfiConverterString.allocationSize(value.`variable`)
    )

    override fun write(value: PrefEnrollmentData, buf: ByteBuffer) {
            FfiConverterString.write(value.`experimentSlug`, buf)
            FfiConverterTypePrefValue.write(value.`prefValue`, buf)
            FfiConverterString.write(value.`featureId`, buf)
            FfiConverterString.write(value.`variable`, buf)
    }
}



data class PreviousGeckoPrefState (
    var `originalValue`: OriginalGeckoPref
    , 
    var `featureId`: kotlin.String
    , 
    var `variable`: kotlin.String
    
){
    

    

    
    companion object
}

/**
 * @suppress
 */
public object FfiConverterTypePreviousGeckoPrefState: FfiConverterRustBuffer<PreviousGeckoPrefState> {
    override fun read(buf: ByteBuffer): PreviousGeckoPrefState {
        return PreviousGeckoPrefState(
            FfiConverterTypeOriginalGeckoPref.read(buf),
            FfiConverterString.read(buf),
            FfiConverterString.read(buf),
        )
    }

    override fun allocationSize(value: PreviousGeckoPrefState) = (
            FfiConverterTypeOriginalGeckoPref.allocationSize(value.`originalValue`) +
            FfiConverterString.allocationSize(value.`featureId`) +
            FfiConverterString.allocationSize(value.`variable`)
    )

    override fun write(value: PreviousGeckoPrefState, buf: ByteBuffer) {
            FfiConverterTypeOriginalGeckoPref.write(value.`originalValue`, buf)
            FfiConverterString.write(value.`featureId`, buf)
            FfiConverterString.write(value.`variable`, buf)
    }
}




enum class EnrollmentChangeEventType {
    
    ENROLLMENT,
    ENROLL_FAILED,
    DISQUALIFICATION,
    UNENROLLMENT,
    UNENROLL_FAILED;

    


    companion object
}


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

    override fun allocationSize(value: EnrollmentChangeEventType) = 4UL

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






enum class FirefoxLabsEnrollStatus {
    
    ENROLLED,
    ALREADY_ENROLLED,
    NO_EXPERIMENT,
    NOT_FIREFOX_LABS_OPT_IN,
    FEATURE_CONFLICT,
    ERROR;

    


    companion object
}


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

    override fun allocationSize(value: FirefoxLabsEnrollStatus) = 4UL

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






enum class FirefoxLabsUnenrollStatus {
    
    UNENROLLED,
    ALREADY_UNENROLLED,
    NO_EXPERIMENT,
    NOT_FIREFOX_LABS_OPT_IN,
    ERROR;

    


    companion object
}


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

    override fun allocationSize(value: FirefoxLabsUnenrollStatus) = 4UL

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







sealed class NimbusException(message: String): kotlin.Exception(message) {
        
        class InvalidPersistedData(message: String) : NimbusException(message)
        
        class RkvException(message: String) : NimbusException(message)
        
        class IoException(message: String) : NimbusException(message)
        
        class JsonException(message: String) : NimbusException(message)
        
        class EvaluationException(message: String) : NimbusException(message)
        
        class InvalidExpression(message: String) : NimbusException(message)
        
        class InvalidFraction(message: String) : NimbusException(message)
        
        class TryFromSliceException(message: String) : NimbusException(message)
        
        class EmptyRatiosException(message: String) : NimbusException(message)
        
        class OutOfBoundsException(message: String) : NimbusException(message)
        
        class UrlParsingException(message: String) : NimbusException(message)
        
        class UuidException(message: String) : NimbusException(message)
        
        class InvalidExperimentFormat(message: String) : NimbusException(message)
        
        class InvalidPath(message: String) : NimbusException(message)
        
        class InternalException(message: String) : NimbusException(message)
        
        class NoSuchExperiment(message: String) : NimbusException(message)
        
        class NoSuchBranch(message: String) : NimbusException(message)
        
        class DatabaseNotReady(message: String) : NimbusException(message)
        
        class VersionParsingException(message: String) : NimbusException(message)
        
        class BehaviorException(message: String) : NimbusException(message)
        
        class TryFromIntException(message: String) : NimbusException(message)
        
        class ParseIntException(message: String) : NimbusException(message)
        
        class TransformParameterException(message: String) : NimbusException(message)
        
        class ClientException(message: String) : NimbusException(message)
        
        class UniFfiCallbackException(message: String) : NimbusException(message)
        
        class RegexException(message: String) : NimbusException(message)
        

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

/**
 * @suppress
 */
public object FfiConverterTypeNimbusError : FfiConverterRustBuffer<NimbusException> {
    override fun read(buf: ByteBuffer): NimbusException {
        
            return when(buf.getInt()) {
            1 -> NimbusException.InvalidPersistedData(FfiConverterString.read(buf))
            2 -> NimbusException.RkvException(FfiConverterString.read(buf))
            3 -> NimbusException.IoException(FfiConverterString.read(buf))
            4 -> NimbusException.JsonException(FfiConverterString.read(buf))
            5 -> NimbusException.EvaluationException(FfiConverterString.read(buf))
            6 -> NimbusException.InvalidExpression(FfiConverterString.read(buf))
            7 -> NimbusException.InvalidFraction(FfiConverterString.read(buf))
            8 -> NimbusException.TryFromSliceException(FfiConverterString.read(buf))
            9 -> NimbusException.EmptyRatiosException(FfiConverterString.read(buf))
            10 -> NimbusException.OutOfBoundsException(FfiConverterString.read(buf))
            11 -> NimbusException.UrlParsingException(FfiConverterString.read(buf))
            12 -> NimbusException.UuidException(FfiConverterString.read(buf))
            13 -> NimbusException.InvalidExperimentFormat(FfiConverterString.read(buf))
            14 -> NimbusException.InvalidPath(FfiConverterString.read(buf))
            15 -> NimbusException.InternalException(FfiConverterString.read(buf))
            16 -> NimbusException.NoSuchExperiment(FfiConverterString.read(buf))
            17 -> NimbusException.NoSuchBranch(FfiConverterString.read(buf))
            18 -> NimbusException.DatabaseNotReady(FfiConverterString.read(buf))
            19 -> NimbusException.VersionParsingException(FfiConverterString.read(buf))
            20 -> NimbusException.BehaviorException(FfiConverterString.read(buf))
            21 -> NimbusException.TryFromIntException(FfiConverterString.read(buf))
            22 -> NimbusException.ParseIntException(FfiConverterString.read(buf))
            23 -> NimbusException.TransformParameterException(FfiConverterString.read(buf))
            24 -> NimbusException.ClientException(FfiConverterString.read(buf))
            25 -> NimbusException.UniFfiCallbackException(FfiConverterString.read(buf))
            26 -> NimbusException.RegexException(FfiConverterString.read(buf))
            else -> throw RuntimeException("invalid error enum value, something is very wrong!!")
        }
        
    }

    override fun allocationSize(value: NimbusException): ULong {
        return 4UL
    }

    override fun write(value: NimbusException, buf: ByteBuffer) {
        when(value) {
            is NimbusException.InvalidPersistedData -> {
                buf.putInt(1)
                Unit
            }
            is NimbusException.RkvException -> {
                buf.putInt(2)
                Unit
            }
            is NimbusException.IoException -> {
                buf.putInt(3)
                Unit
            }
            is NimbusException.JsonException -> {
                buf.putInt(4)
                Unit
            }
            is NimbusException.EvaluationException -> {
                buf.putInt(5)
                Unit
            }
            is NimbusException.InvalidExpression -> {
                buf.putInt(6)
                Unit
            }
            is NimbusException.InvalidFraction -> {
                buf.putInt(7)
                Unit
            }
            is NimbusException.TryFromSliceException -> {
                buf.putInt(8)
                Unit
            }
            is NimbusException.EmptyRatiosException -> {
                buf.putInt(9)
                Unit
            }
            is NimbusException.OutOfBoundsException -> {
                buf.putInt(10)
                Unit
            }
            is NimbusException.UrlParsingException -> {
                buf.putInt(11)
                Unit
            }
            is NimbusException.UuidException -> {
                buf.putInt(12)
                Unit
            }
            is NimbusException.InvalidExperimentFormat -> {
                buf.putInt(13)
                Unit
            }
            is NimbusException.InvalidPath -> {
                buf.putInt(14)
                Unit
            }
            is NimbusException.InternalException -> {
                buf.putInt(15)
                Unit
            }
            is NimbusException.NoSuchExperiment -> {
                buf.putInt(16)
                Unit
            }
            is NimbusException.NoSuchBranch -> {
                buf.putInt(17)
                Unit
            }
            is NimbusException.DatabaseNotReady -> {
                buf.putInt(18)
                Unit
            }
            is NimbusException.VersionParsingException -> {
                buf.putInt(19)
                Unit
            }
            is NimbusException.BehaviorException -> {
                buf.putInt(20)
                Unit
            }
            is NimbusException.TryFromIntException -> {
                buf.putInt(21)
                Unit
            }
            is NimbusException.ParseIntException -> {
                buf.putInt(22)
                Unit
            }
            is NimbusException.TransformParameterException -> {
                buf.putInt(23)
                Unit
            }
            is NimbusException.ClientException -> {
                buf.putInt(24)
                Unit
            }
            is NimbusException.UniFfiCallbackException -> {
                buf.putInt(25)
                Unit
            }
            is NimbusException.RegexException -> {
                buf.putInt(26)
                Unit
            }
        }.let { /* this makes the `when` an expression, which ensures it is exhaustive */ }
    }

}




enum class PrefBranch {
    
    DEFAULT,
    USER;

    


    companion object
}


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

    override fun allocationSize(value: PrefBranch) = 4UL

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






enum class PrefUnenrollReason {
    
    CHANGED,
    FAILED_TO_SET;

    


    companion object
}


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

    override fun allocationSize(value: PrefUnenrollReason) = 4UL

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






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

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

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




/**
 * @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 FfiConverterOptionalLong: FfiConverterRustBuffer<kotlin.Long?> {
    override fun read(buf: ByteBuffer): kotlin.Long? {
        if (buf.get().toInt() == 0) {
            return null
        }
        return FfiConverterLong.read(buf)
    }

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

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




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

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

    override fun write(value: kotlin.Boolean?, buf: ByteBuffer) {
        if (value == null) {
            buf.put(0)
        } else {
            buf.put(1)
            FfiConverterBoolean.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 FfiConverterOptionalTypeGeckoPrefHandler: FfiConverterRustBuffer<GeckoPrefHandler?> {
    override fun read(buf: ByteBuffer): GeckoPrefHandler? {
        if (buf.get().toInt() == 0) {
            return null
        }
        return FfiConverterTypeGeckoPrefHandler.read(buf)
    }

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

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




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

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

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




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

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

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




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

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

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




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

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

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




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

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

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




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

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

    override fun write(value: PrefValue?, buf: ByteBuffer) {
        if (value == null) {
            buf.put(0)
        } else {
            buf.put(1)
            FfiConverterTypePrefValue.write(value, 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 FfiConverterSequenceTypeAvailableExperiment: FfiConverterRustBuffer<List<AvailableExperiment>> {
    override fun read(buf: ByteBuffer): List<AvailableExperiment> {
        val len = buf.getInt()
        return List<AvailableExperiment>(len) {
            FfiConverterTypeAvailableExperiment.read(buf)
        }
    }

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

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




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

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

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




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

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

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




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

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

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




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

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

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




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

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

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




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

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

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




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

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

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




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

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

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




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

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

    override fun write(value: Map<kotlin.String, kotlin.Double>, 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) ->
            FfiConverterString.write(k, buf)
            FfiConverterDouble.write(v, buf)
        }
    }
}




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

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

    override fun write(value: Map<kotlin.String, 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) ->
            FfiConverterString.write(k, buf)
            FfiConverterString.write(v, buf)
        }
    }
}




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

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

    override fun write(value: Map<kotlin.String, GeckoPrefState>, 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) ->
            FfiConverterString.write(k, buf)
            FfiConverterTypeGeckoPrefState.write(v, buf)
        }
    }
}




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

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

    override fun write(value: Map<kotlin.String, Map<kotlin.String, GeckoPrefState>>, 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) ->
            FfiConverterString.write(k, buf)
            FfiConverterMapStringTypeGeckoPrefState.write(v, buf)
        }
    }
}





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


/**
 * @suppress
 */
public object FfiConverterTypeJsonObject: FfiConverter<JsonObject, RustBuffer.ByValue> {
    override fun lift(value: RustBuffer.ByValue): JsonObject {
        val builtinValue = FfiConverterString.lift(value)
        return JSONObject(builtinValue)
    }

    override fun lower(value: JsonObject): RustBuffer.ByValue {
        val builtinValue = value.toString()
        return FfiConverterString.lower(builtinValue)
    }

    override fun read(buf: ByteBuffer): JsonObject {
        val builtinValue = FfiConverterString.read(buf)
        return JSONObject(builtinValue)
    }

    override fun allocationSize(value: JsonObject): ULong {
        val builtinValue = value.toString()
        return FfiConverterString.allocationSize(builtinValue)
    }

    override fun write(value: JsonObject, buf: ByteBuffer) {
        val builtinValue = value.toString()
        FfiConverterString.write(builtinValue, 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 PrefValue = kotlin.String
public typealias FfiConverterTypePrefValue = FfiConverterString


        /**

         */
    @Throws(NimbusException::class) fun `getCalculatedAttributes`(`installationDate`: kotlin.Long?, `dbPath`: kotlin.String, `locale`: kotlin.String): CalculatedAttributes {
            return FfiConverterTypeCalculatedAttributes.lift(
    uniffiRustCallWithError(NimbusException) { _status ->
    UniffiLib.uniffi_nimbus_fn_func_get_calculated_attributes(
    
        FfiConverterOptionalLong.lower(`installationDate`),FfiConverterString.lower(`dbPath`),FfiConverterString.lower(`locale`),_status)
}
    )
    }
    

        /**
         * A test utility used to validate event queries against the jexl evaluator.
         *
         * This method should only be used in tests.
         */
    @Throws(NimbusException::class) fun `validateEventQueries`(`recordedContext`: RecordedContext)
        = 
    uniffiRustCallWithError(NimbusException) { _status ->
    UniffiLib.uniffi_nimbus_fn_func_validate_event_queries(
    
        FfiConverterTypeRecordedContext.lower(`recordedContext`),_status)
}
    
    


