// This file was autogenerated by the `uniffi-bindgen-gecko-js` crate.
// Trust me, you don't want to mess with it!

import { UniFFITypeError } from "resource://gre/modules/UniFFI.sys.mjs";



// Objects intended to be used in the unit tests
export var UnitTestObjs = {};

// Write/Read data to/from an ArrayBuffer
class ArrayBufferDataStream {
    constructor(arrayBuffer) {
        this.dataView = new DataView(arrayBuffer);
        this.pos = 0;
    }

    readUint8() {
        let rv = this.dataView.getUint8(this.pos);
        this.pos += 1;
        return rv;
    }

    writeUint8(value) {
        this.dataView.setUint8(this.pos, value);
        this.pos += 1;
    }

    readUint16() {
        let rv = this.dataView.getUint16(this.pos);
        this.pos += 2;
        return rv;
    }

    writeUint16(value) {
        this.dataView.setUint16(this.pos, value);
        this.pos += 2;
    }

    readUint32() {
        let rv = this.dataView.getUint32(this.pos);
        this.pos += 4;
        return rv;
    }

    writeUint32(value) {
        this.dataView.setUint32(this.pos, value);
        this.pos += 4;
    }

    readUint64() {
        let rv = this.dataView.getBigUint64(this.pos);
        this.pos += 8;
        return Number(rv);
    }

    writeUint64(value) {
        this.dataView.setBigUint64(this.pos, BigInt(value));
        this.pos += 8;
    }


    readInt8() {
        let rv = this.dataView.getInt8(this.pos);
        this.pos += 1;
        return rv;
    }

    writeInt8(value) {
        this.dataView.setInt8(this.pos, value);
        this.pos += 1;
    }

    readInt16() {
        let rv = this.dataView.getInt16(this.pos);
        this.pos += 2;
        return rv;
    }

    writeInt16(value) {
        this.dataView.setInt16(this.pos, value);
        this.pos += 2;
    }

    readInt32() {
        let rv = this.dataView.getInt32(this.pos);
        this.pos += 4;
        return rv;
    }

    writeInt32(value) {
        this.dataView.setInt32(this.pos, value);
        this.pos += 4;
    }

    readInt64() {
        let rv = this.dataView.getBigInt64(this.pos);
        this.pos += 8;
        return Number(rv);
    }

    writeInt64(value) {
        this.dataView.setBigInt64(this.pos, BigInt(value));
        this.pos += 8;
    }

    readFloat32() {
        let rv = this.dataView.getFloat32(this.pos);
        this.pos += 4;
        return rv;
    }

    writeFloat32(value) {
        this.dataView.setFloat32(this.pos, value);
        this.pos += 4;
    }

    readFloat64() {
        let rv = this.dataView.getFloat64(this.pos);
        this.pos += 8;
        return rv;
    }

    writeFloat64(value) {
        this.dataView.setFloat64(this.pos, value);
        this.pos += 8;
    }


    writeString(value) {
      const encoder = new TextEncoder();
      // Note: in order to efficiently write this data, we first write the
      // string data, reserving 4 bytes for the size.
      const dest = new Uint8Array(this.dataView.buffer, this.pos + 4);
      const encodeResult = encoder.encodeInto(value, dest);
      if (encodeResult.read != value.length) {
        throw new UniFFIError(
            "writeString: out of space when writing to ArrayBuffer.  Did the computeSize() method returned the wrong result?"
        );
      }
      const size = encodeResult.written;
      // Next, go back and write the size before the string data
      this.dataView.setUint32(this.pos, size);
      // Finally, advance our position past both the size and string data
      this.pos += size + 4;
    }

    readString() {
      const decoder = new TextDecoder();
      const size = this.readUint32();
      const source = new Uint8Array(this.dataView.buffer, this.pos, size)
      const value = decoder.decode(source);
      this.pos += size;
      return value;
    }

    readBytes() {
      const size = this.readInt32();
      const bytes = new Uint8Array(this.dataView.buffer, this.pos, size);
      this.pos += size;
      return bytes
    }

    writeBytes(uint8Array) {
      this.writeUint32(uint8Array.length);
      value.forEach((elt) => {
        dataStream.writeUint8(elt);
      })
    }

    // Reads a SuggestStore pointer from the data stream
    // UniFFI Pointers are **always** 8 bytes long. That is enforced
    // by the C++ and Rust Scaffolding code.
    readPointerSuggestStore() {
        const pointerId = 4; // suggest:SuggestStore
        const res = UniFFIScaffolding.readPointer(pointerId, this.dataView.buffer, this.pos);
        this.pos += 8;
        return res;
    }

    // Writes a SuggestStore pointer into the data stream
    // UniFFI Pointers are **always** 8 bytes long. That is enforced
    // by the C++ and Rust Scaffolding code.
    writePointerSuggestStore(value) {
        const pointerId = 4; // suggest:SuggestStore
        UniFFIScaffolding.writePointer(pointerId, value, this.dataView.buffer, this.pos);
        this.pos += 8;
    }
    

    // Reads a SuggestStoreBuilder pointer from the data stream
    // UniFFI Pointers are **always** 8 bytes long. That is enforced
    // by the C++ and Rust Scaffolding code.
    readPointerSuggestStoreBuilder() {
        const pointerId = 5; // suggest:SuggestStoreBuilder
        const res = UniFFIScaffolding.readPointer(pointerId, this.dataView.buffer, this.pos);
        this.pos += 8;
        return res;
    }

    // Writes a SuggestStoreBuilder pointer into the data stream
    // UniFFI Pointers are **always** 8 bytes long. That is enforced
    // by the C++ and Rust Scaffolding code.
    writePointerSuggestStoreBuilder(value) {
        const pointerId = 5; // suggest:SuggestStoreBuilder
        UniFFIScaffolding.writePointer(pointerId, value, this.dataView.buffer, this.pos);
        this.pos += 8;
    }
    
}

function handleRustResult(result, liftCallback, liftErrCallback) {
    switch (result.code) {
        case "success":
            return liftCallback(result.data);

        case "error":
            throw liftErrCallback(result.data);

        case "internal-error":
            if (result.data) {
                throw new UniFFIInternalError(FfiConverterString.lift(result.data));
            } else {
                throw new UniFFIInternalError("Unknown error");
            }

        default:
            throw new UniFFIError(`Unexpected status code: ${result.code}`);
    }
}

class UniFFIError {
    constructor(message) {
        this.message = message;
    }

    toString() {
        return `UniFFIError: ${this.message}`
    }
}

class UniFFIInternalError extends UniFFIError {}

// Base class for FFI converters
class FfiConverter {
    // throw `UniFFITypeError` if a value to be converted has an invalid type
    static checkType(value) {
        if (value === undefined ) {
            throw new UniFFITypeError(`undefined`);
        }
        if (value === null ) {
            throw new UniFFITypeError(`null`);
        }
    }
}

// Base class for FFI converters that lift/lower by reading/writing to an ArrayBuffer
class FfiConverterArrayBuffer extends FfiConverter {
    static lift(buf) {
        return this.read(new ArrayBufferDataStream(buf));
    }

    static lower(value) {
        const buf = new ArrayBuffer(this.computeSize(value));
        const dataStream = new ArrayBufferDataStream(buf);
        this.write(dataStream, value);
        return buf;
    }
}

// Symbols that are used to ensure that Object constructors
// can only be used with a proper UniFFI pointer
const uniffiObjectPtr = Symbol("uniffiObjectPtr");
const constructUniffiObject = Symbol("constructUniffiObject");
UnitTestObjs.uniffiObjectPtr = uniffiObjectPtr;

// Export the FFIConverter object to make external types work.
export class FfiConverterI32 extends FfiConverter {
    static checkType(value) {
        super.checkType(value);
        if (!Number.isInteger(value)) {
            throw new UniFFITypeError(`${value} is not an integer`);
        }
        if (value < -2147483648 || value > 2147483647) {
            throw new UniFFITypeError(`${value} exceeds the I32 bounds`);
        }
    }
    static computeSize() {
        return 4;
    }
    static lift(value) {
        return value;
    }
    static lower(value) {
        return value;
    }
    static write(dataStream, value) {
        dataStream.writeInt32(value)
    }
    static read(dataStream) {
        return dataStream.readInt32()
    }
}

// Export the FFIConverter object to make external types work.
export class FfiConverterU64 extends FfiConverter {
    static checkType(value) {
        super.checkType(value);
        if (!Number.isSafeInteger(value)) {
            throw new UniFFITypeError(`${value} exceeds the safe integer bounds`);
        }
        if (value < 0) {
            throw new UniFFITypeError(`${value} exceeds the U64 bounds`);
        }
    }
    static computeSize() {
        return 8;
    }
    static lift(value) {
        return value;
    }
    static lower(value) {
        return value;
    }
    static write(dataStream, value) {
        dataStream.writeUint64(value)
    }
    static read(dataStream) {
        return dataStream.readUint64()
    }
}

// Export the FFIConverter object to make external types work.
export class FfiConverterI64 extends FfiConverter {
    static checkType(value) {
        super.checkType(value);
        if (!Number.isSafeInteger(value)) {
            throw new UniFFITypeError(`${value} exceeds the safe integer bounds`);
        }
    }
    static computeSize() {
        return 8;
    }
    static lift(value) {
        return value;
    }
    static lower(value) {
        return value;
    }
    static write(dataStream, value) {
        dataStream.writeInt64(value)
    }
    static read(dataStream) {
        return dataStream.readInt64()
    }
}

// Export the FFIConverter object to make external types work.
export class FfiConverterF64 extends FfiConverter {
    static computeSize() {
        return 8;
    }
    static lift(value) {
        return value;
    }
    static lower(value) {
        return value;
    }
    static write(dataStream, value) {
        dataStream.writeFloat64(value)
    }
    static read(dataStream) {
        return dataStream.readFloat64()
    }
}

// Export the FFIConverter object to make external types work.
export class FfiConverterBool extends FfiConverter {
    static computeSize() {
        return 1;
    }
    static lift(value) {
        return value == 1;
    }
    static lower(value) {
        if (value) {
            return 1;
        } else {
            return 0;
        }
    }
    static write(dataStream, value) {
        dataStream.writeUint8(this.lower(value))
    }
    static read(dataStream) {
        return this.lift(dataStream.readUint8())
    }
}

// Export the FFIConverter object to make external types work.
export class FfiConverterString extends FfiConverter {
    static checkType(value) {
        super.checkType(value);
        if (typeof value !== "string") {
            throw new UniFFITypeError(`${value} is not a string`);
        }
    }

    static lift(buf) {
        const decoder = new TextDecoder();
        const utf8Arr = new Uint8Array(buf);
        return decoder.decode(utf8Arr);
    }
    static lower(value) {
        const encoder = new TextEncoder();
        return encoder.encode(value).buffer;
    }

    static write(dataStream, value) {
        dataStream.writeString(value);
    }

    static read(dataStream) {
        return dataStream.readString();
    }

    static computeSize(value) {
        const encoder = new TextEncoder();
        return 4 + encoder.encode(value).length
    }
}

// Export the FFIConverter object to make external types work.
export class FfiConverterBytes extends FfiConverterArrayBuffer {
    static read(dataStream) {
        return dataStream.readBytes()
    }

    static write(dataStream, value) {
        dataStream.writeBytes(value)
    }

    static computeSize(value) {
        // The size of the length + 1 byte / item
        return 4 + value.length
    }

    static checkType(value) {
        if (!value instanceof Uint8Array) {
            throw new UniFFITypeError(`${value} is not an Uint8Array`);
        }
    }
}

/**
 * The store is the entry point to the Suggest component. It incrementally
 * downloads suggestions from the Remote Settings service, stores them in a
 * local database, and returns them in response to user queries.
 *
 * Your application should create a single store, and manage it as a singleton.
 * The store is thread-safe, and supports concurrent queries and ingests. We
 * expect that your application will call [`SuggestStore::query()`] to show
 * suggestions as the user types into the address bar, and periodically call
 * [`SuggestStore::ingest()`] in the background to update the database with
 * new suggestions from Remote Settings.
 *
 * For responsiveness, we recommend always calling `query()` on a worker
 * thread. When the user types new input into the address bar, call
 * [`SuggestStore::interrupt()`] on the main thread to cancel the query
 * for the old input, and unblock the worker thread for the new query.
 *
 * The store keeps track of the state needed to support incremental ingestion,
 * but doesn't schedule the ingestion work itself, or decide how many
 * suggestions to ingest at once. This is for two reasons:
 *
 * 1. The primitives for scheduling background work vary between platforms, and
 * aren't available to the lower-level Rust layer. You might use an idle
 * timer on Desktop, `WorkManager` on Android, or `BGTaskScheduler` on iOS.
 * 2. Ingestion constraints can change, depending on the platform and the needs
 * of your application. A mobile device on a metered connection might want
 * to request a small subset of the Suggest data and download the rest
 * later, while a desktop on a fast link might download the entire dataset
 * on the first launch.
 */
export class SuggestStore {
    // Use `init` to instantiate this class.
    // DO NOT USE THIS CONSTRUCTOR DIRECTLY
    constructor(opts) {
        if (!Object.prototype.hasOwnProperty.call(opts, constructUniffiObject)) {
            throw new UniFFIError("Attempting to construct an object using the JavaScript constructor directly" +
            "Please use a UDL defined constructor, or the init function for the primary constructor")
        }
        if (!opts[constructUniffiObject] instanceof UniFFIPointer) {
            throw new UniFFIError("Attempting to create a UniFFI object with a pointer that is not an instance of UniFFIPointer")
        }
        this[uniffiObjectPtr] = opts[constructUniffiObject];
    }
    /**
     * Creates a Suggest store.
     * @returns {SuggestStore}
     */
    static init(path,settingsConfig = null) {
        const liftResult = (result) => FfiConverterTypeSuggestStore.lift(result);
        const liftError = (data) => FfiConverterTypeSuggestApiError.lift(data);
        const functionCall = () => {
            try {
                FfiConverterString.checkType(path)
            } catch (e) {
                if (e instanceof UniFFITypeError) {
                    e.addItemDescriptionPart("path");
                }
                throw e;
            }
            try {
                FfiConverterOptionalTypeRemoteSettingsConfig.checkType(settingsConfig)
            } catch (e) {
                if (e instanceof UniFFITypeError) {
                    e.addItemDescriptionPart("settingsConfig");
                }
                throw e;
            }
            return UniFFIScaffolding.callSync(
                36, // suggest:uniffi_suggest_fn_constructor_suggeststore_new
                FfiConverterString.lower(path),
                FfiConverterOptionalTypeRemoteSettingsConfig.lower(settingsConfig),
            )
        }
        return handleRustResult(functionCall(), liftResult, liftError);}

    /**
     * Removes all content from the database.
     */
    clear() {
        const liftResult = (result) => undefined;
        const liftError = (data) => FfiConverterTypeSuggestApiError.lift(data);
        const functionCall = () => {
            return UniFFIScaffolding.callAsyncWrapper(
                26, // suggest:uniffi_suggest_fn_method_suggeststore_clear
                FfiConverterTypeSuggestStore.lower(this),
            )
        }
        try {
            return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
        }  catch (error) {
            return Promise.reject(error)
        }
    }

    /**
     * Clear dismissed suggestions
     */
    clearDismissedSuggestions() {
        const liftResult = (result) => undefined;
        const liftError = (data) => FfiConverterTypeSuggestApiError.lift(data);
        const functionCall = () => {
            return UniFFIScaffolding.callAsyncWrapper(
                27, // suggest:uniffi_suggest_fn_method_suggeststore_clear_dismissed_suggestions
                FfiConverterTypeSuggestStore.lower(this),
            )
        }
        try {
            return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
        }  catch (error) {
            return Promise.reject(error)
        }
    }

    /**
     * Dismiss a suggestion
     *
     * Dismissed suggestions will not be returned again
     *
     * In the case of AMP suggestions this should be the raw URL.
     */
    dismissSuggestion(suggestionUrl) {
        const liftResult = (result) => undefined;
        const liftError = (data) => FfiConverterTypeSuggestApiError.lift(data);
        const functionCall = () => {
            try {
                FfiConverterString.checkType(suggestionUrl)
            } catch (e) {
                if (e instanceof UniFFITypeError) {
                    e.addItemDescriptionPart("suggestionUrl");
                }
                throw e;
            }
            return UniFFIScaffolding.callAsyncWrapper(
                28, // suggest:uniffi_suggest_fn_method_suggeststore_dismiss_suggestion
                FfiConverterTypeSuggestStore.lower(this),
                FfiConverterString.lower(suggestionUrl),
            )
        }
        try {
            return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
        }  catch (error) {
            return Promise.reject(error)
        }
    }

    /**
     * Fetches geonames stored in the database. A geoname represents a
     * geographic place.
     *
     * `query` is a string that will be matched directly against geoname names.
     * It is not a query string in the usual Suggest sense. `match_name_prefix`
     * determines whether prefix matching is performed on names excluding
     * abbreviations and airport codes. When `true`, names that start with
     * `query` will match. When false, names that equal `query` will match.
     *
     * `geoname_type` restricts returned geonames to a [`GeonameType`].
     *
     * `filter` restricts returned geonames to certain cities or regions.
     * Cities can be restricted to regions by including the regions in
     * `filter`, and regions can be restricted to those containing certain
     * cities by including the cities in `filter`. This is especially useful
     * since city and region names are not unique. `filter` is disjunctive: If
     * any item in `filter` matches a geoname, the geoname will be filtered in.
     *
     * The query can match a single geoname in more than one way. For example,
     * it can match both a full name and an abbreviation. The returned vec of
     * [`GeonameMatch`] values will include all matches for a geoname, one
     * match per `match_type` per geoname. In other words, a matched geoname
     * can map to more than one `GeonameMatch`.
     * @returns {Array.<GeonameMatch>}
     */
    fetchGeonames(query,matchNamePrefix,geonameType,filter) {
        const liftResult = (result) => FfiConverterSequenceTypeGeonameMatch.lift(result);
        const liftError = (data) => FfiConverterTypeSuggestApiError.lift(data);
        const functionCall = () => {
            try {
                FfiConverterString.checkType(query)
            } catch (e) {
                if (e instanceof UniFFITypeError) {
                    e.addItemDescriptionPart("query");
                }
                throw e;
            }
            try {
                FfiConverterBool.checkType(matchNamePrefix)
            } catch (e) {
                if (e instanceof UniFFITypeError) {
                    e.addItemDescriptionPart("matchNamePrefix");
                }
                throw e;
            }
            try {
                FfiConverterOptionalTypeGeonameType.checkType(geonameType)
            } catch (e) {
                if (e instanceof UniFFITypeError) {
                    e.addItemDescriptionPart("geonameType");
                }
                throw e;
            }
            try {
                FfiConverterOptionalSequenceTypeGeoname.checkType(filter)
            } catch (e) {
                if (e instanceof UniFFITypeError) {
                    e.addItemDescriptionPart("filter");
                }
                throw e;
            }
            return UniFFIScaffolding.callAsyncWrapper(
                29, // suggest:uniffi_suggest_fn_method_suggeststore_fetch_geonames
                FfiConverterTypeSuggestStore.lower(this),
                FfiConverterString.lower(query),
                FfiConverterBool.lower(matchNamePrefix),
                FfiConverterOptionalTypeGeonameType.lower(geonameType),
                FfiConverterOptionalSequenceTypeGeoname.lower(filter),
            )
        }
        try {
            return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
        }  catch (error) {
            return Promise.reject(error)
        }
    }

    /**
     * Returns global Suggest configuration data.
     * @returns {SuggestGlobalConfig}
     */
    fetchGlobalConfig() {
        const liftResult = (result) => FfiConverterTypeSuggestGlobalConfig.lift(result);
        const liftError = (data) => FfiConverterTypeSuggestApiError.lift(data);
        const functionCall = () => {
            return UniFFIScaffolding.callAsyncWrapper(
                30, // suggest:uniffi_suggest_fn_method_suggeststore_fetch_global_config
                FfiConverterTypeSuggestStore.lower(this),
            )
        }
        try {
            return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
        }  catch (error) {
            return Promise.reject(error)
        }
    }

    /**
     * Returns per-provider Suggest configuration data.
     * @returns {?SuggestProviderConfig}
     */
    fetchProviderConfig(provider) {
        const liftResult = (result) => FfiConverterOptionalTypeSuggestProviderConfig.lift(result);
        const liftError = (data) => FfiConverterTypeSuggestApiError.lift(data);
        const functionCall = () => {
            try {
                FfiConverterTypeSuggestionProvider.checkType(provider)
            } catch (e) {
                if (e instanceof UniFFITypeError) {
                    e.addItemDescriptionPart("provider");
                }
                throw e;
            }
            return UniFFIScaffolding.callAsyncWrapper(
                31, // suggest:uniffi_suggest_fn_method_suggeststore_fetch_provider_config
                FfiConverterTypeSuggestStore.lower(this),
                FfiConverterTypeSuggestionProvider.lower(provider),
            )
        }
        try {
            return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
        }  catch (error) {
            return Promise.reject(error)
        }
    }

    /**
     * Ingests new suggestions from Remote Settings.
     * @returns {SuggestIngestionMetrics}
     */
    ingest(constraints) {
        const liftResult = (result) => FfiConverterTypeSuggestIngestionMetrics.lift(result);
        const liftError = (data) => FfiConverterTypeSuggestApiError.lift(data);
        const functionCall = () => {
            try {
                FfiConverterTypeSuggestIngestionConstraints.checkType(constraints)
            } catch (e) {
                if (e instanceof UniFFITypeError) {
                    e.addItemDescriptionPart("constraints");
                }
                throw e;
            }
            return UniFFIScaffolding.callAsyncWrapper(
                32, // suggest:uniffi_suggest_fn_method_suggeststore_ingest
                FfiConverterTypeSuggestStore.lower(this),
                FfiConverterTypeSuggestIngestionConstraints.lower(constraints),
            )
        }
        try {
            return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
        }  catch (error) {
            return Promise.reject(error)
        }
    }

    /**
     * Interrupts any ongoing queries.
     *
     * This should be called when the user types new input into the address
     * bar, to ensure that they see fresh suggestions as they type. This
     * method does not interrupt any ongoing ingests.
     */
    interrupt(kind = null) {
        const liftResult = (result) => undefined;
        const liftError = null;
        const functionCall = () => {
            try {
                FfiConverterOptionalTypeInterruptKind.checkType(kind)
            } catch (e) {
                if (e instanceof UniFFITypeError) {
                    e.addItemDescriptionPart("kind");
                }
                throw e;
            }
            return UniFFIScaffolding.callSync(
                33, // suggest:uniffi_suggest_fn_method_suggeststore_interrupt
                FfiConverterTypeSuggestStore.lower(this),
                FfiConverterOptionalTypeInterruptKind.lower(kind),
            )
        }
        return handleRustResult(functionCall(), liftResult, liftError);
    }

    /**
     * Queries the database for suggestions.
     * @returns {Array.<Suggestion>}
     */
    query(query) {
        const liftResult = (result) => FfiConverterSequenceTypeSuggestion.lift(result);
        const liftError = (data) => FfiConverterTypeSuggestApiError.lift(data);
        const functionCall = () => {
            try {
                FfiConverterTypeSuggestionQuery.checkType(query)
            } catch (e) {
                if (e instanceof UniFFITypeError) {
                    e.addItemDescriptionPart("query");
                }
                throw e;
            }
            return UniFFIScaffolding.callAsyncWrapper(
                34, // suggest:uniffi_suggest_fn_method_suggeststore_query
                FfiConverterTypeSuggestStore.lower(this),
                FfiConverterTypeSuggestionQuery.lower(query),
            )
        }
        try {
            return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
        }  catch (error) {
            return Promise.reject(error)
        }
    }

    /**
     * Queries the database for suggestions.
     * @returns {QueryWithMetricsResult}
     */
    queryWithMetrics(query) {
        const liftResult = (result) => FfiConverterTypeQueryWithMetricsResult.lift(result);
        const liftError = (data) => FfiConverterTypeSuggestApiError.lift(data);
        const functionCall = () => {
            try {
                FfiConverterTypeSuggestionQuery.checkType(query)
            } catch (e) {
                if (e instanceof UniFFITypeError) {
                    e.addItemDescriptionPart("query");
                }
                throw e;
            }
            return UniFFIScaffolding.callAsyncWrapper(
                35, // suggest:uniffi_suggest_fn_method_suggeststore_query_with_metrics
                FfiConverterTypeSuggestStore.lower(this),
                FfiConverterTypeSuggestionQuery.lower(query),
            )
        }
        try {
            return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
        }  catch (error) {
            return Promise.reject(error)
        }
    }

}

// Export the FFIConverter object to make external types work.
export class FfiConverterTypeSuggestStore extends FfiConverter {
    static lift(value) {
        const opts = {};
        opts[constructUniffiObject] = value;
        return new SuggestStore(opts);
    }

    static lower(value) {
        const ptr = value[uniffiObjectPtr];
        if (!(ptr instanceof UniFFIPointer)) {
            throw new UniFFITypeError("Object is not a 'SuggestStore' instance");
        }
        return ptr;
    }

    static read(dataStream) {
        return this.lift(dataStream.readPointerSuggestStore());
    }

    static write(dataStream, value) {
        dataStream.writePointerSuggestStore(value[uniffiObjectPtr]);
    }

    static computeSize(value) {
        return 8;
    }
}

/**
 * Builder for [SuggestStore]
 *
 * Using a builder is preferred to calling the constructor directly since it's harder to confuse
 * the data_path and cache_path strings.
 */
export class SuggestStoreBuilder {
    // Use `init` to instantiate this class.
    // DO NOT USE THIS CONSTRUCTOR DIRECTLY
    constructor(opts) {
        if (!Object.prototype.hasOwnProperty.call(opts, constructUniffiObject)) {
            throw new UniFFIError("Attempting to construct an object using the JavaScript constructor directly" +
            "Please use a UDL defined constructor, or the init function for the primary constructor")
        }
        if (!opts[constructUniffiObject] instanceof UniFFIPointer) {
            throw new UniFFIError("Attempting to create a UniFFI object with a pointer that is not an instance of UniFFIPointer")
        }
        this[uniffiObjectPtr] = opts[constructUniffiObject];
    }
    /**
     * init
     * @returns {SuggestStoreBuilder}
     */
    static init() {
        const liftResult = (result) => FfiConverterTypeSuggestStoreBuilder.lift(result);
        const liftError = null;
        const functionCall = () => {
            return UniFFIScaffolding.callSync(
                43, // suggest:uniffi_suggest_fn_constructor_suggeststorebuilder_new
            )
        }
        return handleRustResult(functionCall(), liftResult, liftError);}

    /**
     * build
     * @returns {SuggestStore}
     */
    build() {
        const liftResult = (result) => FfiConverterTypeSuggestStore.lift(result);
        const liftError = (data) => FfiConverterTypeSuggestApiError.lift(data);
        const functionCall = () => {
            return UniFFIScaffolding.callSync(
                37, // suggest:uniffi_suggest_fn_method_suggeststorebuilder_build
                FfiConverterTypeSuggestStoreBuilder.lower(this),
            )
        }
        return handleRustResult(functionCall(), liftResult, liftError);
    }

    /**
     * Deprecated: this is no longer used by the suggest component.
     * @returns {SuggestStoreBuilder}
     */
    cachePath(path) {
        const liftResult = (result) => FfiConverterTypeSuggestStoreBuilder.lift(result);
        const liftError = null;
        const functionCall = () => {
            try {
                FfiConverterString.checkType(path)
            } catch (e) {
                if (e instanceof UniFFITypeError) {
                    e.addItemDescriptionPart("path");
                }
                throw e;
            }
            return UniFFIScaffolding.callAsyncWrapper(
                38, // suggest:uniffi_suggest_fn_method_suggeststorebuilder_cache_path
                FfiConverterTypeSuggestStoreBuilder.lower(this),
                FfiConverterString.lower(path),
            )
        }
        try {
            return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
        }  catch (error) {
            return Promise.reject(error)
        }
    }

    /**
     * dataPath
     * @returns {SuggestStoreBuilder}
     */
    dataPath(path) {
        const liftResult = (result) => FfiConverterTypeSuggestStoreBuilder.lift(result);
        const liftError = null;
        const functionCall = () => {
            try {
                FfiConverterString.checkType(path)
            } catch (e) {
                if (e instanceof UniFFITypeError) {
                    e.addItemDescriptionPart("path");
                }
                throw e;
            }
            return UniFFIScaffolding.callSync(
                39, // suggest:uniffi_suggest_fn_method_suggeststorebuilder_data_path
                FfiConverterTypeSuggestStoreBuilder.lower(this),
                FfiConverterString.lower(path),
            )
        }
        return handleRustResult(functionCall(), liftResult, liftError);
    }

    /**
     * Add an sqlite3 extension to load
     *
     * library_name should be the name of the library without any extension, for example `libmozsqlite3`.
     * entrypoint should be the entry point, for example `sqlite3_fts5_init`.  If `null` (the default)
     * entry point will be used (see https://sqlite.org/loadext.html for details).
     * @returns {SuggestStoreBuilder}
     */
    loadExtension(library,entryPoint) {
        const liftResult = (result) => FfiConverterTypeSuggestStoreBuilder.lift(result);
        const liftError = null;
        const functionCall = () => {
            try {
                FfiConverterString.checkType(library)
            } catch (e) {
                if (e instanceof UniFFITypeError) {
                    e.addItemDescriptionPart("library");
                }
                throw e;
            }
            try {
                FfiConverterOptionalstring.checkType(entryPoint)
            } catch (e) {
                if (e instanceof UniFFITypeError) {
                    e.addItemDescriptionPart("entryPoint");
                }
                throw e;
            }
            return UniFFIScaffolding.callSync(
                40, // suggest:uniffi_suggest_fn_method_suggeststorebuilder_load_extension
                FfiConverterTypeSuggestStoreBuilder.lower(this),
                FfiConverterString.lower(library),
                FfiConverterOptionalstring.lower(entryPoint),
            )
        }
        return handleRustResult(functionCall(), liftResult, liftError);
    }

    /**
     * remoteSettingsBucketName
     * @returns {SuggestStoreBuilder}
     */
    remoteSettingsBucketName(bucketName) {
        const liftResult = (result) => FfiConverterTypeSuggestStoreBuilder.lift(result);
        const liftError = null;
        const functionCall = () => {
            try {
                FfiConverterString.checkType(bucketName)
            } catch (e) {
                if (e instanceof UniFFITypeError) {
                    e.addItemDescriptionPart("bucketName");
                }
                throw e;
            }
            return UniFFIScaffolding.callSync(
                41, // suggest:uniffi_suggest_fn_method_suggeststorebuilder_remote_settings_bucket_name
                FfiConverterTypeSuggestStoreBuilder.lower(this),
                FfiConverterString.lower(bucketName),
            )
        }
        return handleRustResult(functionCall(), liftResult, liftError);
    }

    /**
     * remoteSettingsServer
     * @returns {SuggestStoreBuilder}
     */
    remoteSettingsServer(server) {
        const liftResult = (result) => FfiConverterTypeSuggestStoreBuilder.lift(result);
        const liftError = null;
        const functionCall = () => {
            try {
                FfiConverterTypeRemoteSettingsServer.checkType(server)
            } catch (e) {
                if (e instanceof UniFFITypeError) {
                    e.addItemDescriptionPart("server");
                }
                throw e;
            }
            return UniFFIScaffolding.callSync(
                42, // suggest:uniffi_suggest_fn_method_suggeststorebuilder_remote_settings_server
                FfiConverterTypeSuggestStoreBuilder.lower(this),
                FfiConverterTypeRemoteSettingsServer.lower(server),
            )
        }
        return handleRustResult(functionCall(), liftResult, liftError);
    }

}

// Export the FFIConverter object to make external types work.
export class FfiConverterTypeSuggestStoreBuilder extends FfiConverter {
    static lift(value) {
        const opts = {};
        opts[constructUniffiObject] = value;
        return new SuggestStoreBuilder(opts);
    }

    static lower(value) {
        const ptr = value[uniffiObjectPtr];
        if (!(ptr instanceof UniFFIPointer)) {
            throw new UniFFITypeError("Object is not a 'SuggestStoreBuilder' instance");
        }
        return ptr;
    }

    static read(dataStream) {
        return this.lift(dataStream.readPointerSuggestStoreBuilder());
    }

    static write(dataStream, value) {
        dataStream.writePointerSuggestStoreBuilder(value[uniffiObjectPtr]);
    }

    static computeSize(value) {
        return 8;
    }
}

/**
 * A single geographic place.
 *
 * This corresponds to a single row in the main "geoname" table described in
 * the GeoNames documentation [1]. We exclude fields we don't need.
 *
 * [1]: https://download.geonames.org/export/dump/readme.txt
 */
export class Geoname {
    constructor({ geonameId, name, latitude, longitude, countryCode, admin1Code, population } = {}) {
        try {
            FfiConverterI64.checkType(geonameId)
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart("geonameId");
            }
            throw e;
        }
        try {
            FfiConverterString.checkType(name)
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart("name");
            }
            throw e;
        }
        try {
            FfiConverterF64.checkType(latitude)
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart("latitude");
            }
            throw e;
        }
        try {
            FfiConverterF64.checkType(longitude)
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart("longitude");
            }
            throw e;
        }
        try {
            FfiConverterString.checkType(countryCode)
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart("countryCode");
            }
            throw e;
        }
        try {
            FfiConverterString.checkType(admin1Code)
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart("admin1Code");
            }
            throw e;
        }
        try {
            FfiConverterU64.checkType(population)
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart("population");
            }
            throw e;
        }
        /**
         * The `geonameid` straight from the geoname table.
         * @type {number}
         */
        this.geonameId = geonameId;
        /**
         * This is pretty much the place's canonical name. Usually there will be a
         * row in the alternates table with the same name, but not always. When
         * there is such a row, it doesn't always have `is_preferred_name` set, and
         * in fact fact there may be another row with a different name with
         * `is_preferred_name` set.
         * @type {string}
         */
        this.name = name;
        /**
         * Latitude in decimal degrees.
         * @type {number}
         */
        this.latitude = latitude;
        /**
         * Longitude in decimal degrees.
         * @type {number}
         */
        this.longitude = longitude;
        /**
         * ISO-3166 two-letter uppercase country code, e.g., "US".
         * @type {string}
         */
        this.countryCode = countryCode;
        /**
         * The top-level administrative region for the place within its country,
         * like a state or province. For the U.S., the two-letter uppercase state
         * abbreviation.
         * @type {string}
         */
        this.admin1Code = admin1Code;
        /**
         * Population size.
         * @type {number}
         */
        this.population = population;
    }

    equals(other) {
        return (
            this.geonameId == other.geonameId &&
            this.name == other.name &&
            this.latitude == other.latitude &&
            this.longitude == other.longitude &&
            this.countryCode == other.countryCode &&
            this.admin1Code == other.admin1Code &&
            this.population == other.population
        )
    }
}

// Export the FFIConverter object to make external types work.
export class FfiConverterTypeGeoname extends FfiConverterArrayBuffer {
    static read(dataStream) {
        return new Geoname({
            geonameId: FfiConverterI64.read(dataStream),
            name: FfiConverterString.read(dataStream),
            latitude: FfiConverterF64.read(dataStream),
            longitude: FfiConverterF64.read(dataStream),
            countryCode: FfiConverterString.read(dataStream),
            admin1Code: FfiConverterString.read(dataStream),
            population: FfiConverterU64.read(dataStream),
        });
    }
    static write(dataStream, value) {
        FfiConverterI64.write(dataStream, value.geonameId);
        FfiConverterString.write(dataStream, value.name);
        FfiConverterF64.write(dataStream, value.latitude);
        FfiConverterF64.write(dataStream, value.longitude);
        FfiConverterString.write(dataStream, value.countryCode);
        FfiConverterString.write(dataStream, value.admin1Code);
        FfiConverterU64.write(dataStream, value.population);
    }

    static computeSize(value) {
        let totalSize = 0;
        totalSize += FfiConverterI64.computeSize(value.geonameId);
        totalSize += FfiConverterString.computeSize(value.name);
        totalSize += FfiConverterF64.computeSize(value.latitude);
        totalSize += FfiConverterF64.computeSize(value.longitude);
        totalSize += FfiConverterString.computeSize(value.countryCode);
        totalSize += FfiConverterString.computeSize(value.admin1Code);
        totalSize += FfiConverterU64.computeSize(value.population);
        return totalSize
    }

    static checkType(value) {
        super.checkType(value);
        if (!(value instanceof Geoname)) {
            throw new UniFFITypeError(`Expected 'Geoname', found '${typeof value}'`);
        }
        try {
            FfiConverterI64.checkType(value.geonameId);
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart(".geonameId");
            }
            throw e;
        }
        try {
            FfiConverterString.checkType(value.name);
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart(".name");
            }
            throw e;
        }
        try {
            FfiConverterF64.checkType(value.latitude);
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart(".latitude");
            }
            throw e;
        }
        try {
            FfiConverterF64.checkType(value.longitude);
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart(".longitude");
            }
            throw e;
        }
        try {
            FfiConverterString.checkType(value.countryCode);
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart(".countryCode");
            }
            throw e;
        }
        try {
            FfiConverterString.checkType(value.admin1Code);
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart(".admin1Code");
            }
            throw e;
        }
        try {
            FfiConverterU64.checkType(value.population);
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart(".population");
            }
            throw e;
        }
    }
}

/**
 * A fetched geoname with info on how it was matched.
 */
export class GeonameMatch {
    constructor({ geoname, matchType, prefix } = {}) {
        try {
            FfiConverterTypeGeoname.checkType(geoname)
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart("geoname");
            }
            throw e;
        }
        try {
            FfiConverterTypeGeonameMatchType.checkType(matchType)
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart("matchType");
            }
            throw e;
        }
        try {
            FfiConverterBool.checkType(prefix)
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart("prefix");
            }
            throw e;
        }
        /**
         * The geoname that was matched.
         * @type {Geoname}
         */
        this.geoname = geoname;
        /**
         * The type of name that was matched.
         * @type {GeonameMatchType}
         */
        this.matchType = matchType;
        /**
         * Whether the name was matched by prefix.
         * @type {Boolean}
         */
        this.prefix = prefix;
    }

    equals(other) {
        return (
            this.geoname.equals(other.geoname) &&
            this.matchType == other.matchType &&
            this.prefix == other.prefix
        )
    }
}

// Export the FFIConverter object to make external types work.
export class FfiConverterTypeGeonameMatch extends FfiConverterArrayBuffer {
    static read(dataStream) {
        return new GeonameMatch({
            geoname: FfiConverterTypeGeoname.read(dataStream),
            matchType: FfiConverterTypeGeonameMatchType.read(dataStream),
            prefix: FfiConverterBool.read(dataStream),
        });
    }
    static write(dataStream, value) {
        FfiConverterTypeGeoname.write(dataStream, value.geoname);
        FfiConverterTypeGeonameMatchType.write(dataStream, value.matchType);
        FfiConverterBool.write(dataStream, value.prefix);
    }

    static computeSize(value) {
        let totalSize = 0;
        totalSize += FfiConverterTypeGeoname.computeSize(value.geoname);
        totalSize += FfiConverterTypeGeonameMatchType.computeSize(value.matchType);
        totalSize += FfiConverterBool.computeSize(value.prefix);
        return totalSize
    }

    static checkType(value) {
        super.checkType(value);
        if (!(value instanceof GeonameMatch)) {
            throw new UniFFITypeError(`Expected 'GeonameMatch', found '${typeof value}'`);
        }
        try {
            FfiConverterTypeGeoname.checkType(value.geoname);
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart(".geoname");
            }
            throw e;
        }
        try {
            FfiConverterTypeGeonameMatchType.checkType(value.matchType);
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart(".matchType");
            }
            throw e;
        }
        try {
            FfiConverterBool.checkType(value.prefix);
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart(".prefix");
            }
            throw e;
        }
    }
}

/**
 * Single sample for a Glean labeled_timing_distribution
 */
export class LabeledTimingSample {
    constructor({ label, value } = {}) {
        try {
            FfiConverterString.checkType(label)
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart("label");
            }
            throw e;
        }
        try {
            FfiConverterU64.checkType(value)
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart("value");
            }
            throw e;
        }
        /**
         * @type {string}
         */
        this.label = label;
        /**
         * Time in microseconds
         * @type {number}
         */
        this.value = value;
    }

    equals(other) {
        return (
            this.label == other.label &&
            this.value == other.value
        )
    }
}

// Export the FFIConverter object to make external types work.
export class FfiConverterTypeLabeledTimingSample extends FfiConverterArrayBuffer {
    static read(dataStream) {
        return new LabeledTimingSample({
            label: FfiConverterString.read(dataStream),
            value: FfiConverterU64.read(dataStream),
        });
    }
    static write(dataStream, value) {
        FfiConverterString.write(dataStream, value.label);
        FfiConverterU64.write(dataStream, value.value);
    }

    static computeSize(value) {
        let totalSize = 0;
        totalSize += FfiConverterString.computeSize(value.label);
        totalSize += FfiConverterU64.computeSize(value.value);
        return totalSize
    }

    static checkType(value) {
        super.checkType(value);
        if (!(value instanceof LabeledTimingSample)) {
            throw new UniFFITypeError(`Expected 'LabeledTimingSample', found '${typeof value}'`);
        }
        try {
            FfiConverterString.checkType(value.label);
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart(".label");
            }
            throw e;
        }
        try {
            FfiConverterU64.checkType(value.value);
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart(".value");
            }
            throw e;
        }
    }
}

/**
 * QueryWithMetricsResult
 */
export class QueryWithMetricsResult {
    constructor({ suggestions, queryTimes } = {}) {
        try {
            FfiConverterSequenceTypeSuggestion.checkType(suggestions)
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart("suggestions");
            }
            throw e;
        }
        try {
            FfiConverterSequenceTypeLabeledTimingSample.checkType(queryTimes)
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart("queryTimes");
            }
            throw e;
        }
        /**
         * @type {Array.<Suggestion>}
         */
        this.suggestions = suggestions;
        /**
         * Samples for the `suggest.query_time` metric
         * @type {Array.<LabeledTimingSample>}
         */
        this.queryTimes = queryTimes;
    }

    equals(other) {
        return (
            this.suggestions == other.suggestions &&
            this.queryTimes == other.queryTimes
        )
    }
}

// Export the FFIConverter object to make external types work.
export class FfiConverterTypeQueryWithMetricsResult extends FfiConverterArrayBuffer {
    static read(dataStream) {
        return new QueryWithMetricsResult({
            suggestions: FfiConverterSequenceTypeSuggestion.read(dataStream),
            queryTimes: FfiConverterSequenceTypeLabeledTimingSample.read(dataStream),
        });
    }
    static write(dataStream, value) {
        FfiConverterSequenceTypeSuggestion.write(dataStream, value.suggestions);
        FfiConverterSequenceTypeLabeledTimingSample.write(dataStream, value.queryTimes);
    }

    static computeSize(value) {
        let totalSize = 0;
        totalSize += FfiConverterSequenceTypeSuggestion.computeSize(value.suggestions);
        totalSize += FfiConverterSequenceTypeLabeledTimingSample.computeSize(value.queryTimes);
        return totalSize
    }

    static checkType(value) {
        super.checkType(value);
        if (!(value instanceof QueryWithMetricsResult)) {
            throw new UniFFITypeError(`Expected 'QueryWithMetricsResult', found '${typeof value}'`);
        }
        try {
            FfiConverterSequenceTypeSuggestion.checkType(value.suggestions);
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart(".suggestions");
            }
            throw e;
        }
        try {
            FfiConverterSequenceTypeLabeledTimingSample.checkType(value.queryTimes);
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart(".queryTimes");
            }
            throw e;
        }
    }
}

/**
 * Global Suggest configuration data.
 */
export class SuggestGlobalConfig {
    constructor({ showLessFrequentlyCap } = {}) {
        try {
            FfiConverterI32.checkType(showLessFrequentlyCap)
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart("showLessFrequentlyCap");
            }
            throw e;
        }
        /**
         * @type {number}
         */
        this.showLessFrequentlyCap = showLessFrequentlyCap;
    }

    equals(other) {
        return (
            this.showLessFrequentlyCap == other.showLessFrequentlyCap
        )
    }
}

// Export the FFIConverter object to make external types work.
export class FfiConverterTypeSuggestGlobalConfig extends FfiConverterArrayBuffer {
    static read(dataStream) {
        return new SuggestGlobalConfig({
            showLessFrequentlyCap: FfiConverterI32.read(dataStream),
        });
    }
    static write(dataStream, value) {
        FfiConverterI32.write(dataStream, value.showLessFrequentlyCap);
    }

    static computeSize(value) {
        let totalSize = 0;
        totalSize += FfiConverterI32.computeSize(value.showLessFrequentlyCap);
        return totalSize
    }

    static checkType(value) {
        super.checkType(value);
        if (!(value instanceof SuggestGlobalConfig)) {
            throw new UniFFITypeError(`Expected 'SuggestGlobalConfig', found '${typeof value}'`);
        }
        try {
            FfiConverterI32.checkType(value.showLessFrequentlyCap);
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart(".showLessFrequentlyCap");
            }
            throw e;
        }
    }
}

/**
 * Constraints limit which suggestions to ingest from Remote Settings.
 */
export class SuggestIngestionConstraints {
    constructor({ providers = null, providerConstraints = null, emptyOnly = false } = {}) {
        try {
            FfiConverterOptionalSequenceTypeSuggestionProvider.checkType(providers)
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart("providers");
            }
            throw e;
        }
        try {
            FfiConverterOptionalTypeSuggestionProviderConstraints.checkType(providerConstraints)
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart("providerConstraints");
            }
            throw e;
        }
        try {
            FfiConverterBool.checkType(emptyOnly)
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart("emptyOnly");
            }
            throw e;
        }
        /**
         * @type {?Array.<SuggestionProvider>}
         */
        this.providers = providers;
        /**
         * @type {?SuggestionProviderConstraints}
         */
        this.providerConstraints = providerConstraints;
        /**
         * Only run ingestion if the table `suggestions` is empty
         *
         * @type {Boolean}
         */
        this.emptyOnly = emptyOnly;
    }

    equals(other) {
        return (
            this.providers == other.providers &&
            this.providerConstraints == other.providerConstraints &&
            this.emptyOnly == other.emptyOnly
        )
    }
}

// Export the FFIConverter object to make external types work.
export class FfiConverterTypeSuggestIngestionConstraints extends FfiConverterArrayBuffer {
    static read(dataStream) {
        return new SuggestIngestionConstraints({
            providers: FfiConverterOptionalSequenceTypeSuggestionProvider.read(dataStream),
            providerConstraints: FfiConverterOptionalTypeSuggestionProviderConstraints.read(dataStream),
            emptyOnly: FfiConverterBool.read(dataStream),
        });
    }
    static write(dataStream, value) {
        FfiConverterOptionalSequenceTypeSuggestionProvider.write(dataStream, value.providers);
        FfiConverterOptionalTypeSuggestionProviderConstraints.write(dataStream, value.providerConstraints);
        FfiConverterBool.write(dataStream, value.emptyOnly);
    }

    static computeSize(value) {
        let totalSize = 0;
        totalSize += FfiConverterOptionalSequenceTypeSuggestionProvider.computeSize(value.providers);
        totalSize += FfiConverterOptionalTypeSuggestionProviderConstraints.computeSize(value.providerConstraints);
        totalSize += FfiConverterBool.computeSize(value.emptyOnly);
        return totalSize
    }

    static checkType(value) {
        super.checkType(value);
        if (!(value instanceof SuggestIngestionConstraints)) {
            throw new UniFFITypeError(`Expected 'SuggestIngestionConstraints', found '${typeof value}'`);
        }
        try {
            FfiConverterOptionalSequenceTypeSuggestionProvider.checkType(value.providers);
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart(".providers");
            }
            throw e;
        }
        try {
            FfiConverterOptionalTypeSuggestionProviderConstraints.checkType(value.providerConstraints);
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart(".providerConstraints");
            }
            throw e;
        }
        try {
            FfiConverterBool.checkType(value.emptyOnly);
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart(".emptyOnly");
            }
            throw e;
        }
    }
}

/**
 * Ingestion metrics
 *
 * These are recorded during [crate::Store::ingest] and returned to the consumer to record.
 */
export class SuggestIngestionMetrics {
    constructor({ ingestionTimes, downloadTimes } = {}) {
        try {
            FfiConverterSequenceTypeLabeledTimingSample.checkType(ingestionTimes)
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart("ingestionTimes");
            }
            throw e;
        }
        try {
            FfiConverterSequenceTypeLabeledTimingSample.checkType(downloadTimes)
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart("downloadTimes");
            }
            throw e;
        }
        /**
         * Samples for the `suggest.ingestion_time` metric
         * @type {Array.<LabeledTimingSample>}
         */
        this.ingestionTimes = ingestionTimes;
        /**
         * Samples for the `suggest.ingestion_download_time` metric
         * @type {Array.<LabeledTimingSample>}
         */
        this.downloadTimes = downloadTimes;
    }

    equals(other) {
        return (
            this.ingestionTimes == other.ingestionTimes &&
            this.downloadTimes == other.downloadTimes
        )
    }
}

// Export the FFIConverter object to make external types work.
export class FfiConverterTypeSuggestIngestionMetrics extends FfiConverterArrayBuffer {
    static read(dataStream) {
        return new SuggestIngestionMetrics({
            ingestionTimes: FfiConverterSequenceTypeLabeledTimingSample.read(dataStream),
            downloadTimes: FfiConverterSequenceTypeLabeledTimingSample.read(dataStream),
        });
    }
    static write(dataStream, value) {
        FfiConverterSequenceTypeLabeledTimingSample.write(dataStream, value.ingestionTimes);
        FfiConverterSequenceTypeLabeledTimingSample.write(dataStream, value.downloadTimes);
    }

    static computeSize(value) {
        let totalSize = 0;
        totalSize += FfiConverterSequenceTypeLabeledTimingSample.computeSize(value.ingestionTimes);
        totalSize += FfiConverterSequenceTypeLabeledTimingSample.computeSize(value.downloadTimes);
        return totalSize
    }

    static checkType(value) {
        super.checkType(value);
        if (!(value instanceof SuggestIngestionMetrics)) {
            throw new UniFFITypeError(`Expected 'SuggestIngestionMetrics', found '${typeof value}'`);
        }
        try {
            FfiConverterSequenceTypeLabeledTimingSample.checkType(value.ingestionTimes);
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart(".ingestionTimes");
            }
            throw e;
        }
        try {
            FfiConverterSequenceTypeLabeledTimingSample.checkType(value.downloadTimes);
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart(".downloadTimes");
            }
            throw e;
        }
    }
}

/**
 * Some providers manage multiple suggestion subtypes. Queries, ingests, and
 * other operations on those providers must be constrained to a desired subtype.
 */
export class SuggestionProviderConstraints {
    constructor({ exposureSuggestionTypes = null } = {}) {
        try {
            FfiConverterOptionalSequencestring.checkType(exposureSuggestionTypes)
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart("exposureSuggestionTypes");
            }
            throw e;
        }
        /**
         * `Exposure` provider - For each desired exposure suggestion type, this
         * should contain the value of the `suggestion_type` field of its remote
         * settings record(s).
         * @type {?Array.<string>}
         */
        this.exposureSuggestionTypes = exposureSuggestionTypes;
    }

    equals(other) {
        return (
            this.exposureSuggestionTypes == other.exposureSuggestionTypes
        )
    }
}

// Export the FFIConverter object to make external types work.
export class FfiConverterTypeSuggestionProviderConstraints extends FfiConverterArrayBuffer {
    static read(dataStream) {
        return new SuggestionProviderConstraints({
            exposureSuggestionTypes: FfiConverterOptionalSequencestring.read(dataStream),
        });
    }
    static write(dataStream, value) {
        FfiConverterOptionalSequencestring.write(dataStream, value.exposureSuggestionTypes);
    }

    static computeSize(value) {
        let totalSize = 0;
        totalSize += FfiConverterOptionalSequencestring.computeSize(value.exposureSuggestionTypes);
        return totalSize
    }

    static checkType(value) {
        super.checkType(value);
        if (!(value instanceof SuggestionProviderConstraints)) {
            throw new UniFFITypeError(`Expected 'SuggestionProviderConstraints', found '${typeof value}'`);
        }
        try {
            FfiConverterOptionalSequencestring.checkType(value.exposureSuggestionTypes);
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart(".exposureSuggestionTypes");
            }
            throw e;
        }
    }
}

/**
 * A query for suggestions to show in the address bar.
 */
export class SuggestionQuery {
    constructor({ keyword, providers, providerConstraints = null, limit = null } = {}) {
        try {
            FfiConverterString.checkType(keyword)
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart("keyword");
            }
            throw e;
        }
        try {
            FfiConverterSequenceTypeSuggestionProvider.checkType(providers)
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart("providers");
            }
            throw e;
        }
        try {
            FfiConverterOptionalTypeSuggestionProviderConstraints.checkType(providerConstraints)
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart("providerConstraints");
            }
            throw e;
        }
        try {
            FfiConverterOptionali32.checkType(limit)
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart("limit");
            }
            throw e;
        }
        /**
         * @type {string}
         */
        this.keyword = keyword;
        /**
         * @type {Array.<SuggestionProvider>}
         */
        this.providers = providers;
        /**
         * @type {?SuggestionProviderConstraints}
         */
        this.providerConstraints = providerConstraints;
        /**
         * @type {?number}
         */
        this.limit = limit;
    }

    equals(other) {
        return (
            this.keyword == other.keyword &&
            this.providers == other.providers &&
            this.providerConstraints == other.providerConstraints &&
            this.limit == other.limit
        )
    }
}

// Export the FFIConverter object to make external types work.
export class FfiConverterTypeSuggestionQuery extends FfiConverterArrayBuffer {
    static read(dataStream) {
        return new SuggestionQuery({
            keyword: FfiConverterString.read(dataStream),
            providers: FfiConverterSequenceTypeSuggestionProvider.read(dataStream),
            providerConstraints: FfiConverterOptionalTypeSuggestionProviderConstraints.read(dataStream),
            limit: FfiConverterOptionali32.read(dataStream),
        });
    }
    static write(dataStream, value) {
        FfiConverterString.write(dataStream, value.keyword);
        FfiConverterSequenceTypeSuggestionProvider.write(dataStream, value.providers);
        FfiConverterOptionalTypeSuggestionProviderConstraints.write(dataStream, value.providerConstraints);
        FfiConverterOptionali32.write(dataStream, value.limit);
    }

    static computeSize(value) {
        let totalSize = 0;
        totalSize += FfiConverterString.computeSize(value.keyword);
        totalSize += FfiConverterSequenceTypeSuggestionProvider.computeSize(value.providers);
        totalSize += FfiConverterOptionalTypeSuggestionProviderConstraints.computeSize(value.providerConstraints);
        totalSize += FfiConverterOptionali32.computeSize(value.limit);
        return totalSize
    }

    static checkType(value) {
        super.checkType(value);
        if (!(value instanceof SuggestionQuery)) {
            throw new UniFFITypeError(`Expected 'SuggestionQuery', found '${typeof value}'`);
        }
        try {
            FfiConverterString.checkType(value.keyword);
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart(".keyword");
            }
            throw e;
        }
        try {
            FfiConverterSequenceTypeSuggestionProvider.checkType(value.providers);
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart(".providers");
            }
            throw e;
        }
        try {
            FfiConverterOptionalTypeSuggestionProviderConstraints.checkType(value.providerConstraints);
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart(".providerConstraints");
            }
            throw e;
        }
        try {
            FfiConverterOptionali32.checkType(value.limit);
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart(".limit");
            }
            throw e;
        }
    }
}


/**
 * GeonameMatchType
 */
export const GeonameMatchType = {
    /**
     * For U.S. states, abbreviations are the usual two-letter codes ("CA").
     */
    ABBREVIATION: 1,
    /**
     * AIRPORT_CODE
     */
    AIRPORT_CODE: 2,
    /**
     * This includes any names that aren't abbreviations or airport codes.
     */
    NAME: 3,
};

Object.freeze(GeonameMatchType);
// Export the FFIConverter object to make external types work.
export class FfiConverterTypeGeonameMatchType extends FfiConverterArrayBuffer {
    static read(dataStream) {
        switch (dataStream.readInt32()) {
            case 1:
                return GeonameMatchType.ABBREVIATION
            case 2:
                return GeonameMatchType.AIRPORT_CODE
            case 3:
                return GeonameMatchType.NAME
            default:
                throw new UniFFITypeError("Unknown GeonameMatchType variant");
        }
    }

    static write(dataStream, value) {
        if (value === GeonameMatchType.ABBREVIATION) {
            dataStream.writeInt32(1);
            return;
        }
        if (value === GeonameMatchType.AIRPORT_CODE) {
            dataStream.writeInt32(2);
            return;
        }
        if (value === GeonameMatchType.NAME) {
            dataStream.writeInt32(3);
            return;
        }
        throw new UniFFITypeError("Unknown GeonameMatchType variant");
    }

    static computeSize(value) {
        return 4;
    }

    static checkType(value) {
      if (!Number.isInteger(value) || value < 1 || value > 3) {
          throw new UniFFITypeError(`${value} is not a valid value for GeonameMatchType`);
      }
    }
}



/**
 * The type of a geoname.
 */
export const GeonameType = {
    /**
     * CITY
     */
    CITY: 1,
    /**
     * REGION
     */
    REGION: 2,
};

Object.freeze(GeonameType);
// Export the FFIConverter object to make external types work.
export class FfiConverterTypeGeonameType extends FfiConverterArrayBuffer {
    static read(dataStream) {
        switch (dataStream.readInt32()) {
            case 1:
                return GeonameType.CITY
            case 2:
                return GeonameType.REGION
            default:
                throw new UniFFITypeError("Unknown GeonameType variant");
        }
    }

    static write(dataStream, value) {
        if (value === GeonameType.CITY) {
            dataStream.writeInt32(1);
            return;
        }
        if (value === GeonameType.REGION) {
            dataStream.writeInt32(2);
            return;
        }
        throw new UniFFITypeError("Unknown GeonameType variant");
    }

    static computeSize(value) {
        return 4;
    }

    static checkType(value) {
      if (!Number.isInteger(value) || value < 1 || value > 2) {
          throw new UniFFITypeError(`${value} is not a valid value for GeonameType`);
      }
    }
}



/**
 * What should be interrupted when [SuggestStore::interrupt] is called?
 */
export const InterruptKind = {
    /**
     * Interrupt read operations like [SuggestStore::query]
     */
    READ: 1,
    /**
     * Interrupt write operations.  This mostly means [SuggestStore::ingest], but
     * [SuggestStore::dismiss_suggestion] may also be interrupted.
     */
    WRITE: 2,
    /**
     * Interrupt both read and write operations,
     */
    READ_WRITE: 3,
};

Object.freeze(InterruptKind);
// Export the FFIConverter object to make external types work.
export class FfiConverterTypeInterruptKind extends FfiConverterArrayBuffer {
    static read(dataStream) {
        switch (dataStream.readInt32()) {
            case 1:
                return InterruptKind.READ
            case 2:
                return InterruptKind.WRITE
            case 3:
                return InterruptKind.READ_WRITE
            default:
                throw new UniFFITypeError("Unknown InterruptKind variant");
        }
    }

    static write(dataStream, value) {
        if (value === InterruptKind.READ) {
            dataStream.writeInt32(1);
            return;
        }
        if (value === InterruptKind.WRITE) {
            dataStream.writeInt32(2);
            return;
        }
        if (value === InterruptKind.READ_WRITE) {
            dataStream.writeInt32(3);
            return;
        }
        throw new UniFFITypeError("Unknown InterruptKind variant");
    }

    static computeSize(value) {
        return 4;
    }

    static checkType(value) {
      if (!Number.isInteger(value) || value < 1 || value > 3) {
          throw new UniFFITypeError(`${value} is not a valid value for InterruptKind`);
      }
    }
}





/**
 * The error type for all Suggest component operations. These errors are
 * exposed to your application, which should handle them as needed.
 */
export class SuggestApiError extends Error {}


/**
 * Network
 */
export class Network extends SuggestApiError {

    constructor(
        reason,
        ...params
    ) {
        const message = `reason: ${ reason }`;
        super(message, ...params);
        this.reason = reason;
    }
    toString() {
        return `Network: ${super.toString()}`
    }
}

/**
 * The server requested a backoff after too many requests
 */
export class Backoff extends SuggestApiError {

    constructor(
        seconds,
        ...params
    ) {
        const message = `seconds: ${ seconds }`;
        super(message, ...params);
        this.seconds = seconds;
    }
    toString() {
        return `Backoff: ${super.toString()}`
    }
}

/**
 * An operation was interrupted by calling `SuggestStore.interrupt()`
 */
export class Interrupted extends SuggestApiError {

    constructor(
        ...params
    ) {
        super(...params);
    }
    toString() {
        return `Interrupted: ${super.toString()}`
    }
}

/**
 * Other
 */
export class Other extends SuggestApiError {

    constructor(
        reason,
        ...params
    ) {
        const message = `reason: ${ reason }`;
        super(message, ...params);
        this.reason = reason;
    }
    toString() {
        return `Other: ${super.toString()}`
    }
}

// Export the FFIConverter object to make external types work.
export class FfiConverterTypeSuggestApiError extends FfiConverterArrayBuffer {
    static read(dataStream) {
        switch (dataStream.readInt32()) {
            case 1:
                return new Network(
                    FfiConverterString.read(dataStream)
                    );
            case 2:
                return new Backoff(
                    FfiConverterU64.read(dataStream)
                    );
            case 3:
                return new Interrupted(
                    );
            case 4:
                return new Other(
                    FfiConverterString.read(dataStream)
                    );
            default:
                throw new UniFFITypeError("Unknown SuggestApiError variant");
        }
    }
    static computeSize(value) {
        // Size of the Int indicating the variant
        let totalSize = 4;
        if (value instanceof Network) {
            totalSize += FfiConverterString.computeSize(value.reason);
            return totalSize;
        }
        if (value instanceof Backoff) {
            totalSize += FfiConverterU64.computeSize(value.seconds);
            return totalSize;
        }
        if (value instanceof Interrupted) {
            return totalSize;
        }
        if (value instanceof Other) {
            totalSize += FfiConverterString.computeSize(value.reason);
            return totalSize;
        }
        throw new UniFFITypeError("Unknown SuggestApiError variant");
    }
    static write(dataStream, value) {
        if (value instanceof Network) {
            dataStream.writeInt32(1);
            FfiConverterString.write(dataStream, value.reason);
            return;
        }
        if (value instanceof Backoff) {
            dataStream.writeInt32(2);
            FfiConverterU64.write(dataStream, value.seconds);
            return;
        }
        if (value instanceof Interrupted) {
            dataStream.writeInt32(3);
            return;
        }
        if (value instanceof Other) {
            dataStream.writeInt32(4);
            FfiConverterString.write(dataStream, value.reason);
            return;
        }
        throw new UniFFITypeError("Unknown SuggestApiError variant");
    }

    static errorClass = SuggestApiError;
}


/**
 * Per-provider configuration data.
 */
export class SuggestProviderConfig {}
/**
 * Weather
 */
SuggestProviderConfig.Weather = class extends SuggestProviderConfig{
    constructor(
        score,
        minKeywordLength
        ) {
            super();
            this.score = score;
            this.minKeywordLength = minKeywordLength;
        }
}

// Export the FFIConverter object to make external types work.
export class FfiConverterTypeSuggestProviderConfig extends FfiConverterArrayBuffer {
    static read(dataStream) {
        switch (dataStream.readInt32()) {
            case 1:
                return new SuggestProviderConfig.Weather(
                    FfiConverterF64.read(dataStream),
                    FfiConverterI32.read(dataStream)
                    );
            default:
                throw new UniFFITypeError("Unknown SuggestProviderConfig variant");
        }
    }

    static write(dataStream, value) {
        if (value instanceof SuggestProviderConfig.Weather) {
            dataStream.writeInt32(1);
            FfiConverterF64.write(dataStream, value.score);
            FfiConverterI32.write(dataStream, value.minKeywordLength);
            return;
        }
        throw new UniFFITypeError("Unknown SuggestProviderConfig variant");
    }

    static computeSize(value) {
        // Size of the Int indicating the variant
        let totalSize = 4;
        if (value instanceof SuggestProviderConfig.Weather) {
            totalSize += FfiConverterF64.computeSize(value.score);
            totalSize += FfiConverterI32.computeSize(value.minKeywordLength);
            return totalSize;
        }
        throw new UniFFITypeError("Unknown SuggestProviderConfig variant");
    }

    static checkType(value) {
      if (!(value instanceof SuggestProviderConfig)) {
        throw new UniFFITypeError(`${value} is not a subclass instance of SuggestProviderConfig`);
      }
    }
}



/**
 * A suggestion from the database to show in the address bar.
 */
export class Suggestion {}
/**
 * Amp
 */
Suggestion.Amp = class extends Suggestion{
    constructor(
        title,
        url,
        rawUrl,
        icon,
        iconMimetype,
        fullKeyword,
        blockId,
        advertiser,
        iabCategory,
        impressionUrl,
        clickUrl,
        rawClickUrl,
        score
        ) {
            super();
            this.title = title;
            this.url = url;
            this.rawUrl = rawUrl;
            this.icon = icon;
            this.iconMimetype = iconMimetype;
            this.fullKeyword = fullKeyword;
            this.blockId = blockId;
            this.advertiser = advertiser;
            this.iabCategory = iabCategory;
            this.impressionUrl = impressionUrl;
            this.clickUrl = clickUrl;
            this.rawClickUrl = rawClickUrl;
            this.score = score;
        }
}
/**
 * Pocket
 */
Suggestion.Pocket = class extends Suggestion{
    constructor(
        title,
        url,
        score,
        isTopPick
        ) {
            super();
            this.title = title;
            this.url = url;
            this.score = score;
            this.isTopPick = isTopPick;
        }
}
/**
 * Wikipedia
 */
Suggestion.Wikipedia = class extends Suggestion{
    constructor(
        title,
        url,
        icon,
        iconMimetype,
        fullKeyword
        ) {
            super();
            this.title = title;
            this.url = url;
            this.icon = icon;
            this.iconMimetype = iconMimetype;
            this.fullKeyword = fullKeyword;
        }
}
/**
 * Amo
 */
Suggestion.Amo = class extends Suggestion{
    constructor(
        title,
        url,
        iconUrl,
        description,
        rating,
        numberOfRatings,
        guid,
        score
        ) {
            super();
            this.title = title;
            this.url = url;
            this.iconUrl = iconUrl;
            this.description = description;
            this.rating = rating;
            this.numberOfRatings = numberOfRatings;
            this.guid = guid;
            this.score = score;
        }
}
/**
 * Yelp
 */
Suggestion.Yelp = class extends Suggestion{
    constructor(
        url,
        title,
        icon,
        iconMimetype,
        score,
        hasLocationSign,
        subjectExactMatch,
        locationParam
        ) {
            super();
            this.url = url;
            this.title = title;
            this.icon = icon;
            this.iconMimetype = iconMimetype;
            this.score = score;
            this.hasLocationSign = hasLocationSign;
            this.subjectExactMatch = subjectExactMatch;
            this.locationParam = locationParam;
        }
}
/**
 * Mdn
 */
Suggestion.Mdn = class extends Suggestion{
    constructor(
        title,
        url,
        description,
        score
        ) {
            super();
            this.title = title;
            this.url = url;
            this.description = description;
            this.score = score;
        }
}
/**
 * Weather
 */
Suggestion.Weather = class extends Suggestion{
    constructor(
        city,
        region,
        country,
        latitude,
        longitude,
        score
        ) {
            super();
            this.city = city;
            this.region = region;
            this.country = country;
            this.latitude = latitude;
            this.longitude = longitude;
            this.score = score;
        }
}
/**
 * Fakespot
 */
Suggestion.Fakespot = class extends Suggestion{
    constructor(
        fakespotGrade,
        productId,
        rating,
        title,
        totalReviews,
        url,
        icon,
        iconMimetype,
        score
        ) {
            super();
            this.fakespotGrade = fakespotGrade;
            this.productId = productId;
            this.rating = rating;
            this.title = title;
            this.totalReviews = totalReviews;
            this.url = url;
            this.icon = icon;
            this.iconMimetype = iconMimetype;
            this.score = score;
        }
}
/**
 * Exposure
 */
Suggestion.Exposure = class extends Suggestion{
    constructor(
        suggestionType,
        score
        ) {
            super();
            this.suggestionType = suggestionType;
            this.score = score;
        }
}

// Export the FFIConverter object to make external types work.
export class FfiConverterTypeSuggestion extends FfiConverterArrayBuffer {
    static read(dataStream) {
        switch (dataStream.readInt32()) {
            case 1:
                return new Suggestion.Amp(
                    FfiConverterString.read(dataStream),
                    FfiConverterString.read(dataStream),
                    FfiConverterString.read(dataStream),
                    FfiConverterOptionalbytes.read(dataStream),
                    FfiConverterOptionalstring.read(dataStream),
                    FfiConverterString.read(dataStream),
                    FfiConverterI64.read(dataStream),
                    FfiConverterString.read(dataStream),
                    FfiConverterString.read(dataStream),
                    FfiConverterString.read(dataStream),
                    FfiConverterString.read(dataStream),
                    FfiConverterString.read(dataStream),
                    FfiConverterF64.read(dataStream)
                    );
            case 2:
                return new Suggestion.Pocket(
                    FfiConverterString.read(dataStream),
                    FfiConverterString.read(dataStream),
                    FfiConverterF64.read(dataStream),
                    FfiConverterBool.read(dataStream)
                    );
            case 3:
                return new Suggestion.Wikipedia(
                    FfiConverterString.read(dataStream),
                    FfiConverterString.read(dataStream),
                    FfiConverterOptionalbytes.read(dataStream),
                    FfiConverterOptionalstring.read(dataStream),
                    FfiConverterString.read(dataStream)
                    );
            case 4:
                return new Suggestion.Amo(
                    FfiConverterString.read(dataStream),
                    FfiConverterString.read(dataStream),
                    FfiConverterString.read(dataStream),
                    FfiConverterString.read(dataStream),
                    FfiConverterOptionalstring.read(dataStream),
                    FfiConverterI64.read(dataStream),
                    FfiConverterString.read(dataStream),
                    FfiConverterF64.read(dataStream)
                    );
            case 5:
                return new Suggestion.Yelp(
                    FfiConverterString.read(dataStream),
                    FfiConverterString.read(dataStream),
                    FfiConverterOptionalbytes.read(dataStream),
                    FfiConverterOptionalstring.read(dataStream),
                    FfiConverterF64.read(dataStream),
                    FfiConverterBool.read(dataStream),
                    FfiConverterBool.read(dataStream),
                    FfiConverterString.read(dataStream)
                    );
            case 6:
                return new Suggestion.Mdn(
                    FfiConverterString.read(dataStream),
                    FfiConverterString.read(dataStream),
                    FfiConverterString.read(dataStream),
                    FfiConverterF64.read(dataStream)
                    );
            case 7:
                return new Suggestion.Weather(
                    FfiConverterOptionalstring.read(dataStream),
                    FfiConverterOptionalstring.read(dataStream),
                    FfiConverterOptionalstring.read(dataStream),
                    FfiConverterOptionalf64.read(dataStream),
                    FfiConverterOptionalf64.read(dataStream),
                    FfiConverterF64.read(dataStream)
                    );
            case 8:
                return new Suggestion.Fakespot(
                    FfiConverterString.read(dataStream),
                    FfiConverterString.read(dataStream),
                    FfiConverterF64.read(dataStream),
                    FfiConverterString.read(dataStream),
                    FfiConverterI64.read(dataStream),
                    FfiConverterString.read(dataStream),
                    FfiConverterOptionalbytes.read(dataStream),
                    FfiConverterOptionalstring.read(dataStream),
                    FfiConverterF64.read(dataStream)
                    );
            case 9:
                return new Suggestion.Exposure(
                    FfiConverterString.read(dataStream),
                    FfiConverterF64.read(dataStream)
                    );
            default:
                throw new UniFFITypeError("Unknown Suggestion variant");
        }
    }

    static write(dataStream, value) {
        if (value instanceof Suggestion.Amp) {
            dataStream.writeInt32(1);
            FfiConverterString.write(dataStream, value.title);
            FfiConverterString.write(dataStream, value.url);
            FfiConverterString.write(dataStream, value.rawUrl);
            FfiConverterOptionalbytes.write(dataStream, value.icon);
            FfiConverterOptionalstring.write(dataStream, value.iconMimetype);
            FfiConverterString.write(dataStream, value.fullKeyword);
            FfiConverterI64.write(dataStream, value.blockId);
            FfiConverterString.write(dataStream, value.advertiser);
            FfiConverterString.write(dataStream, value.iabCategory);
            FfiConverterString.write(dataStream, value.impressionUrl);
            FfiConverterString.write(dataStream, value.clickUrl);
            FfiConverterString.write(dataStream, value.rawClickUrl);
            FfiConverterF64.write(dataStream, value.score);
            return;
        }
        if (value instanceof Suggestion.Pocket) {
            dataStream.writeInt32(2);
            FfiConverterString.write(dataStream, value.title);
            FfiConverterString.write(dataStream, value.url);
            FfiConverterF64.write(dataStream, value.score);
            FfiConverterBool.write(dataStream, value.isTopPick);
            return;
        }
        if (value instanceof Suggestion.Wikipedia) {
            dataStream.writeInt32(3);
            FfiConverterString.write(dataStream, value.title);
            FfiConverterString.write(dataStream, value.url);
            FfiConverterOptionalbytes.write(dataStream, value.icon);
            FfiConverterOptionalstring.write(dataStream, value.iconMimetype);
            FfiConverterString.write(dataStream, value.fullKeyword);
            return;
        }
        if (value instanceof Suggestion.Amo) {
            dataStream.writeInt32(4);
            FfiConverterString.write(dataStream, value.title);
            FfiConverterString.write(dataStream, value.url);
            FfiConverterString.write(dataStream, value.iconUrl);
            FfiConverterString.write(dataStream, value.description);
            FfiConverterOptionalstring.write(dataStream, value.rating);
            FfiConverterI64.write(dataStream, value.numberOfRatings);
            FfiConverterString.write(dataStream, value.guid);
            FfiConverterF64.write(dataStream, value.score);
            return;
        }
        if (value instanceof Suggestion.Yelp) {
            dataStream.writeInt32(5);
            FfiConverterString.write(dataStream, value.url);
            FfiConverterString.write(dataStream, value.title);
            FfiConverterOptionalbytes.write(dataStream, value.icon);
            FfiConverterOptionalstring.write(dataStream, value.iconMimetype);
            FfiConverterF64.write(dataStream, value.score);
            FfiConverterBool.write(dataStream, value.hasLocationSign);
            FfiConverterBool.write(dataStream, value.subjectExactMatch);
            FfiConverterString.write(dataStream, value.locationParam);
            return;
        }
        if (value instanceof Suggestion.Mdn) {
            dataStream.writeInt32(6);
            FfiConverterString.write(dataStream, value.title);
            FfiConverterString.write(dataStream, value.url);
            FfiConverterString.write(dataStream, value.description);
            FfiConverterF64.write(dataStream, value.score);
            return;
        }
        if (value instanceof Suggestion.Weather) {
            dataStream.writeInt32(7);
            FfiConverterOptionalstring.write(dataStream, value.city);
            FfiConverterOptionalstring.write(dataStream, value.region);
            FfiConverterOptionalstring.write(dataStream, value.country);
            FfiConverterOptionalf64.write(dataStream, value.latitude);
            FfiConverterOptionalf64.write(dataStream, value.longitude);
            FfiConverterF64.write(dataStream, value.score);
            return;
        }
        if (value instanceof Suggestion.Fakespot) {
            dataStream.writeInt32(8);
            FfiConverterString.write(dataStream, value.fakespotGrade);
            FfiConverterString.write(dataStream, value.productId);
            FfiConverterF64.write(dataStream, value.rating);
            FfiConverterString.write(dataStream, value.title);
            FfiConverterI64.write(dataStream, value.totalReviews);
            FfiConverterString.write(dataStream, value.url);
            FfiConverterOptionalbytes.write(dataStream, value.icon);
            FfiConverterOptionalstring.write(dataStream, value.iconMimetype);
            FfiConverterF64.write(dataStream, value.score);
            return;
        }
        if (value instanceof Suggestion.Exposure) {
            dataStream.writeInt32(9);
            FfiConverterString.write(dataStream, value.suggestionType);
            FfiConverterF64.write(dataStream, value.score);
            return;
        }
        throw new UniFFITypeError("Unknown Suggestion variant");
    }

    static computeSize(value) {
        // Size of the Int indicating the variant
        let totalSize = 4;
        if (value instanceof Suggestion.Amp) {
            totalSize += FfiConverterString.computeSize(value.title);
            totalSize += FfiConverterString.computeSize(value.url);
            totalSize += FfiConverterString.computeSize(value.rawUrl);
            totalSize += FfiConverterOptionalbytes.computeSize(value.icon);
            totalSize += FfiConverterOptionalstring.computeSize(value.iconMimetype);
            totalSize += FfiConverterString.computeSize(value.fullKeyword);
            totalSize += FfiConverterI64.computeSize(value.blockId);
            totalSize += FfiConverterString.computeSize(value.advertiser);
            totalSize += FfiConverterString.computeSize(value.iabCategory);
            totalSize += FfiConverterString.computeSize(value.impressionUrl);
            totalSize += FfiConverterString.computeSize(value.clickUrl);
            totalSize += FfiConverterString.computeSize(value.rawClickUrl);
            totalSize += FfiConverterF64.computeSize(value.score);
            return totalSize;
        }
        if (value instanceof Suggestion.Pocket) {
            totalSize += FfiConverterString.computeSize(value.title);
            totalSize += FfiConverterString.computeSize(value.url);
            totalSize += FfiConverterF64.computeSize(value.score);
            totalSize += FfiConverterBool.computeSize(value.isTopPick);
            return totalSize;
        }
        if (value instanceof Suggestion.Wikipedia) {
            totalSize += FfiConverterString.computeSize(value.title);
            totalSize += FfiConverterString.computeSize(value.url);
            totalSize += FfiConverterOptionalbytes.computeSize(value.icon);
            totalSize += FfiConverterOptionalstring.computeSize(value.iconMimetype);
            totalSize += FfiConverterString.computeSize(value.fullKeyword);
            return totalSize;
        }
        if (value instanceof Suggestion.Amo) {
            totalSize += FfiConverterString.computeSize(value.title);
            totalSize += FfiConverterString.computeSize(value.url);
            totalSize += FfiConverterString.computeSize(value.iconUrl);
            totalSize += FfiConverterString.computeSize(value.description);
            totalSize += FfiConverterOptionalstring.computeSize(value.rating);
            totalSize += FfiConverterI64.computeSize(value.numberOfRatings);
            totalSize += FfiConverterString.computeSize(value.guid);
            totalSize += FfiConverterF64.computeSize(value.score);
            return totalSize;
        }
        if (value instanceof Suggestion.Yelp) {
            totalSize += FfiConverterString.computeSize(value.url);
            totalSize += FfiConverterString.computeSize(value.title);
            totalSize += FfiConverterOptionalbytes.computeSize(value.icon);
            totalSize += FfiConverterOptionalstring.computeSize(value.iconMimetype);
            totalSize += FfiConverterF64.computeSize(value.score);
            totalSize += FfiConverterBool.computeSize(value.hasLocationSign);
            totalSize += FfiConverterBool.computeSize(value.subjectExactMatch);
            totalSize += FfiConverterString.computeSize(value.locationParam);
            return totalSize;
        }
        if (value instanceof Suggestion.Mdn) {
            totalSize += FfiConverterString.computeSize(value.title);
            totalSize += FfiConverterString.computeSize(value.url);
            totalSize += FfiConverterString.computeSize(value.description);
            totalSize += FfiConverterF64.computeSize(value.score);
            return totalSize;
        }
        if (value instanceof Suggestion.Weather) {
            totalSize += FfiConverterOptionalstring.computeSize(value.city);
            totalSize += FfiConverterOptionalstring.computeSize(value.region);
            totalSize += FfiConverterOptionalstring.computeSize(value.country);
            totalSize += FfiConverterOptionalf64.computeSize(value.latitude);
            totalSize += FfiConverterOptionalf64.computeSize(value.longitude);
            totalSize += FfiConverterF64.computeSize(value.score);
            return totalSize;
        }
        if (value instanceof Suggestion.Fakespot) {
            totalSize += FfiConverterString.computeSize(value.fakespotGrade);
            totalSize += FfiConverterString.computeSize(value.productId);
            totalSize += FfiConverterF64.computeSize(value.rating);
            totalSize += FfiConverterString.computeSize(value.title);
            totalSize += FfiConverterI64.computeSize(value.totalReviews);
            totalSize += FfiConverterString.computeSize(value.url);
            totalSize += FfiConverterOptionalbytes.computeSize(value.icon);
            totalSize += FfiConverterOptionalstring.computeSize(value.iconMimetype);
            totalSize += FfiConverterF64.computeSize(value.score);
            return totalSize;
        }
        if (value instanceof Suggestion.Exposure) {
            totalSize += FfiConverterString.computeSize(value.suggestionType);
            totalSize += FfiConverterF64.computeSize(value.score);
            return totalSize;
        }
        throw new UniFFITypeError("Unknown Suggestion variant");
    }

    static checkType(value) {
      if (!(value instanceof Suggestion)) {
        throw new UniFFITypeError(`${value} is not a subclass instance of Suggestion`);
      }
    }
}



/**
 * A provider is a source of search suggestions.
 */
export const SuggestionProvider = {
    /**
     * AMP
     */
    AMP: 1,
    /**
     * WIKIPEDIA
     */
    WIKIPEDIA: 2,
    /**
     * AMO
     */
    AMO: 3,
    /**
     * POCKET
     */
    POCKET: 4,
    /**
     * YELP
     */
    YELP: 5,
    /**
     * MDN
     */
    MDN: 6,
    /**
     * WEATHER
     */
    WEATHER: 7,
    /**
     * AMP_MOBILE
     */
    AMP_MOBILE: 8,
    /**
     * FAKESPOT
     */
    FAKESPOT: 9,
    /**
     * EXPOSURE
     */
    EXPOSURE: 10,
};

Object.freeze(SuggestionProvider);
// Export the FFIConverter object to make external types work.
export class FfiConverterTypeSuggestionProvider extends FfiConverterArrayBuffer {
    static read(dataStream) {
        switch (dataStream.readInt32()) {
            case 1:
                return SuggestionProvider.AMP
            case 2:
                return SuggestionProvider.WIKIPEDIA
            case 3:
                return SuggestionProvider.AMO
            case 4:
                return SuggestionProvider.POCKET
            case 5:
                return SuggestionProvider.YELP
            case 6:
                return SuggestionProvider.MDN
            case 7:
                return SuggestionProvider.WEATHER
            case 8:
                return SuggestionProvider.AMP_MOBILE
            case 9:
                return SuggestionProvider.FAKESPOT
            case 10:
                return SuggestionProvider.EXPOSURE
            default:
                throw new UniFFITypeError("Unknown SuggestionProvider variant");
        }
    }

    static write(dataStream, value) {
        if (value === SuggestionProvider.AMP) {
            dataStream.writeInt32(1);
            return;
        }
        if (value === SuggestionProvider.WIKIPEDIA) {
            dataStream.writeInt32(2);
            return;
        }
        if (value === SuggestionProvider.AMO) {
            dataStream.writeInt32(3);
            return;
        }
        if (value === SuggestionProvider.POCKET) {
            dataStream.writeInt32(4);
            return;
        }
        if (value === SuggestionProvider.YELP) {
            dataStream.writeInt32(5);
            return;
        }
        if (value === SuggestionProvider.MDN) {
            dataStream.writeInt32(6);
            return;
        }
        if (value === SuggestionProvider.WEATHER) {
            dataStream.writeInt32(7);
            return;
        }
        if (value === SuggestionProvider.AMP_MOBILE) {
            dataStream.writeInt32(8);
            return;
        }
        if (value === SuggestionProvider.FAKESPOT) {
            dataStream.writeInt32(9);
            return;
        }
        if (value === SuggestionProvider.EXPOSURE) {
            dataStream.writeInt32(10);
            return;
        }
        throw new UniFFITypeError("Unknown SuggestionProvider variant");
    }

    static computeSize(value) {
        return 4;
    }

    static checkType(value) {
      if (!Number.isInteger(value) || value < 1 || value > 10) {
          throw new UniFFITypeError(`${value} is not a valid value for SuggestionProvider`);
      }
    }
}


// Export the FFIConverter object to make external types work.
export class FfiConverterOptionali32 extends FfiConverterArrayBuffer {
    static checkType(value) {
        if (value !== undefined && value !== null) {
            FfiConverterI32.checkType(value)
        }
    }

    static read(dataStream) {
        const code = dataStream.readUint8(0);
        switch (code) {
            case 0:
                return null
            case 1:
                return FfiConverterI32.read(dataStream)
            default:
                throw UniFFIError(`Unexpected code: ${code}`);
        }
    }

    static write(dataStream, value) {
        if (value === null || value === undefined) {
            dataStream.writeUint8(0);
            return;
        }
        dataStream.writeUint8(1);
        FfiConverterI32.write(dataStream, value)
    }

    static computeSize(value) {
        if (value === null || value === undefined) {
            return 1;
        }
        return 1 + FfiConverterI32.computeSize(value)
    }
}

// Export the FFIConverter object to make external types work.
export class FfiConverterOptionalf64 extends FfiConverterArrayBuffer {
    static checkType(value) {
        if (value !== undefined && value !== null) {
            FfiConverterF64.checkType(value)
        }
    }

    static read(dataStream) {
        const code = dataStream.readUint8(0);
        switch (code) {
            case 0:
                return null
            case 1:
                return FfiConverterF64.read(dataStream)
            default:
                throw UniFFIError(`Unexpected code: ${code}`);
        }
    }

    static write(dataStream, value) {
        if (value === null || value === undefined) {
            dataStream.writeUint8(0);
            return;
        }
        dataStream.writeUint8(1);
        FfiConverterF64.write(dataStream, value)
    }

    static computeSize(value) {
        if (value === null || value === undefined) {
            return 1;
        }
        return 1 + FfiConverterF64.computeSize(value)
    }
}

// Export the FFIConverter object to make external types work.
export class FfiConverterOptionalstring extends FfiConverterArrayBuffer {
    static checkType(value) {
        if (value !== undefined && value !== null) {
            FfiConverterString.checkType(value)
        }
    }

    static read(dataStream) {
        const code = dataStream.readUint8(0);
        switch (code) {
            case 0:
                return null
            case 1:
                return FfiConverterString.read(dataStream)
            default:
                throw UniFFIError(`Unexpected code: ${code}`);
        }
    }

    static write(dataStream, value) {
        if (value === null || value === undefined) {
            dataStream.writeUint8(0);
            return;
        }
        dataStream.writeUint8(1);
        FfiConverterString.write(dataStream, value)
    }

    static computeSize(value) {
        if (value === null || value === undefined) {
            return 1;
        }
        return 1 + FfiConverterString.computeSize(value)
    }
}

// Export the FFIConverter object to make external types work.
export class FfiConverterOptionalbytes extends FfiConverterArrayBuffer {
    static checkType(value) {
        if (value !== undefined && value !== null) {
            FfiConverterBytes.checkType(value)
        }
    }

    static read(dataStream) {
        const code = dataStream.readUint8(0);
        switch (code) {
            case 0:
                return null
            case 1:
                return FfiConverterBytes.read(dataStream)
            default:
                throw UniFFIError(`Unexpected code: ${code}`);
        }
    }

    static write(dataStream, value) {
        if (value === null || value === undefined) {
            dataStream.writeUint8(0);
            return;
        }
        dataStream.writeUint8(1);
        FfiConverterBytes.write(dataStream, value)
    }

    static computeSize(value) {
        if (value === null || value === undefined) {
            return 1;
        }
        return 1 + FfiConverterBytes.computeSize(value)
    }
}

// Export the FFIConverter object to make external types work.
export class FfiConverterOptionalTypeSuggestionProviderConstraints extends FfiConverterArrayBuffer {
    static checkType(value) {
        if (value !== undefined && value !== null) {
            FfiConverterTypeSuggestionProviderConstraints.checkType(value)
        }
    }

    static read(dataStream) {
        const code = dataStream.readUint8(0);
        switch (code) {
            case 0:
                return null
            case 1:
                return FfiConverterTypeSuggestionProviderConstraints.read(dataStream)
            default:
                throw UniFFIError(`Unexpected code: ${code}`);
        }
    }

    static write(dataStream, value) {
        if (value === null || value === undefined) {
            dataStream.writeUint8(0);
            return;
        }
        dataStream.writeUint8(1);
        FfiConverterTypeSuggestionProviderConstraints.write(dataStream, value)
    }

    static computeSize(value) {
        if (value === null || value === undefined) {
            return 1;
        }
        return 1 + FfiConverterTypeSuggestionProviderConstraints.computeSize(value)
    }
}

// Export the FFIConverter object to make external types work.
export class FfiConverterOptionalTypeGeonameType extends FfiConverterArrayBuffer {
    static checkType(value) {
        if (value !== undefined && value !== null) {
            FfiConverterTypeGeonameType.checkType(value)
        }
    }

    static read(dataStream) {
        const code = dataStream.readUint8(0);
        switch (code) {
            case 0:
                return null
            case 1:
                return FfiConverterTypeGeonameType.read(dataStream)
            default:
                throw UniFFIError(`Unexpected code: ${code}`);
        }
    }

    static write(dataStream, value) {
        if (value === null || value === undefined) {
            dataStream.writeUint8(0);
            return;
        }
        dataStream.writeUint8(1);
        FfiConverterTypeGeonameType.write(dataStream, value)
    }

    static computeSize(value) {
        if (value === null || value === undefined) {
            return 1;
        }
        return 1 + FfiConverterTypeGeonameType.computeSize(value)
    }
}

// Export the FFIConverter object to make external types work.
export class FfiConverterOptionalTypeInterruptKind extends FfiConverterArrayBuffer {
    static checkType(value) {
        if (value !== undefined && value !== null) {
            FfiConverterTypeInterruptKind.checkType(value)
        }
    }

    static read(dataStream) {
        const code = dataStream.readUint8(0);
        switch (code) {
            case 0:
                return null
            case 1:
                return FfiConverterTypeInterruptKind.read(dataStream)
            default:
                throw UniFFIError(`Unexpected code: ${code}`);
        }
    }

    static write(dataStream, value) {
        if (value === null || value === undefined) {
            dataStream.writeUint8(0);
            return;
        }
        dataStream.writeUint8(1);
        FfiConverterTypeInterruptKind.write(dataStream, value)
    }

    static computeSize(value) {
        if (value === null || value === undefined) {
            return 1;
        }
        return 1 + FfiConverterTypeInterruptKind.computeSize(value)
    }
}

// Export the FFIConverter object to make external types work.
export class FfiConverterOptionalTypeSuggestProviderConfig extends FfiConverterArrayBuffer {
    static checkType(value) {
        if (value !== undefined && value !== null) {
            FfiConverterTypeSuggestProviderConfig.checkType(value)
        }
    }

    static read(dataStream) {
        const code = dataStream.readUint8(0);
        switch (code) {
            case 0:
                return null
            case 1:
                return FfiConverterTypeSuggestProviderConfig.read(dataStream)
            default:
                throw UniFFIError(`Unexpected code: ${code}`);
        }
    }

    static write(dataStream, value) {
        if (value === null || value === undefined) {
            dataStream.writeUint8(0);
            return;
        }
        dataStream.writeUint8(1);
        FfiConverterTypeSuggestProviderConfig.write(dataStream, value)
    }

    static computeSize(value) {
        if (value === null || value === undefined) {
            return 1;
        }
        return 1 + FfiConverterTypeSuggestProviderConfig.computeSize(value)
    }
}

// Export the FFIConverter object to make external types work.
export class FfiConverterOptionalSequencestring extends FfiConverterArrayBuffer {
    static checkType(value) {
        if (value !== undefined && value !== null) {
            FfiConverterSequencestring.checkType(value)
        }
    }

    static read(dataStream) {
        const code = dataStream.readUint8(0);
        switch (code) {
            case 0:
                return null
            case 1:
                return FfiConverterSequencestring.read(dataStream)
            default:
                throw UniFFIError(`Unexpected code: ${code}`);
        }
    }

    static write(dataStream, value) {
        if (value === null || value === undefined) {
            dataStream.writeUint8(0);
            return;
        }
        dataStream.writeUint8(1);
        FfiConverterSequencestring.write(dataStream, value)
    }

    static computeSize(value) {
        if (value === null || value === undefined) {
            return 1;
        }
        return 1 + FfiConverterSequencestring.computeSize(value)
    }
}

// Export the FFIConverter object to make external types work.
export class FfiConverterOptionalSequenceTypeGeoname extends FfiConverterArrayBuffer {
    static checkType(value) {
        if (value !== undefined && value !== null) {
            FfiConverterSequenceTypeGeoname.checkType(value)
        }
    }

    static read(dataStream) {
        const code = dataStream.readUint8(0);
        switch (code) {
            case 0:
                return null
            case 1:
                return FfiConverterSequenceTypeGeoname.read(dataStream)
            default:
                throw UniFFIError(`Unexpected code: ${code}`);
        }
    }

    static write(dataStream, value) {
        if (value === null || value === undefined) {
            dataStream.writeUint8(0);
            return;
        }
        dataStream.writeUint8(1);
        FfiConverterSequenceTypeGeoname.write(dataStream, value)
    }

    static computeSize(value) {
        if (value === null || value === undefined) {
            return 1;
        }
        return 1 + FfiConverterSequenceTypeGeoname.computeSize(value)
    }
}

// Export the FFIConverter object to make external types work.
export class FfiConverterOptionalSequenceTypeSuggestionProvider extends FfiConverterArrayBuffer {
    static checkType(value) {
        if (value !== undefined && value !== null) {
            FfiConverterSequenceTypeSuggestionProvider.checkType(value)
        }
    }

    static read(dataStream) {
        const code = dataStream.readUint8(0);
        switch (code) {
            case 0:
                return null
            case 1:
                return FfiConverterSequenceTypeSuggestionProvider.read(dataStream)
            default:
                throw UniFFIError(`Unexpected code: ${code}`);
        }
    }

    static write(dataStream, value) {
        if (value === null || value === undefined) {
            dataStream.writeUint8(0);
            return;
        }
        dataStream.writeUint8(1);
        FfiConverterSequenceTypeSuggestionProvider.write(dataStream, value)
    }

    static computeSize(value) {
        if (value === null || value === undefined) {
            return 1;
        }
        return 1 + FfiConverterSequenceTypeSuggestionProvider.computeSize(value)
    }
}

// Export the FFIConverter object to make external types work.
export class FfiConverterOptionalTypeRemoteSettingsConfig extends FfiConverterArrayBuffer {
    static checkType(value) {
        if (value !== undefined && value !== null) {
            FfiConverterTypeRemoteSettingsConfig.checkType(value)
        }
    }

    static read(dataStream) {
        const code = dataStream.readUint8(0);
        switch (code) {
            case 0:
                return null
            case 1:
                return FfiConverterTypeRemoteSettingsConfig.read(dataStream)
            default:
                throw UniFFIError(`Unexpected code: ${code}`);
        }
    }

    static write(dataStream, value) {
        if (value === null || value === undefined) {
            dataStream.writeUint8(0);
            return;
        }
        dataStream.writeUint8(1);
        FfiConverterTypeRemoteSettingsConfig.write(dataStream, value)
    }

    static computeSize(value) {
        if (value === null || value === undefined) {
            return 1;
        }
        return 1 + FfiConverterTypeRemoteSettingsConfig.computeSize(value)
    }
}

// Export the FFIConverter object to make external types work.
export class FfiConverterSequencestring extends FfiConverterArrayBuffer {
    static read(dataStream) {
        const len = dataStream.readInt32();
        const arr = [];
        for (let i = 0; i < len; i++) {
            arr.push(FfiConverterString.read(dataStream));
        }
        return arr;
    }

    static write(dataStream, value) {
        dataStream.writeInt32(value.length);
        value.forEach((innerValue) => {
            FfiConverterString.write(dataStream, innerValue);
        })
    }

    static computeSize(value) {
        // The size of the length
        let size = 4;
        for (const innerValue of value) {
            size += FfiConverterString.computeSize(innerValue);
        }
        return size;
    }

    static checkType(value) {
        if (!Array.isArray(value)) {
            throw new UniFFITypeError(`${value} is not an array`);
        }
        value.forEach((innerValue, idx) => {
            try {
                FfiConverterString.checkType(innerValue);
            } catch (e) {
                if (e instanceof UniFFITypeError) {
                    e.addItemDescriptionPart(`[${idx}]`);
                }
                throw e;
            }
        })
    }
}

// Export the FFIConverter object to make external types work.
export class FfiConverterSequenceTypeGeoname extends FfiConverterArrayBuffer {
    static read(dataStream) {
        const len = dataStream.readInt32();
        const arr = [];
        for (let i = 0; i < len; i++) {
            arr.push(FfiConverterTypeGeoname.read(dataStream));
        }
        return arr;
    }

    static write(dataStream, value) {
        dataStream.writeInt32(value.length);
        value.forEach((innerValue) => {
            FfiConverterTypeGeoname.write(dataStream, innerValue);
        })
    }

    static computeSize(value) {
        // The size of the length
        let size = 4;
        for (const innerValue of value) {
            size += FfiConverterTypeGeoname.computeSize(innerValue);
        }
        return size;
    }

    static checkType(value) {
        if (!Array.isArray(value)) {
            throw new UniFFITypeError(`${value} is not an array`);
        }
        value.forEach((innerValue, idx) => {
            try {
                FfiConverterTypeGeoname.checkType(innerValue);
            } catch (e) {
                if (e instanceof UniFFITypeError) {
                    e.addItemDescriptionPart(`[${idx}]`);
                }
                throw e;
            }
        })
    }
}

// Export the FFIConverter object to make external types work.
export class FfiConverterSequenceTypeGeonameMatch extends FfiConverterArrayBuffer {
    static read(dataStream) {
        const len = dataStream.readInt32();
        const arr = [];
        for (let i = 0; i < len; i++) {
            arr.push(FfiConverterTypeGeonameMatch.read(dataStream));
        }
        return arr;
    }

    static write(dataStream, value) {
        dataStream.writeInt32(value.length);
        value.forEach((innerValue) => {
            FfiConverterTypeGeonameMatch.write(dataStream, innerValue);
        })
    }

    static computeSize(value) {
        // The size of the length
        let size = 4;
        for (const innerValue of value) {
            size += FfiConverterTypeGeonameMatch.computeSize(innerValue);
        }
        return size;
    }

    static checkType(value) {
        if (!Array.isArray(value)) {
            throw new UniFFITypeError(`${value} is not an array`);
        }
        value.forEach((innerValue, idx) => {
            try {
                FfiConverterTypeGeonameMatch.checkType(innerValue);
            } catch (e) {
                if (e instanceof UniFFITypeError) {
                    e.addItemDescriptionPart(`[${idx}]`);
                }
                throw e;
            }
        })
    }
}

// Export the FFIConverter object to make external types work.
export class FfiConverterSequenceTypeLabeledTimingSample extends FfiConverterArrayBuffer {
    static read(dataStream) {
        const len = dataStream.readInt32();
        const arr = [];
        for (let i = 0; i < len; i++) {
            arr.push(FfiConverterTypeLabeledTimingSample.read(dataStream));
        }
        return arr;
    }

    static write(dataStream, value) {
        dataStream.writeInt32(value.length);
        value.forEach((innerValue) => {
            FfiConverterTypeLabeledTimingSample.write(dataStream, innerValue);
        })
    }

    static computeSize(value) {
        // The size of the length
        let size = 4;
        for (const innerValue of value) {
            size += FfiConverterTypeLabeledTimingSample.computeSize(innerValue);
        }
        return size;
    }

    static checkType(value) {
        if (!Array.isArray(value)) {
            throw new UniFFITypeError(`${value} is not an array`);
        }
        value.forEach((innerValue, idx) => {
            try {
                FfiConverterTypeLabeledTimingSample.checkType(innerValue);
            } catch (e) {
                if (e instanceof UniFFITypeError) {
                    e.addItemDescriptionPart(`[${idx}]`);
                }
                throw e;
            }
        })
    }
}

// Export the FFIConverter object to make external types work.
export class FfiConverterSequenceTypeSuggestion extends FfiConverterArrayBuffer {
    static read(dataStream) {
        const len = dataStream.readInt32();
        const arr = [];
        for (let i = 0; i < len; i++) {
            arr.push(FfiConverterTypeSuggestion.read(dataStream));
        }
        return arr;
    }

    static write(dataStream, value) {
        dataStream.writeInt32(value.length);
        value.forEach((innerValue) => {
            FfiConverterTypeSuggestion.write(dataStream, innerValue);
        })
    }

    static computeSize(value) {
        // The size of the length
        let size = 4;
        for (const innerValue of value) {
            size += FfiConverterTypeSuggestion.computeSize(innerValue);
        }
        return size;
    }

    static checkType(value) {
        if (!Array.isArray(value)) {
            throw new UniFFITypeError(`${value} is not an array`);
        }
        value.forEach((innerValue, idx) => {
            try {
                FfiConverterTypeSuggestion.checkType(innerValue);
            } catch (e) {
                if (e instanceof UniFFITypeError) {
                    e.addItemDescriptionPart(`[${idx}]`);
                }
                throw e;
            }
        })
    }
}

// Export the FFIConverter object to make external types work.
export class FfiConverterSequenceTypeSuggestionProvider extends FfiConverterArrayBuffer {
    static read(dataStream) {
        const len = dataStream.readInt32();
        const arr = [];
        for (let i = 0; i < len; i++) {
            arr.push(FfiConverterTypeSuggestionProvider.read(dataStream));
        }
        return arr;
    }

    static write(dataStream, value) {
        dataStream.writeInt32(value.length);
        value.forEach((innerValue) => {
            FfiConverterTypeSuggestionProvider.write(dataStream, innerValue);
        })
    }

    static computeSize(value) {
        // The size of the length
        let size = 4;
        for (const innerValue of value) {
            size += FfiConverterTypeSuggestionProvider.computeSize(innerValue);
        }
        return size;
    }

    static checkType(value) {
        if (!Array.isArray(value)) {
            throw new UniFFITypeError(`${value} is not an array`);
        }
        value.forEach((innerValue, idx) => {
            try {
                FfiConverterTypeSuggestionProvider.checkType(innerValue);
            } catch (e) {
                if (e instanceof UniFFITypeError) {
                    e.addItemDescriptionPart(`[${idx}]`);
                }
                throw e;
            }
        })
    }
}

import {
  FfiConverterTypeRemoteSettingsConfig,
  RemoteSettingsConfig,
} from "resource://gre/modules/RustRemoteSettings.sys.mjs";

// Export the FFIConverter object to make external types work.
export { FfiConverterTypeRemoteSettingsConfig, RemoteSettingsConfig };

import {
  FfiConverterTypeRemoteSettingsServer,
  RemoteSettingsServer,
} from "resource://gre/modules/RustRemoteSettings.sys.mjs";

// Export the FFIConverter object to make external types work.
export { FfiConverterTypeRemoteSettingsServer, RemoteSettingsServer };





/**
 * Determines whether a "raw" sponsored suggestion URL is equivalent to a
 * "cooked" URL. The two URLs are equivalent if they are identical except for
 * their replaced template parameters, which can be different.
 * @returns {Boolean}
 */
export function rawSuggestionUrlMatches(rawUrl,cookedUrl) {

        const liftResult = (result) => FfiConverterBool.lift(result);
        const liftError = null;
        const functionCall = () => {
            try {
                FfiConverterString.checkType(rawUrl)
            } catch (e) {
                if (e instanceof UniFFITypeError) {
                    e.addItemDescriptionPart("rawUrl");
                }
                throw e;
            }
            try {
                FfiConverterString.checkType(cookedUrl)
            } catch (e) {
                if (e instanceof UniFFITypeError) {
                    e.addItemDescriptionPart("cookedUrl");
                }
                throw e;
            }
            return UniFFIScaffolding.callSync(
                25, // suggest:uniffi_suggest_fn_func_raw_suggestion_url_matches
                FfiConverterString.lower(rawUrl),
                FfiConverterString.lower(cookedUrl),
            )
        }
        return handleRustResult(functionCall(), liftResult, liftError);
}
