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

import {
  ArrayBufferDataStream,
  FfiConverter,
  FfiConverterArrayBuffer,
  FfiConverterInt8,
  FfiConverterUInt8,
  FfiConverterInt16,
  FfiConverterUInt16,
  FfiConverterInt32,
  FfiConverterUInt32,
  FfiConverterInt64,
  FfiConverterUInt64,
  FfiConverterFloat32,
  FfiConverterFloat64,
  FfiConverterBoolean,
  FfiConverterBytes,
  FfiConverterString,
  UniFFICallbackHandler,
  UniFFICallbackMethodHandler,
  UniFFIError,
  UniFFIInternalError,
  UniFFITypeError,
  constructUniffiObject,
  handleRustResult,
  uniffiObjectPtr,
} from "moz-src:///toolkit/components/uniffi-js/js/UniFFI.sys.mjs";

// Objects intended to be used in the unit tests
export var UnitTestObjs = {
    uniffiObjectPtr,
};
/**
 * 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.
 * @param {string} rawUrl
 * @param {string} cookedUrl
 * @returns {boolean}
 */
export function rawSuggestionUrlMatches(
    rawUrl, 
    cookedUrl) {
   
FfiConverterString.checkType(rawUrl);
FfiConverterString.checkType(cookedUrl);
const result = UniFFIScaffolding.callSync(
    172, // uniffi_suggest_fn_func_raw_suggestion_url_matches
    FfiConverterString.lower(rawUrl),
    FfiConverterString.lower(cookedUrl),
)
return handleRustResult(
    result,
    FfiConverterBoolean.lift.bind(FfiConverterBoolean),
    null,
)
}




// 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 new 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)
    }
}
/**
 * A set of names for a single entity.
 */
export class AlternateNames {
    constructor(
        {
            primary, 
            localized, 
            abbreviation
        } = {
            primary: undefined, 
            localized: undefined, 
            abbreviation: undefined
        }
    ) {
        try {
            FfiConverterString.checkType(primary)
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart("primary");
            }
            throw e;
        }
        try {
            FfiConverterOptionalString.checkType(localized)
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart("localized");
            }
            throw e;
        }
        try {
            FfiConverterOptionalString.checkType(abbreviation)
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart("abbreviation");
            }
            throw e;
        }
        /**
         * The entity's primary name. For a `Geoname`, this is `Geoname::name`.
         * @type {string}
         */
        this.primary = primary;
        /**
         * The entity's name in the language that was ingested according to the
         * locale in the remote settings context. If none exists and this
         * `AlternateNames` is for a `Geoname`, then this will be its primary name.
         * @type {?string}
         */
        this.localized = localized;
        /**
         * The entity's abbreviation, if any.
         * @type {?string}
         */
        this.abbreviation = abbreviation;
    }

    equals(other) {
        return (
            this.primary == other.primary
            && this.localized == other.localized
            && this.abbreviation == other.abbreviation
        )
    }
}

// Export the FFIConverter object to make external types work.
export class FfiConverterTypeAlternateNames extends FfiConverterArrayBuffer {
    static read(dataStream) {
        return new AlternateNames({
            primary: FfiConverterString.read(dataStream),
            localized: FfiConverterOptionalString.read(dataStream),
            abbreviation: FfiConverterOptionalString.read(dataStream),
        });
    }
    static write(dataStream, value) {
        FfiConverterString.write(dataStream, value.primary);
        FfiConverterOptionalString.write(dataStream, value.localized);
        FfiConverterOptionalString.write(dataStream, value.abbreviation);
    }

    static computeSize(value) {
        let totalSize = 0;
        totalSize += FfiConverterString.computeSize(value.primary);
        totalSize += FfiConverterOptionalString.computeSize(value.localized);
        totalSize += FfiConverterOptionalString.computeSize(value.abbreviation);
        return totalSize
    }

    static checkType(value) {
        super.checkType(value);
        if (!(value instanceof AlternateNames)) {
            throw new UniFFITypeError(`Expected 'AlternateNames', found '${typeof value}'`);
        }
        try {
            FfiConverterString.checkType(value.primary);
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart(".primary");
            }
            throw e;
        }
        try {
            FfiConverterOptionalString.checkType(value.localized);
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart(".localized");
            }
            throw e;
        }
        try {
            FfiConverterOptionalString.checkType(value.abbreviation);
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart(".abbreviation");
            }
            throw e;
        }
    }
}


/**
 * Additional data about how an FTS match was made
 */
export class FtsMatchInfo {
    constructor(
        {
            prefix, 
            stemming
        } = {
            prefix: undefined, 
            stemming: undefined
        }
    ) {
        try {
            FfiConverterBoolean.checkType(prefix)
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart("prefix");
            }
            throw e;
        }
        try {
            FfiConverterBoolean.checkType(stemming)
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart("stemming");
            }
            throw e;
        }
        /**
         * Was this a prefix match (`water b` matched against `water bottle`)
         * @type {boolean}
         */
        this.prefix = prefix;
        /**
         * Did the match require stemming? (`run shoes` matched against `running shoes`)
         * @type {boolean}
         */
        this.stemming = stemming;
    }

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

// Export the FFIConverter object to make external types work.
export class FfiConverterTypeFtsMatchInfo extends FfiConverterArrayBuffer {
    static read(dataStream) {
        return new FtsMatchInfo({
            prefix: FfiConverterBoolean.read(dataStream),
            stemming: FfiConverterBoolean.read(dataStream),
        });
    }
    static write(dataStream, value) {
        FfiConverterBoolean.write(dataStream, value.prefix);
        FfiConverterBoolean.write(dataStream, value.stemming);
    }

    static computeSize(value) {
        let totalSize = 0;
        totalSize += FfiConverterBoolean.computeSize(value.prefix);
        totalSize += FfiConverterBoolean.computeSize(value.stemming);
        return totalSize
    }

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





/**
 * The type of a geoname.
 */
export class GeonameType {}
/**
 * Country
 */
GeonameType.Country = class extends GeonameType{
   constructor() {
            super();
    }
}
/**
 * A state, province, prefecture, district, borough, etc.
 */
GeonameType.AdminDivision = class extends GeonameType{
   constructor({level = undefined } = {}) {
                super();
            try {
                FfiConverterUInt8.checkType(level);
            } catch (e) {
                if (e instanceof UniFFITypeError) {
                    e.addItemDescriptionPart("level");
                }
                throw e;
            }
            this.level = level;
    }
}
/**
 * AdminDivisionOther
 */
GeonameType.AdminDivisionOther = class extends GeonameType{
   constructor() {
            super();
    }
}
/**
 * A city, town, village, populated place, etc.
 */
GeonameType.City = class extends GeonameType{
   constructor() {
            super();
    }
}
/**
 * Other
 */
GeonameType.Other = class extends GeonameType{
   constructor() {
            super();
    }
}

// Export the FFIConverter object to make external types work.
export class FfiConverterTypeGeonameType extends FfiConverterArrayBuffer {
    static read(dataStream) {
        // Use sequential indices (1-based) for the wire format to match the Rust scaffolding
        switch (dataStream.readInt32()) {
            case 1:
                return new GeonameType.Country();
            case 2:
                return new GeonameType.AdminDivision({
                    level: FfiConverterUInt8.read(dataStream)
                });
            case 3:
                return new GeonameType.AdminDivisionOther();
            case 4:
                return new GeonameType.City();
            case 5:
                return new GeonameType.Other();
            default:
                throw new UniFFITypeError("Unknown GeonameType variant");
        }
    }

    static write(dataStream, value) {
        // Use sequential indices (1-based) for the wire format to match the Rust scaffolding
        if (value instanceof GeonameType.Country) {
            dataStream.writeInt32(1);
            return;
        }
        if (value instanceof GeonameType.AdminDivision) {
            dataStream.writeInt32(2);
            FfiConverterUInt8.write(dataStream, value.level);
            return;
        }
        if (value instanceof GeonameType.AdminDivisionOther) {
            dataStream.writeInt32(3);
            return;
        }
        if (value instanceof GeonameType.City) {
            dataStream.writeInt32(4);
            return;
        }
        if (value instanceof GeonameType.Other) {
            dataStream.writeInt32(5);
            return;
        }
        throw new UniFFITypeError("Unknown GeonameType variant");
    }

    static computeSize(value) {
        // Size of the Int indicating the variant
        let totalSize = 4;
        if (value instanceof GeonameType.Country) {
            return totalSize;
        }
        if (value instanceof GeonameType.AdminDivision) {
            totalSize += FfiConverterUInt8.computeSize(value.level);
            return totalSize;
        }
        if (value instanceof GeonameType.AdminDivisionOther) {
            return totalSize;
        }
        if (value instanceof GeonameType.City) {
            return totalSize;
        }
        if (value instanceof GeonameType.Other) {
            return totalSize;
        }
        throw new UniFFITypeError("Unknown GeonameType variant");
    }

    static checkType(value) {
      if (!(value instanceof GeonameType)) {
        throw new UniFFITypeError(`${value} is not a subclass instance of GeonameType`);
      }
    }
}
// Export the FFIConverter object to make external types work.
export class FfiConverterMapUInt8String extends FfiConverterArrayBuffer {
    static read(dataStream) {
        const len = dataStream.readInt32();
        const map = new Map();
        for (let i = 0; i < len; i++) {
            const key = FfiConverterUInt8.read(dataStream);
            const value = FfiConverterString.read(dataStream);
            map.set(key, value);
        }

        return map;
    }

     static write(dataStream, map) {
        dataStream.writeInt32(map.size);
        for (const [key, value] of map) {
            FfiConverterUInt8.write(dataStream, key);
            FfiConverterString.write(dataStream, value);
        }
    }

    static computeSize(map) {
        // The size of the length
        let size = 4;
        for (const [key, value] of map) {
            size += FfiConverterUInt8.computeSize(key);
            size += FfiConverterString.computeSize(value);
        }
        return size;
    }

    static checkType(map) {
        for (const [key, value] of map) {
            try {
                FfiConverterUInt8.checkType(key);
            } catch (e) {
                if (e instanceof UniFFITypeError) {
                    e.addItemDescriptionPart("(key)");
                }
                throw e;
            }

            try {
                FfiConverterString.checkType(value);
            } catch (e) {
                if (e instanceof UniFFITypeError) {
                    e.addItemDescriptionPart(`[${key}]`);
                }
                throw e;
            }
        }
    }
}


/**
 * 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, 
            geonameType, 
            name, 
            countryCode, 
            featureClass, 
            featureCode, 
            adminDivisionCodes, 
            population, 
            latitude, 
            longitude
        } = {
            geonameId: undefined, 
            geonameType: undefined, 
            name: undefined, 
            countryCode: undefined, 
            featureClass: undefined, 
            featureCode: undefined, 
            adminDivisionCodes: undefined, 
            population: undefined, 
            latitude: undefined, 
            longitude: undefined
        }
    ) {
        try {
            FfiConverterInt64.checkType(geonameId)
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart("geonameId");
            }
            throw e;
        }
        try {
            FfiConverterTypeGeonameType.checkType(geonameType)
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart("geonameType");
            }
            throw e;
        }
        try {
            FfiConverterString.checkType(name)
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart("name");
            }
            throw e;
        }
        try {
            FfiConverterString.checkType(countryCode)
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart("countryCode");
            }
            throw e;
        }
        try {
            FfiConverterString.checkType(featureClass)
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart("featureClass");
            }
            throw e;
        }
        try {
            FfiConverterString.checkType(featureCode)
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart("featureCode");
            }
            throw e;
        }
        try {
            FfiConverterMapUInt8String.checkType(adminDivisionCodes)
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart("adminDivisionCodes");
            }
            throw e;
        }
        try {
            FfiConverterUInt64.checkType(population)
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart("population");
            }
            throw e;
        }
        try {
            FfiConverterString.checkType(latitude)
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart("latitude");
            }
            throw e;
        }
        try {
            FfiConverterString.checkType(longitude)
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart("longitude");
            }
            throw e;
        }
        /**
         * The `geonameid` straight from the geoname table.
         * @type {number}
         */
        this.geonameId = geonameId;
        /**
         * The geoname type. This is derived from `feature_class` and
         * `feature_code` as a more convenient representation of the type.
         * @type {GeonameType[keyof GeonameType]}
         */
        this.geonameType = geonameType;
        /**
         * The place's primary name.
         * @type {string}
         */
        this.name = name;
        /**
         * ISO-3166 two-letter uppercase country code, e.g., "US".
         * @type {string}
         */
        this.countryCode = countryCode;
        /**
         * Primary geoname category. Examples:
         * 
         * "PCLI" - Independent political entity: country
         * "A" - Administrative division: state, province, borough, district, etc.
         * "P" - Populated place: city, village, etc.
         * @type {string}
         */
        this.featureClass = featureClass;
        /**
         * Secondary geoname category, depends on `feature_class`. Examples:
         * 
         * "ADM1" - Administrative division 1
         * "PPL" - Populated place like a city
         * @type {string}
         */
        this.featureCode = featureCode;
        /**
         * Administrative divisions. This maps admin division levels (1-based) to
         * their corresponding codes. For example, Liverpool has two admin
         * divisions: "ENG" at level 1 and "H8" at level 2. They would be
         * represented in this map with entries `(1, "ENG")` and `(2, "H8")`.
         * @type {object}
         */
        this.adminDivisionCodes = adminDivisionCodes;
        /**
         * Population size.
         * @type {number}
         */
        this.population = population;
        /**
         * Latitude in decimal degrees (as a string).
         * @type {string}
         */
        this.latitude = latitude;
        /**
         * Longitude in decimal degrees (as a string).
         * @type {string}
         */
        this.longitude = longitude;
    }

    equals(other) {
        return (
            this.geonameId == other.geonameId
            && this.geonameType == other.geonameType
            && this.name == other.name
            && this.countryCode == other.countryCode
            && this.featureClass == other.featureClass
            && this.featureCode == other.featureCode
            && this.adminDivisionCodes == other.adminDivisionCodes
            && this.population == other.population
            && this.latitude == other.latitude
            && this.longitude == other.longitude
        )
    }
}

// Export the FFIConverter object to make external types work.
export class FfiConverterTypeGeoname extends FfiConverterArrayBuffer {
    static read(dataStream) {
        return new Geoname({
            geonameId: FfiConverterInt64.read(dataStream),
            geonameType: FfiConverterTypeGeonameType.read(dataStream),
            name: FfiConverterString.read(dataStream),
            countryCode: FfiConverterString.read(dataStream),
            featureClass: FfiConverterString.read(dataStream),
            featureCode: FfiConverterString.read(dataStream),
            adminDivisionCodes: FfiConverterMapUInt8String.read(dataStream),
            population: FfiConverterUInt64.read(dataStream),
            latitude: FfiConverterString.read(dataStream),
            longitude: FfiConverterString.read(dataStream),
        });
    }
    static write(dataStream, value) {
        FfiConverterInt64.write(dataStream, value.geonameId);
        FfiConverterTypeGeonameType.write(dataStream, value.geonameType);
        FfiConverterString.write(dataStream, value.name);
        FfiConverterString.write(dataStream, value.countryCode);
        FfiConverterString.write(dataStream, value.featureClass);
        FfiConverterString.write(dataStream, value.featureCode);
        FfiConverterMapUInt8String.write(dataStream, value.adminDivisionCodes);
        FfiConverterUInt64.write(dataStream, value.population);
        FfiConverterString.write(dataStream, value.latitude);
        FfiConverterString.write(dataStream, value.longitude);
    }

    static computeSize(value) {
        let totalSize = 0;
        totalSize += FfiConverterInt64.computeSize(value.geonameId);
        totalSize += FfiConverterTypeGeonameType.computeSize(value.geonameType);
        totalSize += FfiConverterString.computeSize(value.name);
        totalSize += FfiConverterString.computeSize(value.countryCode);
        totalSize += FfiConverterString.computeSize(value.featureClass);
        totalSize += FfiConverterString.computeSize(value.featureCode);
        totalSize += FfiConverterMapUInt8String.computeSize(value.adminDivisionCodes);
        totalSize += FfiConverterUInt64.computeSize(value.population);
        totalSize += FfiConverterString.computeSize(value.latitude);
        totalSize += FfiConverterString.computeSize(value.longitude);
        return totalSize
    }

    static checkType(value) {
        super.checkType(value);
        if (!(value instanceof Geoname)) {
            throw new UniFFITypeError(`Expected 'Geoname', found '${typeof value}'`);
        }
        try {
            FfiConverterInt64.checkType(value.geonameId);
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart(".geonameId");
            }
            throw e;
        }
        try {
            FfiConverterTypeGeonameType.checkType(value.geonameType);
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart(".geonameType");
            }
            throw e;
        }
        try {
            FfiConverterString.checkType(value.name);
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart(".name");
            }
            throw e;
        }
        try {
            FfiConverterString.checkType(value.countryCode);
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart(".countryCode");
            }
            throw e;
        }
        try {
            FfiConverterString.checkType(value.featureClass);
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart(".featureClass");
            }
            throw e;
        }
        try {
            FfiConverterString.checkType(value.featureCode);
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart(".featureCode");
            }
            throw e;
        }
        try {
            FfiConverterMapUInt8String.checkType(value.adminDivisionCodes);
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart(".adminDivisionCodes");
            }
            throw e;
        }
        try {
            FfiConverterUInt64.checkType(value.population);
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart(".population");
            }
            throw e;
        }
        try {
            FfiConverterString.checkType(value.latitude);
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart(".latitude");
            }
            throw e;
        }
        try {
            FfiConverterString.checkType(value.longitude);
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart(".longitude");
            }
            throw e;
        }
    }
}
// Export the FFIConverter object to make external types work.
export class FfiConverterOptionalTypeAlternateNames extends FfiConverterArrayBuffer {
    static checkType(value) {
        if (value !== undefined && value !== null) {
            FfiConverterTypeAlternateNames.checkType(value)
        }
    }

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

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

    static computeSize(value) {
        if (value === null || value === undefined) {
            return 1;
        }
        return 1 + FfiConverterTypeAlternateNames.computeSize(value)
    }
}
// Export the FFIConverter object to make external types work.
export class FfiConverterMapUInt8TypeAlternateNames extends FfiConverterArrayBuffer {
    static read(dataStream) {
        const len = dataStream.readInt32();
        const map = new Map();
        for (let i = 0; i < len; i++) {
            const key = FfiConverterUInt8.read(dataStream);
            const value = FfiConverterTypeAlternateNames.read(dataStream);
            map.set(key, value);
        }

        return map;
    }

     static write(dataStream, map) {
        dataStream.writeInt32(map.size);
        for (const [key, value] of map) {
            FfiConverterUInt8.write(dataStream, key);
            FfiConverterTypeAlternateNames.write(dataStream, value);
        }
    }

    static computeSize(map) {
        // The size of the length
        let size = 4;
        for (const [key, value] of map) {
            size += FfiConverterUInt8.computeSize(key);
            size += FfiConverterTypeAlternateNames.computeSize(value);
        }
        return size;
    }

    static checkType(map) {
        for (const [key, value] of map) {
            try {
                FfiConverterUInt8.checkType(key);
            } catch (e) {
                if (e instanceof UniFFITypeError) {
                    e.addItemDescriptionPart("(key)");
                }
                throw e;
            }

            try {
                FfiConverterTypeAlternateNames.checkType(value);
            } catch (e) {
                if (e instanceof UniFFITypeError) {
                    e.addItemDescriptionPart(`[${key}]`);
                }
                throw e;
            }
        }
    }
}
/**
 * Alternate names for a geoname and its country and admin divisions.
 */
export class GeonameAlternates {
    constructor(
        {
            geoname, 
            country, 
            adminDivisions
        } = {
            geoname: undefined, 
            country: undefined, 
            adminDivisions: undefined
        }
    ) {
        try {
            FfiConverterTypeAlternateNames.checkType(geoname)
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart("geoname");
            }
            throw e;
        }
        try {
            FfiConverterOptionalTypeAlternateNames.checkType(country)
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart("country");
            }
            throw e;
        }
        try {
            FfiConverterMapUInt8TypeAlternateNames.checkType(adminDivisions)
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart("adminDivisions");
            }
            throw e;
        }
        /**
         * Names for the geoname itself.
         * @type {AlternateNames}
         */
        this.geoname = geoname;
        /**
         * Names for the geoname's country. This will be `Some` as long as the
         * country is also in the ingested data, which should typically be true.
         * @type {?AlternateNames}
         */
        this.country = country;
        /**
         * Names for the geoname's admin divisions. This is parallel to
         * `Geoname::admin_division_codes`. If there are no names in the ingested
         * data for an admin division, then it will be absent from this map.
         * @type {object}
         */
        this.adminDivisions = adminDivisions;
    }

    equals(other) {
        return (
            this.geoname.equals(other.geoname)
            && this.country == other.country
            && this.adminDivisions == other.adminDivisions
        )
    }
}

// Export the FFIConverter object to make external types work.
export class FfiConverterTypeGeonameAlternates extends FfiConverterArrayBuffer {
    static read(dataStream) {
        return new GeonameAlternates({
            geoname: FfiConverterTypeAlternateNames.read(dataStream),
            country: FfiConverterOptionalTypeAlternateNames.read(dataStream),
            adminDivisions: FfiConverterMapUInt8TypeAlternateNames.read(dataStream),
        });
    }
    static write(dataStream, value) {
        FfiConverterTypeAlternateNames.write(dataStream, value.geoname);
        FfiConverterOptionalTypeAlternateNames.write(dataStream, value.country);
        FfiConverterMapUInt8TypeAlternateNames.write(dataStream, value.adminDivisions);
    }

    static computeSize(value) {
        let totalSize = 0;
        totalSize += FfiConverterTypeAlternateNames.computeSize(value.geoname);
        totalSize += FfiConverterOptionalTypeAlternateNames.computeSize(value.country);
        totalSize += FfiConverterMapUInt8TypeAlternateNames.computeSize(value.adminDivisions);
        return totalSize
    }

    static checkType(value) {
        super.checkType(value);
        if (!(value instanceof GeonameAlternates)) {
            throw new UniFFITypeError(`Expected 'GeonameAlternates', found '${typeof value}'`);
        }
        try {
            FfiConverterTypeAlternateNames.checkType(value.geoname);
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart(".geoname");
            }
            throw e;
        }
        try {
            FfiConverterOptionalTypeAlternateNames.checkType(value.country);
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart(".country");
            }
            throw e;
        }
        try {
            FfiConverterMapUInt8TypeAlternateNames.checkType(value.adminDivisions);
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart(".adminDivisions");
            }
            throw e;
        }
    }
}

/**
 * GeonameMatchType
 */
export const GeonameMatchType = Object.freeze({
    /**
     * ABBREVIATION
     */
    ABBREVIATION: 0,
    /**
     * AIRPORT_CODE
     */
    AIRPORT_CODE: 1,
    /**
     * This includes any names that aren't abbreviations or airport codes.
     */
    NAME: 2,
});

// Export the FFIConverter object to make external types work.
export class FfiConverterTypeGeonameMatchType extends FfiConverterArrayBuffer {
    static #validValues = Object.values(GeonameMatchType)

    static read(dataStream) {
        // Use sequential indices (1-based) for the wire format to match the Rust scaffolding
        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) {
        // Use sequential indices (1-based) for the wire format to match the Rust scaffolding
        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) {
      // Check that the value is a valid enum variant
      if (!this.#validValues.includes(value)) {
          throw new UniFFITypeError(`${value} is not a valid value for GeonameMatchType`);
      }
    }
}
/**
 * A fetched geoname with info on how it was matched.
 */
export class GeonameMatch {
    constructor(
        {
            geoname, 
            matchType, 
            prefix
        } = {
            geoname: undefined, 
            matchType: undefined, 
            prefix: undefined
        }
    ) {
        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 {
            FfiConverterBoolean.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[keyof 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: FfiConverterBoolean.read(dataStream),
        });
    }
    static write(dataStream, value) {
        FfiConverterTypeGeoname.write(dataStream, value.geoname);
        FfiConverterTypeGeonameMatchType.write(dataStream, value.matchType);
        FfiConverterBoolean.write(dataStream, value.prefix);
    }

    static computeSize(value) {
        let totalSize = 0;
        totalSize += FfiConverterTypeGeoname.computeSize(value.geoname);
        totalSize += FfiConverterTypeGeonameMatchType.computeSize(value.matchType);
        totalSize += FfiConverterBoolean.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 {
            FfiConverterBoolean.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
        } = {
            label: undefined, 
            value: undefined
        }
    ) {
        try {
            FfiConverterString.checkType(label)
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart("label");
            }
            throw e;
        }
        try {
            FfiConverterUInt64.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: FfiConverterUInt64.read(dataStream),
        });
    }
    static write(dataStream, value) {
        FfiConverterString.write(dataStream, value.label);
        FfiConverterUInt64.write(dataStream, value.value);
    }

    static computeSize(value) {
        let totalSize = 0;
        totalSize += FfiConverterString.computeSize(value.label);
        totalSize += FfiConverterUInt64.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 {
            FfiConverterUInt64.checkType(value.value);
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart(".value");
            }
            throw e;
        }
    }
}


// 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 new 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 FfiConverterSequenceInt32 extends FfiConverterArrayBuffer {
    static read(dataStream) {
        const len = dataStream.readInt32();
        const arr = [];
        for (let i = 0; i < len; i++) {
            arr.push(FfiConverterInt32.read(dataStream));
        }
        return arr;
    }

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

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

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


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

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

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

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

/**
 * Subject type for Yelp suggestion.
 */
export const YelpSubjectType = Object.freeze({
    /**
     * SERVICE
     */
    SERVICE: 0,
    /**
     * BUSINESS
     */
    BUSINESS: 1,
});

// Export the FFIConverter object to make external types work.
export class FfiConverterTypeYelpSubjectType extends FfiConverterArrayBuffer {
    static #validValues = Object.values(YelpSubjectType)

    static read(dataStream) {
        // Use sequential indices (1-based) for the wire format to match the Rust scaffolding
        switch (dataStream.readInt32()) {
            case 1:
                return YelpSubjectType.SERVICE
            case 2:
                return YelpSubjectType.BUSINESS
            default:
                throw new UniFFITypeError("Unknown YelpSubjectType variant");
        }
    }

    static write(dataStream, value) {
        // Use sequential indices (1-based) for the wire format to match the Rust scaffolding
        if (value === YelpSubjectType.SERVICE) {
            dataStream.writeInt32(1);
            return;
        }
        if (value === YelpSubjectType.BUSINESS) {
            dataStream.writeInt32(2);
            return;
        }
        throw new UniFFITypeError("Unknown YelpSubjectType variant");
    }

    static computeSize(value) {
        return 4;
    }

    static checkType(value) {
      // Check that the value is a valid enum variant
      if (!this.#validValues.includes(value)) {
          throw new UniFFITypeError(`${value} is not a valid value for YelpSubjectType`);
      }
    }
}
// Export the FFIConverter object to make external types work.
export class FfiConverterOptionalTypeGeoname extends FfiConverterArrayBuffer {
    static checkType(value) {
        if (value !== undefined && value !== null) {
            FfiConverterTypeGeoname.checkType(value)
        }
    }

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

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

    static computeSize(value) {
        if (value === null || value === undefined) {
            return 1;
        }
        return 1 + FfiConverterTypeGeoname.computeSize(value)
    }
}
export class FfiConverterTypeJsonValue extends FfiConverter {
    static lift(value) {
        return FfiConverterString.lift(value);
    }

    static lower(value) {
        return FfiConverterString.lower(value);
    }

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

    static read(dataStream) {
        const builtinVal = FfiConverterString.read(dataStream);
        return builtinVal;
    }

    static computeSize(value) {
        return FfiConverterString.computeSize(value);
    }

    static checkType(value) {
        if (value === null || value === undefined) {
            throw new TypeError("value is null or undefined");
        }
    }
}
// Export the FFIConverter object to make external types work.
export class FfiConverterOptionalTypeJsonValue extends FfiConverterArrayBuffer {
    static checkType(value) {
        if (value !== undefined && value !== null) {
            FfiConverterTypeJsonValue.checkType(value)
        }
    }

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

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

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

/**
 * A suggestion from the database to show in the address bar.
 */
export class Suggestion {}
/**
 * Amp
 */
Suggestion.Amp = class extends Suggestion{
   constructor({title = undefined, url = undefined, rawUrl = undefined, icon = undefined, iconMimetype = undefined, fullKeyword = undefined, blockId = undefined, advertiser = undefined, iabCategory = undefined, categories = undefined, impressionUrl = undefined, clickUrl = undefined, rawClickUrl = undefined, score = undefined, ftsMatchInfo = undefined } = {}) {
                super();
            try {
                FfiConverterString.checkType(title);
            } catch (e) {
                if (e instanceof UniFFITypeError) {
                    e.addItemDescriptionPart("title");
                }
                throw e;
            }
            this.title = title;try {
                FfiConverterString.checkType(url);
            } catch (e) {
                if (e instanceof UniFFITypeError) {
                    e.addItemDescriptionPart("url");
                }
                throw e;
            }
            this.url = url;try {
                FfiConverterString.checkType(rawUrl);
            } catch (e) {
                if (e instanceof UniFFITypeError) {
                    e.addItemDescriptionPart("rawUrl");
                }
                throw e;
            }
            this.rawUrl = rawUrl;try {
                FfiConverterOptionalBytes.checkType(icon);
            } catch (e) {
                if (e instanceof UniFFITypeError) {
                    e.addItemDescriptionPart("icon");
                }
                throw e;
            }
            this.icon = icon;try {
                FfiConverterOptionalString.checkType(iconMimetype);
            } catch (e) {
                if (e instanceof UniFFITypeError) {
                    e.addItemDescriptionPart("iconMimetype");
                }
                throw e;
            }
            this.iconMimetype = iconMimetype;try {
                FfiConverterString.checkType(fullKeyword);
            } catch (e) {
                if (e instanceof UniFFITypeError) {
                    e.addItemDescriptionPart("fullKeyword");
                }
                throw e;
            }
            this.fullKeyword = fullKeyword;try {
                FfiConverterInt64.checkType(blockId);
            } catch (e) {
                if (e instanceof UniFFITypeError) {
                    e.addItemDescriptionPart("blockId");
                }
                throw e;
            }
            this.blockId = blockId;try {
                FfiConverterString.checkType(advertiser);
            } catch (e) {
                if (e instanceof UniFFITypeError) {
                    e.addItemDescriptionPart("advertiser");
                }
                throw e;
            }
            this.advertiser = advertiser;try {
                FfiConverterString.checkType(iabCategory);
            } catch (e) {
                if (e instanceof UniFFITypeError) {
                    e.addItemDescriptionPart("iabCategory");
                }
                throw e;
            }
            this.iabCategory = iabCategory;try {
                FfiConverterSequenceInt32.checkType(categories);
            } catch (e) {
                if (e instanceof UniFFITypeError) {
                    e.addItemDescriptionPart("categories");
                }
                throw e;
            }
            this.categories = categories;try {
                FfiConverterString.checkType(impressionUrl);
            } catch (e) {
                if (e instanceof UniFFITypeError) {
                    e.addItemDescriptionPart("impressionUrl");
                }
                throw e;
            }
            this.impressionUrl = impressionUrl;try {
                FfiConverterString.checkType(clickUrl);
            } catch (e) {
                if (e instanceof UniFFITypeError) {
                    e.addItemDescriptionPart("clickUrl");
                }
                throw e;
            }
            this.clickUrl = clickUrl;try {
                FfiConverterString.checkType(rawClickUrl);
            } catch (e) {
                if (e instanceof UniFFITypeError) {
                    e.addItemDescriptionPart("rawClickUrl");
                }
                throw e;
            }
            this.rawClickUrl = rawClickUrl;try {
                FfiConverterFloat64.checkType(score);
            } catch (e) {
                if (e instanceof UniFFITypeError) {
                    e.addItemDescriptionPart("score");
                }
                throw e;
            }
            this.score = score;try {
                FfiConverterOptionalTypeFtsMatchInfo.checkType(ftsMatchInfo);
            } catch (e) {
                if (e instanceof UniFFITypeError) {
                    e.addItemDescriptionPart("ftsMatchInfo");
                }
                throw e;
            }
            this.ftsMatchInfo = ftsMatchInfo;
    }
}
/**
 * Wikipedia
 */
Suggestion.Wikipedia = class extends Suggestion{
   constructor({title = undefined, url = undefined, icon = undefined, iconMimetype = undefined, fullKeyword = undefined } = {}) {
                super();
            try {
                FfiConverterString.checkType(title);
            } catch (e) {
                if (e instanceof UniFFITypeError) {
                    e.addItemDescriptionPart("title");
                }
                throw e;
            }
            this.title = title;try {
                FfiConverterString.checkType(url);
            } catch (e) {
                if (e instanceof UniFFITypeError) {
                    e.addItemDescriptionPart("url");
                }
                throw e;
            }
            this.url = url;try {
                FfiConverterOptionalBytes.checkType(icon);
            } catch (e) {
                if (e instanceof UniFFITypeError) {
                    e.addItemDescriptionPart("icon");
                }
                throw e;
            }
            this.icon = icon;try {
                FfiConverterOptionalString.checkType(iconMimetype);
            } catch (e) {
                if (e instanceof UniFFITypeError) {
                    e.addItemDescriptionPart("iconMimetype");
                }
                throw e;
            }
            this.iconMimetype = iconMimetype;try {
                FfiConverterString.checkType(fullKeyword);
            } catch (e) {
                if (e instanceof UniFFITypeError) {
                    e.addItemDescriptionPart("fullKeyword");
                }
                throw e;
            }
            this.fullKeyword = fullKeyword;
    }
}
/**
 * Amo
 */
Suggestion.Amo = class extends Suggestion{
   constructor({title = undefined, url = undefined, iconUrl = undefined, description = undefined, rating = undefined, numberOfRatings = undefined, guid = undefined, score = undefined } = {}) {
                super();
            try {
                FfiConverterString.checkType(title);
            } catch (e) {
                if (e instanceof UniFFITypeError) {
                    e.addItemDescriptionPart("title");
                }
                throw e;
            }
            this.title = title;try {
                FfiConverterString.checkType(url);
            } catch (e) {
                if (e instanceof UniFFITypeError) {
                    e.addItemDescriptionPart("url");
                }
                throw e;
            }
            this.url = url;try {
                FfiConverterString.checkType(iconUrl);
            } catch (e) {
                if (e instanceof UniFFITypeError) {
                    e.addItemDescriptionPart("iconUrl");
                }
                throw e;
            }
            this.iconUrl = iconUrl;try {
                FfiConverterString.checkType(description);
            } catch (e) {
                if (e instanceof UniFFITypeError) {
                    e.addItemDescriptionPart("description");
                }
                throw e;
            }
            this.description = description;try {
                FfiConverterOptionalString.checkType(rating);
            } catch (e) {
                if (e instanceof UniFFITypeError) {
                    e.addItemDescriptionPart("rating");
                }
                throw e;
            }
            this.rating = rating;try {
                FfiConverterInt64.checkType(numberOfRatings);
            } catch (e) {
                if (e instanceof UniFFITypeError) {
                    e.addItemDescriptionPart("numberOfRatings");
                }
                throw e;
            }
            this.numberOfRatings = numberOfRatings;try {
                FfiConverterString.checkType(guid);
            } catch (e) {
                if (e instanceof UniFFITypeError) {
                    e.addItemDescriptionPart("guid");
                }
                throw e;
            }
            this.guid = guid;try {
                FfiConverterFloat64.checkType(score);
            } catch (e) {
                if (e instanceof UniFFITypeError) {
                    e.addItemDescriptionPart("score");
                }
                throw e;
            }
            this.score = score;
    }
}
/**
 * Yelp
 */
Suggestion.Yelp = class extends Suggestion{
   constructor({url = undefined, title = undefined, icon = undefined, iconMimetype = undefined, score = undefined, hasLocationSign = undefined, subjectExactMatch = undefined, subjectType = undefined, locationParam = undefined } = {}) {
                super();
            try {
                FfiConverterString.checkType(url);
            } catch (e) {
                if (e instanceof UniFFITypeError) {
                    e.addItemDescriptionPart("url");
                }
                throw e;
            }
            this.url = url;try {
                FfiConverterString.checkType(title);
            } catch (e) {
                if (e instanceof UniFFITypeError) {
                    e.addItemDescriptionPart("title");
                }
                throw e;
            }
            this.title = title;try {
                FfiConverterOptionalBytes.checkType(icon);
            } catch (e) {
                if (e instanceof UniFFITypeError) {
                    e.addItemDescriptionPart("icon");
                }
                throw e;
            }
            this.icon = icon;try {
                FfiConverterOptionalString.checkType(iconMimetype);
            } catch (e) {
                if (e instanceof UniFFITypeError) {
                    e.addItemDescriptionPart("iconMimetype");
                }
                throw e;
            }
            this.iconMimetype = iconMimetype;try {
                FfiConverterFloat64.checkType(score);
            } catch (e) {
                if (e instanceof UniFFITypeError) {
                    e.addItemDescriptionPart("score");
                }
                throw e;
            }
            this.score = score;try {
                FfiConverterBoolean.checkType(hasLocationSign);
            } catch (e) {
                if (e instanceof UniFFITypeError) {
                    e.addItemDescriptionPart("hasLocationSign");
                }
                throw e;
            }
            this.hasLocationSign = hasLocationSign;try {
                FfiConverterBoolean.checkType(subjectExactMatch);
            } catch (e) {
                if (e instanceof UniFFITypeError) {
                    e.addItemDescriptionPart("subjectExactMatch");
                }
                throw e;
            }
            this.subjectExactMatch = subjectExactMatch;try {
                FfiConverterTypeYelpSubjectType.checkType(subjectType);
            } catch (e) {
                if (e instanceof UniFFITypeError) {
                    e.addItemDescriptionPart("subjectType");
                }
                throw e;
            }
            this.subjectType = subjectType;try {
                FfiConverterString.checkType(locationParam);
            } catch (e) {
                if (e instanceof UniFFITypeError) {
                    e.addItemDescriptionPart("locationParam");
                }
                throw e;
            }
            this.locationParam = locationParam;
    }
}
/**
 * Mdn
 */
Suggestion.Mdn = class extends Suggestion{
   constructor({title = undefined, url = undefined, description = undefined, score = undefined } = {}) {
                super();
            try {
                FfiConverterString.checkType(title);
            } catch (e) {
                if (e instanceof UniFFITypeError) {
                    e.addItemDescriptionPart("title");
                }
                throw e;
            }
            this.title = title;try {
                FfiConverterString.checkType(url);
            } catch (e) {
                if (e instanceof UniFFITypeError) {
                    e.addItemDescriptionPart("url");
                }
                throw e;
            }
            this.url = url;try {
                FfiConverterString.checkType(description);
            } catch (e) {
                if (e instanceof UniFFITypeError) {
                    e.addItemDescriptionPart("description");
                }
                throw e;
            }
            this.description = description;try {
                FfiConverterFloat64.checkType(score);
            } catch (e) {
                if (e instanceof UniFFITypeError) {
                    e.addItemDescriptionPart("score");
                }
                throw e;
            }
            this.score = score;
    }
}
/**
 * Weather
 */
Suggestion.Weather = class extends Suggestion{
   constructor({city = undefined, score = undefined } = {}) {
                super();
            try {
                FfiConverterOptionalTypeGeoname.checkType(city);
            } catch (e) {
                if (e instanceof UniFFITypeError) {
                    e.addItemDescriptionPart("city");
                }
                throw e;
            }
            this.city = city;try {
                FfiConverterFloat64.checkType(score);
            } catch (e) {
                if (e instanceof UniFFITypeError) {
                    e.addItemDescriptionPart("score");
                }
                throw e;
            }
            this.score = score;
    }
}
/**
 * Dynamic
 */
Suggestion.Dynamic = class extends Suggestion{
   constructor({suggestionType = undefined, data = undefined, dismissalKey = undefined, score = undefined } = {}) {
                super();
            try {
                FfiConverterString.checkType(suggestionType);
            } catch (e) {
                if (e instanceof UniFFITypeError) {
                    e.addItemDescriptionPart("suggestionType");
                }
                throw e;
            }
            this.suggestionType = suggestionType;try {
                FfiConverterOptionalTypeJsonValue.checkType(data);
            } catch (e) {
                if (e instanceof UniFFITypeError) {
                    e.addItemDescriptionPart("data");
                }
                throw e;
            }
            this.data = data;try {
                FfiConverterOptionalString.checkType(dismissalKey);
            } catch (e) {
                if (e instanceof UniFFITypeError) {
                    e.addItemDescriptionPart("dismissalKey");
                }
                throw e;
            }
            this.dismissalKey = dismissalKey;try {
                FfiConverterFloat64.checkType(score);
            } catch (e) {
                if (e instanceof UniFFITypeError) {
                    e.addItemDescriptionPart("score");
                }
                throw e;
            }
            this.score = score;
    }
}

// Export the FFIConverter object to make external types work.
export class FfiConverterTypeSuggestion extends FfiConverterArrayBuffer {
    static read(dataStream) {
        // Use sequential indices (1-based) for the wire format to match the Rust scaffolding
        switch (dataStream.readInt32()) {
            case 1:
                return new Suggestion.Amp({
                    title: FfiConverterString.read(dataStream),
                    url: FfiConverterString.read(dataStream),
                    rawUrl: FfiConverterString.read(dataStream),
                    icon: FfiConverterOptionalBytes.read(dataStream),
                    iconMimetype: FfiConverterOptionalString.read(dataStream),
                    fullKeyword: FfiConverterString.read(dataStream),
                    blockId: FfiConverterInt64.read(dataStream),
                    advertiser: FfiConverterString.read(dataStream),
                    iabCategory: FfiConverterString.read(dataStream),
                    categories: FfiConverterSequenceInt32.read(dataStream),
                    impressionUrl: FfiConverterString.read(dataStream),
                    clickUrl: FfiConverterString.read(dataStream),
                    rawClickUrl: FfiConverterString.read(dataStream),
                    score: FfiConverterFloat64.read(dataStream),
                    ftsMatchInfo: FfiConverterOptionalTypeFtsMatchInfo.read(dataStream)
                });
            case 2:
                return new Suggestion.Wikipedia({
                    title: FfiConverterString.read(dataStream),
                    url: FfiConverterString.read(dataStream),
                    icon: FfiConverterOptionalBytes.read(dataStream),
                    iconMimetype: FfiConverterOptionalString.read(dataStream),
                    fullKeyword: FfiConverterString.read(dataStream)
                });
            case 3:
                return new Suggestion.Amo({
                    title: FfiConverterString.read(dataStream),
                    url: FfiConverterString.read(dataStream),
                    iconUrl: FfiConverterString.read(dataStream),
                    description: FfiConverterString.read(dataStream),
                    rating: FfiConverterOptionalString.read(dataStream),
                    numberOfRatings: FfiConverterInt64.read(dataStream),
                    guid: FfiConverterString.read(dataStream),
                    score: FfiConverterFloat64.read(dataStream)
                });
            case 4:
                return new Suggestion.Yelp({
                    url: FfiConverterString.read(dataStream),
                    title: FfiConverterString.read(dataStream),
                    icon: FfiConverterOptionalBytes.read(dataStream),
                    iconMimetype: FfiConverterOptionalString.read(dataStream),
                    score: FfiConverterFloat64.read(dataStream),
                    hasLocationSign: FfiConverterBoolean.read(dataStream),
                    subjectExactMatch: FfiConverterBoolean.read(dataStream),
                    subjectType: FfiConverterTypeYelpSubjectType.read(dataStream),
                    locationParam: FfiConverterString.read(dataStream)
                });
            case 5:
                return new Suggestion.Mdn({
                    title: FfiConverterString.read(dataStream),
                    url: FfiConverterString.read(dataStream),
                    description: FfiConverterString.read(dataStream),
                    score: FfiConverterFloat64.read(dataStream)
                });
            case 6:
                return new Suggestion.Weather({
                    city: FfiConverterOptionalTypeGeoname.read(dataStream),
                    score: FfiConverterFloat64.read(dataStream)
                });
            case 7:
                return new Suggestion.Dynamic({
                    suggestionType: FfiConverterString.read(dataStream),
                    data: FfiConverterOptionalTypeJsonValue.read(dataStream),
                    dismissalKey: FfiConverterOptionalString.read(dataStream),
                    score: FfiConverterFloat64.read(dataStream)
                });
            default:
                throw new UniFFITypeError("Unknown Suggestion variant");
        }
    }

    static write(dataStream, value) {
        // Use sequential indices (1-based) for the wire format to match the Rust scaffolding
        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);
            FfiConverterInt64.write(dataStream, value.blockId);
            FfiConverterString.write(dataStream, value.advertiser);
            FfiConverterString.write(dataStream, value.iabCategory);
            FfiConverterSequenceInt32.write(dataStream, value.categories);
            FfiConverterString.write(dataStream, value.impressionUrl);
            FfiConverterString.write(dataStream, value.clickUrl);
            FfiConverterString.write(dataStream, value.rawClickUrl);
            FfiConverterFloat64.write(dataStream, value.score);
            FfiConverterOptionalTypeFtsMatchInfo.write(dataStream, value.ftsMatchInfo);
            return;
        }
        if (value instanceof Suggestion.Wikipedia) {
            dataStream.writeInt32(2);
            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(3);
            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);
            FfiConverterInt64.write(dataStream, value.numberOfRatings);
            FfiConverterString.write(dataStream, value.guid);
            FfiConverterFloat64.write(dataStream, value.score);
            return;
        }
        if (value instanceof Suggestion.Yelp) {
            dataStream.writeInt32(4);
            FfiConverterString.write(dataStream, value.url);
            FfiConverterString.write(dataStream, value.title);
            FfiConverterOptionalBytes.write(dataStream, value.icon);
            FfiConverterOptionalString.write(dataStream, value.iconMimetype);
            FfiConverterFloat64.write(dataStream, value.score);
            FfiConverterBoolean.write(dataStream, value.hasLocationSign);
            FfiConverterBoolean.write(dataStream, value.subjectExactMatch);
            FfiConverterTypeYelpSubjectType.write(dataStream, value.subjectType);
            FfiConverterString.write(dataStream, value.locationParam);
            return;
        }
        if (value instanceof Suggestion.Mdn) {
            dataStream.writeInt32(5);
            FfiConverterString.write(dataStream, value.title);
            FfiConverterString.write(dataStream, value.url);
            FfiConverterString.write(dataStream, value.description);
            FfiConverterFloat64.write(dataStream, value.score);
            return;
        }
        if (value instanceof Suggestion.Weather) {
            dataStream.writeInt32(6);
            FfiConverterOptionalTypeGeoname.write(dataStream, value.city);
            FfiConverterFloat64.write(dataStream, value.score);
            return;
        }
        if (value instanceof Suggestion.Dynamic) {
            dataStream.writeInt32(7);
            FfiConverterString.write(dataStream, value.suggestionType);
            FfiConverterOptionalTypeJsonValue.write(dataStream, value.data);
            FfiConverterOptionalString.write(dataStream, value.dismissalKey);
            FfiConverterFloat64.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 += FfiConverterInt64.computeSize(value.blockId);
            totalSize += FfiConverterString.computeSize(value.advertiser);
            totalSize += FfiConverterString.computeSize(value.iabCategory);
            totalSize += FfiConverterSequenceInt32.computeSize(value.categories);
            totalSize += FfiConverterString.computeSize(value.impressionUrl);
            totalSize += FfiConverterString.computeSize(value.clickUrl);
            totalSize += FfiConverterString.computeSize(value.rawClickUrl);
            totalSize += FfiConverterFloat64.computeSize(value.score);
            totalSize += FfiConverterOptionalTypeFtsMatchInfo.computeSize(value.ftsMatchInfo);
            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 += FfiConverterInt64.computeSize(value.numberOfRatings);
            totalSize += FfiConverterString.computeSize(value.guid);
            totalSize += FfiConverterFloat64.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 += FfiConverterFloat64.computeSize(value.score);
            totalSize += FfiConverterBoolean.computeSize(value.hasLocationSign);
            totalSize += FfiConverterBoolean.computeSize(value.subjectExactMatch);
            totalSize += FfiConverterTypeYelpSubjectType.computeSize(value.subjectType);
            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 += FfiConverterFloat64.computeSize(value.score);
            return totalSize;
        }
        if (value instanceof Suggestion.Weather) {
            totalSize += FfiConverterOptionalTypeGeoname.computeSize(value.city);
            totalSize += FfiConverterFloat64.computeSize(value.score);
            return totalSize;
        }
        if (value instanceof Suggestion.Dynamic) {
            totalSize += FfiConverterString.computeSize(value.suggestionType);
            totalSize += FfiConverterOptionalTypeJsonValue.computeSize(value.data);
            totalSize += FfiConverterOptionalString.computeSize(value.dismissalKey);
            totalSize += FfiConverterFloat64.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`);
      }
    }
}
// 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 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;
            }
        })
    }
}
/**
 * QueryWithMetricsResult
 */
export class QueryWithMetricsResult {
    constructor(
        {
            suggestions, 
            queryTimes
        } = {
            suggestions: undefined, 
            queryTimes: undefined
        }
    ) {
        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[keyof 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
        } = {
            showLessFrequentlyCap: undefined
        }
    ) {
        try {
            FfiConverterInt32.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: FfiConverterInt32.read(dataStream),
        });
    }
    static write(dataStream, value) {
        FfiConverterInt32.write(dataStream, value.showLessFrequentlyCap);
    }

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

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

/**
 * A provider is a source of search suggestions.
 * Please preserve the integer values after removing or adding providers.
 * Provider configs are associated with integer keys stored in the database.
 */
export const SuggestionProvider = Object.freeze({
    /**
     * AMP
     */
    AMP: 1,
    /**
     * WIKIPEDIA
     */
    WIKIPEDIA: 2,
    /**
     * AMO
     */
    AMO: 3,
    /**
     * YELP
     */
    YELP: 5,
    /**
     * MDN
     */
    MDN: 6,
    /**
     * WEATHER
     */
    WEATHER: 7,
    /**
     * DYNAMIC
     */
    DYNAMIC: 9,
});

// Export the FFIConverter object to make external types work.
export class FfiConverterTypeSuggestionProvider extends FfiConverterArrayBuffer {
    static #validValues = Object.values(SuggestionProvider)

    static read(dataStream) {
        // Use sequential indices (1-based) for the wire format to match the Rust scaffolding
        switch (dataStream.readInt32()) {
            case 1:
                return SuggestionProvider.AMP
            case 2:
                return SuggestionProvider.WIKIPEDIA
            case 3:
                return SuggestionProvider.AMO
            case 4:
                return SuggestionProvider.YELP
            case 5:
                return SuggestionProvider.MDN
            case 6:
                return SuggestionProvider.WEATHER
            case 7:
                return SuggestionProvider.DYNAMIC
            default:
                throw new UniFFITypeError("Unknown SuggestionProvider variant");
        }
    }

    static write(dataStream, value) {
        // Use sequential indices (1-based) for the wire format to match the Rust scaffolding
        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.YELP) {
            dataStream.writeInt32(4);
            return;
        }
        if (value === SuggestionProvider.MDN) {
            dataStream.writeInt32(5);
            return;
        }
        if (value === SuggestionProvider.WEATHER) {
            dataStream.writeInt32(6);
            return;
        }
        if (value === SuggestionProvider.DYNAMIC) {
            dataStream.writeInt32(7);
            return;
        }
        throw new UniFFITypeError("Unknown SuggestionProvider variant");
    }

    static computeSize(value) {
        return 4;
    }

    static checkType(value) {
      // Check that the value is a valid enum variant
      if (!this.#validValues.includes(value)) {
          throw new UniFFITypeError(`${value} is not a valid value for SuggestionProvider`);
      }
    }
}
// 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;
            }
        })
    }
}
// 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 new 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 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 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 new 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)
    }
}

/**
 * AmpMatchingStrategy
 */
export const AmpMatchingStrategy = Object.freeze({
    /**
     * Disable keywords added via keyword expansion.
     * This eliminates keywords that for terms related to the "real" keywords, for example
     * misspellings like "underarmor" instead of "under armor"'.
     */
    NO_KEYWORD_EXPANSION: 1,
    /**
     * Use FTS matching against the full keywords, joined together.
     */
    FTS_AGAINST_FULL_KEYWORDS: 2,
    /**
     * Use FTS matching against the title field
     */
    FTS_AGAINST_TITLE: 3,
});

// Export the FFIConverter object to make external types work.
export class FfiConverterTypeAmpMatchingStrategy extends FfiConverterArrayBuffer {
    static #validValues = Object.values(AmpMatchingStrategy)

    static read(dataStream) {
        // Use sequential indices (1-based) for the wire format to match the Rust scaffolding
        switch (dataStream.readInt32()) {
            case 1:
                return AmpMatchingStrategy.NO_KEYWORD_EXPANSION
            case 2:
                return AmpMatchingStrategy.FTS_AGAINST_FULL_KEYWORDS
            case 3:
                return AmpMatchingStrategy.FTS_AGAINST_TITLE
            default:
                throw new UniFFITypeError("Unknown AmpMatchingStrategy variant");
        }
    }

    static write(dataStream, value) {
        // Use sequential indices (1-based) for the wire format to match the Rust scaffolding
        if (value === AmpMatchingStrategy.NO_KEYWORD_EXPANSION) {
            dataStream.writeInt32(1);
            return;
        }
        if (value === AmpMatchingStrategy.FTS_AGAINST_FULL_KEYWORDS) {
            dataStream.writeInt32(2);
            return;
        }
        if (value === AmpMatchingStrategy.FTS_AGAINST_TITLE) {
            dataStream.writeInt32(3);
            return;
        }
        throw new UniFFITypeError("Unknown AmpMatchingStrategy variant");
    }

    static computeSize(value) {
        return 4;
    }

    static checkType(value) {
      // Check that the value is a valid enum variant
      if (!this.#validValues.includes(value)) {
          throw new UniFFITypeError(`${value} is not a valid value for AmpMatchingStrategy`);
      }
    }
}
// Export the FFIConverter object to make external types work.
export class FfiConverterOptionalTypeAmpMatchingStrategy extends FfiConverterArrayBuffer {
    static checkType(value) {
        if (value !== undefined && value !== null) {
            FfiConverterTypeAmpMatchingStrategy.checkType(value)
        }
    }

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

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

    static computeSize(value) {
        if (value === null || value === undefined) {
            return 1;
        }
        return 1 + FfiConverterTypeAmpMatchingStrategy.computeSize(value)
    }
}
/**
 * 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(
        {
            dynamicSuggestionTypes= null, 
            ampAlternativeMatching= null
        } = {
            dynamicSuggestionTypes: undefined, 
            ampAlternativeMatching: undefined
        }
    ) {
        try {
            FfiConverterOptionalSequenceString.checkType(dynamicSuggestionTypes)
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart("dynamicSuggestionTypes");
            }
            throw e;
        }
        try {
            FfiConverterOptionalTypeAmpMatchingStrategy.checkType(ampAlternativeMatching)
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart("ampAlternativeMatching");
            }
            throw e;
        }
        /**
         * Which dynamic suggestions should we fetch or ingest? Corresponds to the
         * `suggestion_type` value in dynamic suggestions remote settings records.
         * @type {?Array.<string>}
         */
        this.dynamicSuggestionTypes = dynamicSuggestionTypes;
        /**
         * Which strategy should we use for the AMP queries?
         * Use None for the default strategy.
         * @type {?AmpMatchingStrategy[keyof AmpMatchingStrategy]}
         */
        this.ampAlternativeMatching = ampAlternativeMatching;
    }

    equals(other) {
        return (
            this.dynamicSuggestionTypes == other.dynamicSuggestionTypes
            && this.ampAlternativeMatching == other.ampAlternativeMatching
        )
    }
}

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

    static computeSize(value) {
        let totalSize = 0;
        totalSize += FfiConverterOptionalSequenceString.computeSize(value.dynamicSuggestionTypes);
        totalSize += FfiConverterOptionalTypeAmpMatchingStrategy.computeSize(value.ampAlternativeMatching);
        return totalSize
    }

    static checkType(value) {
        super.checkType(value);
        if (!(value instanceof SuggestionProviderConstraints)) {
            throw new UniFFITypeError(`Expected 'SuggestionProviderConstraints', found '${typeof value}'`);
        }
        try {
            FfiConverterOptionalSequenceString.checkType(value.dynamicSuggestionTypes);
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart(".dynamicSuggestionTypes");
            }
            throw e;
        }
        try {
            FfiConverterOptionalTypeAmpMatchingStrategy.checkType(value.ampAlternativeMatching);
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart(".ampAlternativeMatching");
            }
            throw e;
        }
    }
}
// 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 new 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)
    }
}
/**
 * Constraints limit which suggestions to ingest from Remote Settings.
 */
export class SuggestIngestionConstraints {
    constructor(
        {
            providers= null, 
            providerConstraints= null, 
            emptyOnly= false
        } = {
            providers: undefined, 
            providerConstraints: undefined, 
            emptyOnly: undefined
        }
    ) {
        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 {
            FfiConverterBoolean.checkType(emptyOnly)
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart("emptyOnly");
            }
            throw e;
        }
        /**
         * @type {?Array.<SuggestionProvider[keyof 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: FfiConverterBoolean.read(dataStream),
        });
    }
    static write(dataStream, value) {
        FfiConverterOptionalSequenceTypeSuggestionProvider.write(dataStream, value.providers);
        FfiConverterOptionalTypeSuggestionProviderConstraints.write(dataStream, value.providerConstraints);
        FfiConverterBoolean.write(dataStream, value.emptyOnly);
    }

    static computeSize(value) {
        let totalSize = 0;
        totalSize += FfiConverterOptionalSequenceTypeSuggestionProvider.computeSize(value.providers);
        totalSize += FfiConverterOptionalTypeSuggestionProviderConstraints.computeSize(value.providerConstraints);
        totalSize += FfiConverterBoolean.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 {
            FfiConverterBoolean.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
        } = {
            ingestionTimes: undefined, 
            downloadTimes: undefined
        }
    ) {
        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;
        }
    }
}
// Export the FFIConverter object to make external types work.
export class FfiConverterOptionalInt32 extends FfiConverterArrayBuffer {
    static checkType(value) {
        if (value !== undefined && value !== null) {
            FfiConverterInt32.checkType(value)
        }
    }

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

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

    static computeSize(value) {
        if (value === null || value === undefined) {
            return 1;
        }
        return 1 + FfiConverterInt32.computeSize(value)
    }
}
/**
 * A query for suggestions to show in the address bar.
 */
export class SuggestionQuery {
    constructor(
        {
            keyword, 
            providers, 
            providerConstraints= null, 
            limit= null
        } = {
            keyword: undefined, 
            providers: undefined, 
            providerConstraints: undefined, 
            limit: undefined
        }
    ) {
        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 {
            FfiConverterOptionalInt32.checkType(limit)
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart("limit");
            }
            throw e;
        }
        /**
         * @type {string}
         */
        this.keyword = keyword;
        /**
         * @type {Array.<SuggestionProvider[keyof 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: FfiConverterOptionalInt32.read(dataStream),
        });
    }
    static write(dataStream, value) {
        FfiConverterString.write(dataStream, value.keyword);
        FfiConverterSequenceTypeSuggestionProvider.write(dataStream, value.providers);
        FfiConverterOptionalTypeSuggestionProviderConstraints.write(dataStream, value.providerConstraints);
        FfiConverterOptionalInt32.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 += FfiConverterOptionalInt32.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 {
            FfiConverterOptionalInt32.checkType(value.limit);
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart(".limit");
            }
            throw e;
        }
    }
}

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

// Export the FFIConverter object to make external types work.
export class FfiConverterTypeInterruptKind extends FfiConverterArrayBuffer {
    static #validValues = Object.values(InterruptKind)

    static read(dataStream) {
        // Use sequential indices (1-based) for the wire format to match the Rust scaffolding
        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) {
        // Use sequential indices (1-based) for the wire format to match the Rust scaffolding
        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) {
      // Check that the value is a valid enum variant
      if (!this.#validValues.includes(value)) {
          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(
                    FfiConverterUInt64.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 += FfiConverterUInt64.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);
            FfiConverterUInt64.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 = undefined, minKeywordLength = undefined } = {}) {
                super();
            try {
                FfiConverterFloat64.checkType(score);
            } catch (e) {
                if (e instanceof UniFFITypeError) {
                    e.addItemDescriptionPart("score");
                }
                throw e;
            }
            this.score = score;try {
                FfiConverterInt32.checkType(minKeywordLength);
            } catch (e) {
                if (e instanceof UniFFITypeError) {
                    e.addItemDescriptionPart("minKeywordLength");
                }
                throw e;
            }
            this.minKeywordLength = minKeywordLength;
    }
}

// Export the FFIConverter object to make external types work.
export class FfiConverterTypeSuggestProviderConfig extends FfiConverterArrayBuffer {
    static read(dataStream) {
        // Use sequential indices (1-based) for the wire format to match the Rust scaffolding
        switch (dataStream.readInt32()) {
            case 1:
                return new SuggestProviderConfig.Weather({
                    score: FfiConverterFloat64.read(dataStream),
                    minKeywordLength: FfiConverterInt32.read(dataStream)
                });
            default:
                throw new UniFFITypeError("Unknown SuggestProviderConfig variant");
        }
    }

    static write(dataStream, value) {
        // Use sequential indices (1-based) for the wire format to match the Rust scaffolding
        if (value instanceof SuggestProviderConfig.Weather) {
            dataStream.writeInt32(1);
            FfiConverterFloat64.write(dataStream, value.score);
            FfiConverterInt32.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 += FfiConverterFloat64.computeSize(value.score);
            totalSize += FfiConverterInt32.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`);
      }
    }
}
// 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 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 new 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 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 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 new 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 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 new 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)
    }
}

/**
 * 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 SuggestStoreInterface {
    /**
     * Return whether any suggestions have been dismissed.
     * @returns {Promise<boolean>}}
     */
    async anyDismissedSuggestions() {
      throw Error("anyDismissedSuggestions not implemented");
    }
    /**
     * Removes all content from the database.
     */
    async clear() {
      throw Error("clear not implemented");
    }
    /**
     * Clear dismissed suggestions
     */
    async clearDismissedSuggestions() {
      throw Error("clearDismissedSuggestions not implemented");
    }
    /**
     * Dismiss a suggestion by its dismissal key.
     * 
     * Dismissed suggestions cannot be fetched again.
     * 
     * Prefer [SuggestStore::dismiss_by_suggestion] if you have a
     * `crate::Suggestion`. This method is intended for cases where a
     * suggestion originates outside this component.
     * @param {string} key
     */
    async dismissByKey(
        key) {
      throw Error("dismissByKey not implemented");
    }
    /**
     * Dismiss a suggestion.
     * 
     * Dismissed suggestions cannot be fetched again.
     * @param {Suggestion[keyof Suggestion]} suggestion
     */
    async dismissBySuggestion(
        suggestion) {
      throw Error("dismissBySuggestion not implemented");
    }
    /**
     * Deprecated, use [SuggestStore::dismiss_by_suggestion] or
     * [SuggestStore::dismiss_by_key] instead.
     * 
     * Dismiss a suggestion
     * 
     * Dismissed suggestions will not be returned again
     * @param {string} suggestionUrl
     */
    async dismissSuggestion(
        suggestionUrl) {
      throw Error("dismissSuggestion not implemented");
    }
    /**
     * Fetches a geoname's names stored in the database.
     * 
     * See `fetch_geoname_alternates` in `geoname.rs` for documentation.
     * @param {Geoname} geoname
     * @returns {Promise<GeonameAlternates>}}
     */
    async fetchGeonameAlternates(
        geoname) {
      throw Error("fetchGeonameAlternates not implemented");
    }
    /**
     * Fetches geonames stored in the database. A geoname represents a
     * geographic place.
     * 
     * See `fetch_geonames` in `geoname.rs` for documentation.
     * @param {string} query
     * @param {boolean} matchNamePrefix
     * @param {?Array.<Geoname>} filter
     * @returns {Promise<Array.<GeonameMatch>>}}
     */
    async fetchGeonames(
        query, 
        matchNamePrefix, 
        filter) {
      throw Error("fetchGeonames not implemented");
    }
    /**
     * Returns global Suggest configuration data.
     * @returns {Promise<SuggestGlobalConfig>}}
     */
    async fetchGlobalConfig() {
      throw Error("fetchGlobalConfig not implemented");
    }
    /**
     * Returns per-provider Suggest configuration data.
     * @param {SuggestionProvider[keyof SuggestionProvider]} provider
     * @returns {Promise<?SuggestProviderConfig[keyof SuggestProviderConfig]>}}
     */
    async fetchProviderConfig(
        provider) {
      throw Error("fetchProviderConfig not implemented");
    }
    /**
     * Ingests new suggestions from Remote Settings.
     * @param {SuggestIngestionConstraints} constraints
     * @returns {Promise<SuggestIngestionMetrics>}}
     */
    async ingest(
        constraints) {
      throw Error("ingest not implemented");
    }
    /**
     * 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.
     * @param {?InterruptKind[keyof InterruptKind]} kind
     */
    interrupt(
        kind = null) {
      throw Error("interrupt not implemented");
    }
    /**
     * Return whether a suggestion has been dismissed given its dismissal key.
     * 
     * [SuggestStore::query] will never return dismissed suggestions, so
     * normally you never need to know whether a suggestion has been dismissed.
     * This method is intended for cases where a dismissal key originates
     * outside this component.
     * @param {string} key
     * @returns {Promise<boolean>}}
     */
    async isDismissedByKey(
        key) {
      throw Error("isDismissedByKey not implemented");
    }
    /**
     * Return whether a suggestion has been dismissed.
     * 
     * [SuggestStore::query] will never return dismissed suggestions, so
     * normally you never need to know whether a `Suggestion` has been
     * dismissed, but this method can be used to do so.
     * @param {Suggestion[keyof Suggestion]} suggestion
     * @returns {Promise<boolean>}}
     */
    async isDismissedBySuggestion(
        suggestion) {
      throw Error("isDismissedBySuggestion not implemented");
    }
    /**
     * Queries the database for suggestions.
     * @param {SuggestionQuery} query
     * @returns {Promise<Array.<Suggestion[keyof Suggestion]>>}}
     */
    async query(
        query) {
      throw Error("query not implemented");
    }
    /**
     * Queries the database for suggestions.
     * @param {SuggestionQuery} query
     * @returns {Promise<QueryWithMetricsResult>}}
     */
    async queryWithMetrics(
        query) {
      throw Error("queryWithMetrics not implemented");
    }

}

/**
 * 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 extends SuggestStoreInterface {
    // Use `init` to instantiate this class.
    // DO NOT USE THIS CONSTRUCTOR DIRECTLY
    constructor(opts) {
        super();
        if (!Object.prototype.hasOwnProperty.call(opts, constructUniffiObject)) {
            throw new UniFFIError("Attempting to construct an int 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.
     * @param {string} path
     * @param {RemoteSettingsService} remoteSettingsService
     * @returns {SuggestStore}
     */
    static init(
        path, 
        remoteSettingsService) {
       
        FfiConverterString.checkType(path);
        FfiConverterTypeRemoteSettingsService.checkType(remoteSettingsService);
        const result = UniFFIScaffolding.callSync(
            173, // uniffi_suggest_fn_constructor_suggeststore_new
            FfiConverterString.lower(path),
            FfiConverterTypeRemoteSettingsService.lower(remoteSettingsService),
        )
        return handleRustResult(
            result,
            FfiConverterTypeSuggestStore.lift.bind(FfiConverterTypeSuggestStore),
            null,
        )
    }

    /**
     * Return whether any suggestions have been dismissed.
     * @returns {Promise<boolean>}}
     */
    async anyDismissedSuggestions() {
       
        const result = await UniFFIScaffolding.callAsyncWrapper(
            174, // uniffi_suggest_fn_method_suggeststore_any_dismissed_suggestions
            FfiConverterTypeSuggestStore.lowerReceiver(this),
        )
        return handleRustResult(
            result,
            FfiConverterBoolean.lift.bind(FfiConverterBoolean),
            FfiConverterTypeSuggestApiError.lift.bind(FfiConverterTypeSuggestApiError),
        )
    }

    /**
     * Removes all content from the database.
     */
    async clear() {
       
        const result = await UniFFIScaffolding.callAsyncWrapper(
            175, // uniffi_suggest_fn_method_suggeststore_clear
            FfiConverterTypeSuggestStore.lowerReceiver(this),
        )
        return handleRustResult(
            result,
            (result) => undefined,
            FfiConverterTypeSuggestApiError.lift.bind(FfiConverterTypeSuggestApiError),
        )
    }

    /**
     * Clear dismissed suggestions
     */
    async clearDismissedSuggestions() {
       
        const result = await UniFFIScaffolding.callAsyncWrapper(
            176, // uniffi_suggest_fn_method_suggeststore_clear_dismissed_suggestions
            FfiConverterTypeSuggestStore.lowerReceiver(this),
        )
        return handleRustResult(
            result,
            (result) => undefined,
            FfiConverterTypeSuggestApiError.lift.bind(FfiConverterTypeSuggestApiError),
        )
    }

    /**
     * Dismiss a suggestion by its dismissal key.
     * 
     * Dismissed suggestions cannot be fetched again.
     * 
     * Prefer [SuggestStore::dismiss_by_suggestion] if you have a
     * `crate::Suggestion`. This method is intended for cases where a
     * suggestion originates outside this component.
     * @param {string} key
     */
    async dismissByKey(
        key) {
       
        FfiConverterString.checkType(key);
        const result = await UniFFIScaffolding.callAsyncWrapper(
            177, // uniffi_suggest_fn_method_suggeststore_dismiss_by_key
            FfiConverterTypeSuggestStore.lowerReceiver(this),
            FfiConverterString.lower(key),
        )
        return handleRustResult(
            result,
            (result) => undefined,
            FfiConverterTypeSuggestApiError.lift.bind(FfiConverterTypeSuggestApiError),
        )
    }

    /**
     * Dismiss a suggestion.
     * 
     * Dismissed suggestions cannot be fetched again.
     * @param {Suggestion[keyof Suggestion]} suggestion
     */
    async dismissBySuggestion(
        suggestion) {
       
        FfiConverterTypeSuggestion.checkType(suggestion);
        const result = await UniFFIScaffolding.callAsyncWrapper(
            178, // uniffi_suggest_fn_method_suggeststore_dismiss_by_suggestion
            FfiConverterTypeSuggestStore.lowerReceiver(this),
            FfiConverterTypeSuggestion.lower(suggestion),
        )
        return handleRustResult(
            result,
            (result) => undefined,
            FfiConverterTypeSuggestApiError.lift.bind(FfiConverterTypeSuggestApiError),
        )
    }

    /**
     * Deprecated, use [SuggestStore::dismiss_by_suggestion] or
     * [SuggestStore::dismiss_by_key] instead.
     * 
     * Dismiss a suggestion
     * 
     * Dismissed suggestions will not be returned again
     * @param {string} suggestionUrl
     */
    async dismissSuggestion(
        suggestionUrl) {
       
        FfiConverterString.checkType(suggestionUrl);
        const result = await UniFFIScaffolding.callAsyncWrapper(
            179, // uniffi_suggest_fn_method_suggeststore_dismiss_suggestion
            FfiConverterTypeSuggestStore.lowerReceiver(this),
            FfiConverterString.lower(suggestionUrl),
        )
        return handleRustResult(
            result,
            (result) => undefined,
            FfiConverterTypeSuggestApiError.lift.bind(FfiConverterTypeSuggestApiError),
        )
    }

    /**
     * Fetches a geoname's names stored in the database.
     * 
     * See `fetch_geoname_alternates` in `geoname.rs` for documentation.
     * @param {Geoname} geoname
     * @returns {Promise<GeonameAlternates>}}
     */
    async fetchGeonameAlternates(
        geoname) {
       
        FfiConverterTypeGeoname.checkType(geoname);
        const result = await UniFFIScaffolding.callAsyncWrapper(
            180, // uniffi_suggest_fn_method_suggeststore_fetch_geoname_alternates
            FfiConverterTypeSuggestStore.lowerReceiver(this),
            FfiConverterTypeGeoname.lower(geoname),
        )
        return handleRustResult(
            result,
            FfiConverterTypeGeonameAlternates.lift.bind(FfiConverterTypeGeonameAlternates),
            FfiConverterTypeSuggestApiError.lift.bind(FfiConverterTypeSuggestApiError),
        )
    }

    /**
     * Fetches geonames stored in the database. A geoname represents a
     * geographic place.
     * 
     * See `fetch_geonames` in `geoname.rs` for documentation.
     * @param {string} query
     * @param {boolean} matchNamePrefix
     * @param {?Array.<Geoname>} filter
     * @returns {Promise<Array.<GeonameMatch>>}}
     */
    async fetchGeonames(
        query, 
        matchNamePrefix, 
        filter) {
       
        FfiConverterString.checkType(query);
        FfiConverterBoolean.checkType(matchNamePrefix);
        FfiConverterOptionalSequenceTypeGeoname.checkType(filter);
        const result = await UniFFIScaffolding.callAsyncWrapper(
            181, // uniffi_suggest_fn_method_suggeststore_fetch_geonames
            FfiConverterTypeSuggestStore.lowerReceiver(this),
            FfiConverterString.lower(query),
            FfiConverterBoolean.lower(matchNamePrefix),
            FfiConverterOptionalSequenceTypeGeoname.lower(filter),
        )
        return handleRustResult(
            result,
            FfiConverterSequenceTypeGeonameMatch.lift.bind(FfiConverterSequenceTypeGeonameMatch),
            FfiConverterTypeSuggestApiError.lift.bind(FfiConverterTypeSuggestApiError),
        )
    }

    /**
     * Returns global Suggest configuration data.
     * @returns {Promise<SuggestGlobalConfig>}}
     */
    async fetchGlobalConfig() {
       
        const result = await UniFFIScaffolding.callAsyncWrapper(
            182, // uniffi_suggest_fn_method_suggeststore_fetch_global_config
            FfiConverterTypeSuggestStore.lowerReceiver(this),
        )
        return handleRustResult(
            result,
            FfiConverterTypeSuggestGlobalConfig.lift.bind(FfiConverterTypeSuggestGlobalConfig),
            FfiConverterTypeSuggestApiError.lift.bind(FfiConverterTypeSuggestApiError),
        )
    }

    /**
     * Returns per-provider Suggest configuration data.
     * @param {SuggestionProvider[keyof SuggestionProvider]} provider
     * @returns {Promise<?SuggestProviderConfig[keyof SuggestProviderConfig]>}}
     */
    async fetchProviderConfig(
        provider) {
       
        FfiConverterTypeSuggestionProvider.checkType(provider);
        const result = await UniFFIScaffolding.callAsyncWrapper(
            183, // uniffi_suggest_fn_method_suggeststore_fetch_provider_config
            FfiConverterTypeSuggestStore.lowerReceiver(this),
            FfiConverterTypeSuggestionProvider.lower(provider),
        )
        return handleRustResult(
            result,
            FfiConverterOptionalTypeSuggestProviderConfig.lift.bind(FfiConverterOptionalTypeSuggestProviderConfig),
            FfiConverterTypeSuggestApiError.lift.bind(FfiConverterTypeSuggestApiError),
        )
    }

    /**
     * Ingests new suggestions from Remote Settings.
     * @param {SuggestIngestionConstraints} constraints
     * @returns {Promise<SuggestIngestionMetrics>}}
     */
    async ingest(
        constraints) {
       
        FfiConverterTypeSuggestIngestionConstraints.checkType(constraints);
        const result = await UniFFIScaffolding.callAsyncWrapper(
            184, // uniffi_suggest_fn_method_suggeststore_ingest
            FfiConverterTypeSuggestStore.lowerReceiver(this),
            FfiConverterTypeSuggestIngestionConstraints.lower(constraints),
        )
        return handleRustResult(
            result,
            FfiConverterTypeSuggestIngestionMetrics.lift.bind(FfiConverterTypeSuggestIngestionMetrics),
            FfiConverterTypeSuggestApiError.lift.bind(FfiConverterTypeSuggestApiError),
        )
    }

    /**
     * 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.
     * @param {?InterruptKind[keyof InterruptKind]} kind
     */
    interrupt(
        kind = null) {
       
        FfiConverterOptionalTypeInterruptKind.checkType(kind);
        const result = UniFFIScaffolding.callSync(
            185, // uniffi_suggest_fn_method_suggeststore_interrupt
            FfiConverterTypeSuggestStore.lowerReceiver(this),
            FfiConverterOptionalTypeInterruptKind.lower(kind),
        )
        return handleRustResult(
            result,
            (result) => undefined,
            null,
        )
    }

    /**
     * Return whether a suggestion has been dismissed given its dismissal key.
     * 
     * [SuggestStore::query] will never return dismissed suggestions, so
     * normally you never need to know whether a suggestion has been dismissed.
     * This method is intended for cases where a dismissal key originates
     * outside this component.
     * @param {string} key
     * @returns {Promise<boolean>}}
     */
    async isDismissedByKey(
        key) {
       
        FfiConverterString.checkType(key);
        const result = await UniFFIScaffolding.callAsyncWrapper(
            186, // uniffi_suggest_fn_method_suggeststore_is_dismissed_by_key
            FfiConverterTypeSuggestStore.lowerReceiver(this),
            FfiConverterString.lower(key),
        )
        return handleRustResult(
            result,
            FfiConverterBoolean.lift.bind(FfiConverterBoolean),
            FfiConverterTypeSuggestApiError.lift.bind(FfiConverterTypeSuggestApiError),
        )
    }

    /**
     * Return whether a suggestion has been dismissed.
     * 
     * [SuggestStore::query] will never return dismissed suggestions, so
     * normally you never need to know whether a `Suggestion` has been
     * dismissed, but this method can be used to do so.
     * @param {Suggestion[keyof Suggestion]} suggestion
     * @returns {Promise<boolean>}}
     */
    async isDismissedBySuggestion(
        suggestion) {
       
        FfiConverterTypeSuggestion.checkType(suggestion);
        const result = await UniFFIScaffolding.callAsyncWrapper(
            187, // uniffi_suggest_fn_method_suggeststore_is_dismissed_by_suggestion
            FfiConverterTypeSuggestStore.lowerReceiver(this),
            FfiConverterTypeSuggestion.lower(suggestion),
        )
        return handleRustResult(
            result,
            FfiConverterBoolean.lift.bind(FfiConverterBoolean),
            FfiConverterTypeSuggestApiError.lift.bind(FfiConverterTypeSuggestApiError),
        )
    }

    /**
     * Queries the database for suggestions.
     * @param {SuggestionQuery} query
     * @returns {Promise<Array.<Suggestion[keyof Suggestion]>>}}
     */
    async query(
        query) {
       
        FfiConverterTypeSuggestionQuery.checkType(query);
        const result = await UniFFIScaffolding.callAsyncWrapper(
            188, // uniffi_suggest_fn_method_suggeststore_query
            FfiConverterTypeSuggestStore.lowerReceiver(this),
            FfiConverterTypeSuggestionQuery.lower(query),
        )
        return handleRustResult(
            result,
            FfiConverterSequenceTypeSuggestion.lift.bind(FfiConverterSequenceTypeSuggestion),
            FfiConverterTypeSuggestApiError.lift.bind(FfiConverterTypeSuggestApiError),
        )
    }

    /**
     * Queries the database for suggestions.
     * @param {SuggestionQuery} query
     * @returns {Promise<QueryWithMetricsResult>}}
     */
    async queryWithMetrics(
        query) {
       
        FfiConverterTypeSuggestionQuery.checkType(query);
        const result = await UniFFIScaffolding.callAsyncWrapper(
            189, // uniffi_suggest_fn_method_suggeststore_query_with_metrics
            FfiConverterTypeSuggestStore.lowerReceiver(this),
            FfiConverterTypeSuggestionQuery.lower(query),
        )
        return handleRustResult(
            result,
            FfiConverterTypeQueryWithMetricsResult.lift.bind(FfiConverterTypeQueryWithMetricsResult),
            FfiConverterTypeSuggestApiError.lift.bind(FfiConverterTypeSuggestApiError),
        )
    }

}

// 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 lowerReceiver(value) {
        // This works exactly the same as lower for non-trait interfaces
        return this.lower(value);
    }

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

    static write(dataStream, value) {
        dataStream.writePointer(21, this.lower(value));
    }

    static computeSize(value) {
        return 8;
    }
}

import {
  FfiConverterTypeRemoteSettingsServer,
} from "./RustRemoteSettings.sys.mjs";

// Export the FFIConverter object to make external types work.
export { FfiConverterTypeRemoteSettingsServer };
import {
  FfiConverterTypeRemoteSettingsService,
} from "./RustRemoteSettings.sys.mjs";

// Export the FFIConverter object to make external types work.
export { FfiConverterTypeRemoteSettingsService };

/**
 * 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 SuggestStoreBuilderInterface {
    /**
     * build
     * @returns {SuggestStore}
     */
    build() {
      throw Error("build not implemented");
    }
    /**
     * Deprecated: this is no longer used by the suggest component.
     * @param {string} path
     * @returns {Promise<SuggestStoreBuilder>}}
     */
    async cachePath(
        path) {
      throw Error("cachePath not implemented");
    }
    /**
     * dataPath
     * @param {string} path
     * @returns {SuggestStoreBuilder}
     */
    dataPath(
        path) {
      throw Error("dataPath not implemented");
    }
    /**
     * 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).
     * @param {string} library
     * @param {?string} entryPoint
     * @returns {SuggestStoreBuilder}
     */
    loadExtension(
        library, 
        entryPoint) {
      throw Error("loadExtension not implemented");
    }
    /**
     * remoteSettingsBucketName
     * @param {string} bucketName
     * @returns {SuggestStoreBuilder}
     */
    remoteSettingsBucketName(
        bucketName) {
      throw Error("remoteSettingsBucketName not implemented");
    }
    /**
     * remoteSettingsServer
     * @param {RemoteSettingsServer[keyof RemoteSettingsServer]} server
     * @returns {SuggestStoreBuilder}
     */
    remoteSettingsServer(
        server) {
      throw Error("remoteSettingsServer not implemented");
    }
    /**
     * remoteSettingsService
     * @param {RemoteSettingsService} rsService
     * @returns {SuggestStoreBuilder}
     */
    remoteSettingsService(
        rsService) {
      throw Error("remoteSettingsService not implemented");
    }

}

/**
 * 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 extends SuggestStoreBuilderInterface {
    // Use `init` to instantiate this class.
    // DO NOT USE THIS CONSTRUCTOR DIRECTLY
    constructor(opts) {
        super();
        if (!Object.prototype.hasOwnProperty.call(opts, constructUniffiObject)) {
            throw new UniFFIError("Attempting to construct an int 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 result = UniFFIScaffolding.callSync(
            190, // uniffi_suggest_fn_constructor_suggeststorebuilder_new
        )
        return handleRustResult(
            result,
            FfiConverterTypeSuggestStoreBuilder.lift.bind(FfiConverterTypeSuggestStoreBuilder),
            null,
        )
    }

    /**
     * build
     * @returns {SuggestStore}
     */
    build() {
       
        const result = UniFFIScaffolding.callSync(
            191, // uniffi_suggest_fn_method_suggeststorebuilder_build
            FfiConverterTypeSuggestStoreBuilder.lowerReceiver(this),
        )
        return handleRustResult(
            result,
            FfiConverterTypeSuggestStore.lift.bind(FfiConverterTypeSuggestStore),
            FfiConverterTypeSuggestApiError.lift.bind(FfiConverterTypeSuggestApiError),
        )
    }

    /**
     * Deprecated: this is no longer used by the suggest component.
     * @param {string} path
     * @returns {Promise<SuggestStoreBuilder>}}
     */
    async cachePath(
        path) {
       
        FfiConverterString.checkType(path);
        const result = await UniFFIScaffolding.callAsyncWrapper(
            192, // uniffi_suggest_fn_method_suggeststorebuilder_cache_path
            FfiConverterTypeSuggestStoreBuilder.lowerReceiver(this),
            FfiConverterString.lower(path),
        )
        return handleRustResult(
            result,
            FfiConverterTypeSuggestStoreBuilder.lift.bind(FfiConverterTypeSuggestStoreBuilder),
            null,
        )
    }

    /**
     * dataPath
     * @param {string} path
     * @returns {SuggestStoreBuilder}
     */
    dataPath(
        path) {
       
        FfiConverterString.checkType(path);
        const result = UniFFIScaffolding.callSync(
            193, // uniffi_suggest_fn_method_suggeststorebuilder_data_path
            FfiConverterTypeSuggestStoreBuilder.lowerReceiver(this),
            FfiConverterString.lower(path),
        )
        return handleRustResult(
            result,
            FfiConverterTypeSuggestStoreBuilder.lift.bind(FfiConverterTypeSuggestStoreBuilder),
            null,
        )
    }

    /**
     * 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).
     * @param {string} library
     * @param {?string} entryPoint
     * @returns {SuggestStoreBuilder}
     */
    loadExtension(
        library, 
        entryPoint) {
       
        FfiConverterString.checkType(library);
        FfiConverterOptionalString.checkType(entryPoint);
        const result = UniFFIScaffolding.callSync(
            194, // uniffi_suggest_fn_method_suggeststorebuilder_load_extension
            FfiConverterTypeSuggestStoreBuilder.lowerReceiver(this),
            FfiConverterString.lower(library),
            FfiConverterOptionalString.lower(entryPoint),
        )
        return handleRustResult(
            result,
            FfiConverterTypeSuggestStoreBuilder.lift.bind(FfiConverterTypeSuggestStoreBuilder),
            null,
        )
    }

    /**
     * remoteSettingsBucketName
     * @param {string} bucketName
     * @returns {SuggestStoreBuilder}
     */
    remoteSettingsBucketName(
        bucketName) {
       
        FfiConverterString.checkType(bucketName);
        const result = UniFFIScaffolding.callSync(
            195, // uniffi_suggest_fn_method_suggeststorebuilder_remote_settings_bucket_name
            FfiConverterTypeSuggestStoreBuilder.lowerReceiver(this),
            FfiConverterString.lower(bucketName),
        )
        return handleRustResult(
            result,
            FfiConverterTypeSuggestStoreBuilder.lift.bind(FfiConverterTypeSuggestStoreBuilder),
            null,
        )
    }

    /**
     * remoteSettingsServer
     * @param {RemoteSettingsServer[keyof RemoteSettingsServer]} server
     * @returns {SuggestStoreBuilder}
     */
    remoteSettingsServer(
        server) {
       
        FfiConverterTypeRemoteSettingsServer.checkType(server);
        const result = UniFFIScaffolding.callSync(
            196, // uniffi_suggest_fn_method_suggeststorebuilder_remote_settings_server
            FfiConverterTypeSuggestStoreBuilder.lowerReceiver(this),
            FfiConverterTypeRemoteSettingsServer.lower(server),
        )
        return handleRustResult(
            result,
            FfiConverterTypeSuggestStoreBuilder.lift.bind(FfiConverterTypeSuggestStoreBuilder),
            null,
        )
    }

    /**
     * remoteSettingsService
     * @param {RemoteSettingsService} rsService
     * @returns {SuggestStoreBuilder}
     */
    remoteSettingsService(
        rsService) {
       
        FfiConverterTypeRemoteSettingsService.checkType(rsService);
        const result = UniFFIScaffolding.callSync(
            197, // uniffi_suggest_fn_method_suggeststorebuilder_remote_settings_service
            FfiConverterTypeSuggestStoreBuilder.lowerReceiver(this),
            FfiConverterTypeRemoteSettingsService.lower(rsService),
        )
        return handleRustResult(
            result,
            FfiConverterTypeSuggestStoreBuilder.lift.bind(FfiConverterTypeSuggestStoreBuilder),
            null,
        )
    }

}

// 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 lowerReceiver(value) {
        // This works exactly the same as lower for non-trait interfaces
        return this.lower(value);
    }

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

    static write(dataStream, value) {
        dataStream.writePointer(22, this.lower(value));
    }

    static computeSize(value) {
        return 8;
    }
}

