// 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,
};
/**
 * Calculate score for a piece of categorized content based on a user interest vector.
 * 
 * This scoring function is of the following properties:
 * - The score ranges from 0.0 to 1.0
 * - The score is monotonically increasing for the accumulated interest count
 * 
 * # Params:
 * - `interest_vector`: a user interest vector that can be fetched via
 * `RelevancyStore::user_interest_vector()`.
 * - `content_categories`: a list of categories (interests) of the give content.
 * # Return:
 * - A score ranges in [0, 1].
 * @param {InterestVector} interestVector
 * @param {Array.<Interest[keyof Interest]>} contentCategories
 * @returns {number}
 */
export function score(
    interestVector, 
    contentCategories) {
   
FfiConverterTypeInterestVector.checkType(interestVector);
FfiConverterSequenceTypeInterest.checkType(contentCategories);
const result = UniFFIScaffolding.callSync(
    142, // uniffi_relevancy_fn_func_score
    FfiConverterTypeInterestVector.lower(interestVector),
    FfiConverterSequenceTypeInterest.lower(contentCategories),
)
return handleRustResult(
    result,
    FfiConverterFloat64.lift.bind(FfiConverterFloat64),
    null,
)
}






/**
 * BanditData
 */
export class BanditData {
    constructor(
        {
            bandit, 
            arm, 
            impressions, 
            clicks, 
            alpha, 
            beta
        } = {
            bandit: undefined, 
            arm: undefined, 
            impressions: undefined, 
            clicks: undefined, 
            alpha: undefined, 
            beta: undefined
        }
    ) {
        try {
            FfiConverterString.checkType(bandit)
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart("bandit");
            }
            throw e;
        }
        try {
            FfiConverterString.checkType(arm)
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart("arm");
            }
            throw e;
        }
        try {
            FfiConverterUInt64.checkType(impressions)
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart("impressions");
            }
            throw e;
        }
        try {
            FfiConverterUInt64.checkType(clicks)
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart("clicks");
            }
            throw e;
        }
        try {
            FfiConverterUInt64.checkType(alpha)
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart("alpha");
            }
            throw e;
        }
        try {
            FfiConverterUInt64.checkType(beta)
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart("beta");
            }
            throw e;
        }
        /**
         * @type {string}
         */
        this.bandit = bandit;
        /**
         * @type {string}
         */
        this.arm = arm;
        /**
         * @type {number}
         */
        this.impressions = impressions;
        /**
         * @type {number}
         */
        this.clicks = clicks;
        /**
         * @type {number}
         */
        this.alpha = alpha;
        /**
         * @type {number}
         */
        this.beta = beta;
    }

    equals(other) {
        return (
            this.bandit == other.bandit
            && this.arm == other.arm
            && this.impressions == other.impressions
            && this.clicks == other.clicks
            && this.alpha == other.alpha
            && this.beta == other.beta
        )
    }
}

// Export the FFIConverter object to make external types work.
export class FfiConverterTypeBanditData extends FfiConverterArrayBuffer {
    static read(dataStream) {
        return new BanditData({
            bandit: FfiConverterString.read(dataStream),
            arm: FfiConverterString.read(dataStream),
            impressions: FfiConverterUInt64.read(dataStream),
            clicks: FfiConverterUInt64.read(dataStream),
            alpha: FfiConverterUInt64.read(dataStream),
            beta: FfiConverterUInt64.read(dataStream),
        });
    }
    static write(dataStream, value) {
        FfiConverterString.write(dataStream, value.bandit);
        FfiConverterString.write(dataStream, value.arm);
        FfiConverterUInt64.write(dataStream, value.impressions);
        FfiConverterUInt64.write(dataStream, value.clicks);
        FfiConverterUInt64.write(dataStream, value.alpha);
        FfiConverterUInt64.write(dataStream, value.beta);
    }

    static computeSize(value) {
        let totalSize = 0;
        totalSize += FfiConverterString.computeSize(value.bandit);
        totalSize += FfiConverterString.computeSize(value.arm);
        totalSize += FfiConverterUInt64.computeSize(value.impressions);
        totalSize += FfiConverterUInt64.computeSize(value.clicks);
        totalSize += FfiConverterUInt64.computeSize(value.alpha);
        totalSize += FfiConverterUInt64.computeSize(value.beta);
        return totalSize
    }

    static checkType(value) {
        super.checkType(value);
        if (!(value instanceof BanditData)) {
            throw new UniFFITypeError(`Expected 'BanditData', found '${typeof value}'`);
        }
        try {
            FfiConverterString.checkType(value.bandit);
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart(".bandit");
            }
            throw e;
        }
        try {
            FfiConverterString.checkType(value.arm);
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart(".arm");
            }
            throw e;
        }
        try {
            FfiConverterUInt64.checkType(value.impressions);
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart(".impressions");
            }
            throw e;
        }
        try {
            FfiConverterUInt64.checkType(value.clicks);
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart(".clicks");
            }
            throw e;
        }
        try {
            FfiConverterUInt64.checkType(value.alpha);
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart(".alpha");
            }
            throw e;
        }
        try {
            FfiConverterUInt64.checkType(value.beta);
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart(".beta");
            }
            throw e;
        }
    }
}


/**
 * Interest metrics that we want to send to Glean as part of the validation process.  These contain
 * the cosine similarity when comparing the user's interest against various interest vectors that
 * consumers may use.
 * 
 * Cosine similarly was chosen because it seems easy to calculate.  This was then matched against
 * some semi-plausible real-world interest vectors that consumers might use.  This is all up for
 * debate and we may decide to switch to some other metrics.
 * 
 * Similarity values are transformed to integers by multiplying the floating point value by 1000 and
 * rounding.  This is to make them compatible with Glean's distribution metrics.
 */
export class InterestMetrics {
    constructor(
        {
            topSingleInterestSimilarity, 
            top2interestSimilarity, 
            top3interestSimilarity
        } = {
            topSingleInterestSimilarity: undefined, 
            top2interestSimilarity: undefined, 
            top3interestSimilarity: undefined
        }
    ) {
        try {
            FfiConverterUInt32.checkType(topSingleInterestSimilarity)
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart("topSingleInterestSimilarity");
            }
            throw e;
        }
        try {
            FfiConverterUInt32.checkType(top2interestSimilarity)
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart("top2interestSimilarity");
            }
            throw e;
        }
        try {
            FfiConverterUInt32.checkType(top3interestSimilarity)
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart("top3interestSimilarity");
            }
            throw e;
        }
        /**
         * Similarity between the user's interest vector and an interest vector where the element for
         * the user's top interest is copied, but all other interests are set to zero.  This measures
         * the highest possible similarity with consumers that used interest vectors with a single
         * interest set.
         * @type {number}
         */
        this.topSingleInterestSimilarity = topSingleInterestSimilarity;
        /**
         * The same as before, but the top 2 interests are copied. This measures the highest possible
         * similarity with consumers that used interest vectors with a two interests (note: this means
         * they would need to choose the user's top two interests and have the exact same proportion
         * between them as the user).
         * @type {number}
         */
        this.top2interestSimilarity = top2interestSimilarity;
        /**
         * The same as before, but the top 3 interests are copied.
         * @type {number}
         */
        this.top3interestSimilarity = top3interestSimilarity;
    }

    equals(other) {
        return (
            this.topSingleInterestSimilarity == other.topSingleInterestSimilarity
            && this.top2interestSimilarity == other.top2interestSimilarity
            && this.top3interestSimilarity == other.top3interestSimilarity
        )
    }
}

// Export the FFIConverter object to make external types work.
export class FfiConverterTypeInterestMetrics extends FfiConverterArrayBuffer {
    static read(dataStream) {
        return new InterestMetrics({
            topSingleInterestSimilarity: FfiConverterUInt32.read(dataStream),
            top2interestSimilarity: FfiConverterUInt32.read(dataStream),
            top3interestSimilarity: FfiConverterUInt32.read(dataStream),
        });
    }
    static write(dataStream, value) {
        FfiConverterUInt32.write(dataStream, value.topSingleInterestSimilarity);
        FfiConverterUInt32.write(dataStream, value.top2interestSimilarity);
        FfiConverterUInt32.write(dataStream, value.top3interestSimilarity);
    }

    static computeSize(value) {
        let totalSize = 0;
        totalSize += FfiConverterUInt32.computeSize(value.topSingleInterestSimilarity);
        totalSize += FfiConverterUInt32.computeSize(value.top2interestSimilarity);
        totalSize += FfiConverterUInt32.computeSize(value.top3interestSimilarity);
        return totalSize
    }

    static checkType(value) {
        super.checkType(value);
        if (!(value instanceof InterestMetrics)) {
            throw new UniFFITypeError(`Expected 'InterestMetrics', found '${typeof value}'`);
        }
        try {
            FfiConverterUInt32.checkType(value.topSingleInterestSimilarity);
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart(".topSingleInterestSimilarity");
            }
            throw e;
        }
        try {
            FfiConverterUInt32.checkType(value.top2interestSimilarity);
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart(".top2interestSimilarity");
            }
            throw e;
        }
        try {
            FfiConverterUInt32.checkType(value.top3interestSimilarity);
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart(".top3interestSimilarity");
            }
            throw e;
        }
    }
}
/**
 * Vector storing a count value for each interest
 * 
 * Here "vector" refers to the mathematical object, not a Rust `Vec`.  It always has a fixed
 * number of elements.
 */
export class InterestVector {
    constructor(
        {
            inconclusive, 
            animals, 
            arts, 
            autos, 
            business, 
            career, 
            education, 
            fashion, 
            finance, 
            food, 
            government, 
            hobbies, 
            home, 
            news, 
            realEstate, 
            society, 
            sports, 
            tech, 
            travel
        } = {
            inconclusive: undefined, 
            animals: undefined, 
            arts: undefined, 
            autos: undefined, 
            business: undefined, 
            career: undefined, 
            education: undefined, 
            fashion: undefined, 
            finance: undefined, 
            food: undefined, 
            government: undefined, 
            hobbies: undefined, 
            home: undefined, 
            news: undefined, 
            realEstate: undefined, 
            society: undefined, 
            sports: undefined, 
            tech: undefined, 
            travel: undefined
        }
    ) {
        try {
            FfiConverterUInt32.checkType(inconclusive)
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart("inconclusive");
            }
            throw e;
        }
        try {
            FfiConverterUInt32.checkType(animals)
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart("animals");
            }
            throw e;
        }
        try {
            FfiConverterUInt32.checkType(arts)
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart("arts");
            }
            throw e;
        }
        try {
            FfiConverterUInt32.checkType(autos)
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart("autos");
            }
            throw e;
        }
        try {
            FfiConverterUInt32.checkType(business)
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart("business");
            }
            throw e;
        }
        try {
            FfiConverterUInt32.checkType(career)
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart("career");
            }
            throw e;
        }
        try {
            FfiConverterUInt32.checkType(education)
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart("education");
            }
            throw e;
        }
        try {
            FfiConverterUInt32.checkType(fashion)
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart("fashion");
            }
            throw e;
        }
        try {
            FfiConverterUInt32.checkType(finance)
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart("finance");
            }
            throw e;
        }
        try {
            FfiConverterUInt32.checkType(food)
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart("food");
            }
            throw e;
        }
        try {
            FfiConverterUInt32.checkType(government)
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart("government");
            }
            throw e;
        }
        try {
            FfiConverterUInt32.checkType(hobbies)
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart("hobbies");
            }
            throw e;
        }
        try {
            FfiConverterUInt32.checkType(home)
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart("home");
            }
            throw e;
        }
        try {
            FfiConverterUInt32.checkType(news)
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart("news");
            }
            throw e;
        }
        try {
            FfiConverterUInt32.checkType(realEstate)
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart("realEstate");
            }
            throw e;
        }
        try {
            FfiConverterUInt32.checkType(society)
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart("society");
            }
            throw e;
        }
        try {
            FfiConverterUInt32.checkType(sports)
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart("sports");
            }
            throw e;
        }
        try {
            FfiConverterUInt32.checkType(tech)
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart("tech");
            }
            throw e;
        }
        try {
            FfiConverterUInt32.checkType(travel)
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart("travel");
            }
            throw e;
        }
        /**
         * @type {number}
         */
        this.inconclusive = inconclusive;
        /**
         * @type {number}
         */
        this.animals = animals;
        /**
         * @type {number}
         */
        this.arts = arts;
        /**
         * @type {number}
         */
        this.autos = autos;
        /**
         * @type {number}
         */
        this.business = business;
        /**
         * @type {number}
         */
        this.career = career;
        /**
         * @type {number}
         */
        this.education = education;
        /**
         * @type {number}
         */
        this.fashion = fashion;
        /**
         * @type {number}
         */
        this.finance = finance;
        /**
         * @type {number}
         */
        this.food = food;
        /**
         * @type {number}
         */
        this.government = government;
        /**
         * @type {number}
         */
        this.hobbies = hobbies;
        /**
         * @type {number}
         */
        this.home = home;
        /**
         * @type {number}
         */
        this.news = news;
        /**
         * @type {number}
         */
        this.realEstate = realEstate;
        /**
         * @type {number}
         */
        this.society = society;
        /**
         * @type {number}
         */
        this.sports = sports;
        /**
         * @type {number}
         */
        this.tech = tech;
        /**
         * @type {number}
         */
        this.travel = travel;
    }

    equals(other) {
        return (
            this.inconclusive == other.inconclusive
            && this.animals == other.animals
            && this.arts == other.arts
            && this.autos == other.autos
            && this.business == other.business
            && this.career == other.career
            && this.education == other.education
            && this.fashion == other.fashion
            && this.finance == other.finance
            && this.food == other.food
            && this.government == other.government
            && this.hobbies == other.hobbies
            && this.home == other.home
            && this.news == other.news
            && this.realEstate == other.realEstate
            && this.society == other.society
            && this.sports == other.sports
            && this.tech == other.tech
            && this.travel == other.travel
        )
    }
}

// Export the FFIConverter object to make external types work.
export class FfiConverterTypeInterestVector extends FfiConverterArrayBuffer {
    static read(dataStream) {
        return new InterestVector({
            inconclusive: FfiConverterUInt32.read(dataStream),
            animals: FfiConverterUInt32.read(dataStream),
            arts: FfiConverterUInt32.read(dataStream),
            autos: FfiConverterUInt32.read(dataStream),
            business: FfiConverterUInt32.read(dataStream),
            career: FfiConverterUInt32.read(dataStream),
            education: FfiConverterUInt32.read(dataStream),
            fashion: FfiConverterUInt32.read(dataStream),
            finance: FfiConverterUInt32.read(dataStream),
            food: FfiConverterUInt32.read(dataStream),
            government: FfiConverterUInt32.read(dataStream),
            hobbies: FfiConverterUInt32.read(dataStream),
            home: FfiConverterUInt32.read(dataStream),
            news: FfiConverterUInt32.read(dataStream),
            realEstate: FfiConverterUInt32.read(dataStream),
            society: FfiConverterUInt32.read(dataStream),
            sports: FfiConverterUInt32.read(dataStream),
            tech: FfiConverterUInt32.read(dataStream),
            travel: FfiConverterUInt32.read(dataStream),
        });
    }
    static write(dataStream, value) {
        FfiConverterUInt32.write(dataStream, value.inconclusive);
        FfiConverterUInt32.write(dataStream, value.animals);
        FfiConverterUInt32.write(dataStream, value.arts);
        FfiConverterUInt32.write(dataStream, value.autos);
        FfiConverterUInt32.write(dataStream, value.business);
        FfiConverterUInt32.write(dataStream, value.career);
        FfiConverterUInt32.write(dataStream, value.education);
        FfiConverterUInt32.write(dataStream, value.fashion);
        FfiConverterUInt32.write(dataStream, value.finance);
        FfiConverterUInt32.write(dataStream, value.food);
        FfiConverterUInt32.write(dataStream, value.government);
        FfiConverterUInt32.write(dataStream, value.hobbies);
        FfiConverterUInt32.write(dataStream, value.home);
        FfiConverterUInt32.write(dataStream, value.news);
        FfiConverterUInt32.write(dataStream, value.realEstate);
        FfiConverterUInt32.write(dataStream, value.society);
        FfiConverterUInt32.write(dataStream, value.sports);
        FfiConverterUInt32.write(dataStream, value.tech);
        FfiConverterUInt32.write(dataStream, value.travel);
    }

    static computeSize(value) {
        let totalSize = 0;
        totalSize += FfiConverterUInt32.computeSize(value.inconclusive);
        totalSize += FfiConverterUInt32.computeSize(value.animals);
        totalSize += FfiConverterUInt32.computeSize(value.arts);
        totalSize += FfiConverterUInt32.computeSize(value.autos);
        totalSize += FfiConverterUInt32.computeSize(value.business);
        totalSize += FfiConverterUInt32.computeSize(value.career);
        totalSize += FfiConverterUInt32.computeSize(value.education);
        totalSize += FfiConverterUInt32.computeSize(value.fashion);
        totalSize += FfiConverterUInt32.computeSize(value.finance);
        totalSize += FfiConverterUInt32.computeSize(value.food);
        totalSize += FfiConverterUInt32.computeSize(value.government);
        totalSize += FfiConverterUInt32.computeSize(value.hobbies);
        totalSize += FfiConverterUInt32.computeSize(value.home);
        totalSize += FfiConverterUInt32.computeSize(value.news);
        totalSize += FfiConverterUInt32.computeSize(value.realEstate);
        totalSize += FfiConverterUInt32.computeSize(value.society);
        totalSize += FfiConverterUInt32.computeSize(value.sports);
        totalSize += FfiConverterUInt32.computeSize(value.tech);
        totalSize += FfiConverterUInt32.computeSize(value.travel);
        return totalSize
    }

    static checkType(value) {
        super.checkType(value);
        if (!(value instanceof InterestVector)) {
            throw new UniFFITypeError(`Expected 'InterestVector', found '${typeof value}'`);
        }
        try {
            FfiConverterUInt32.checkType(value.inconclusive);
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart(".inconclusive");
            }
            throw e;
        }
        try {
            FfiConverterUInt32.checkType(value.animals);
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart(".animals");
            }
            throw e;
        }
        try {
            FfiConverterUInt32.checkType(value.arts);
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart(".arts");
            }
            throw e;
        }
        try {
            FfiConverterUInt32.checkType(value.autos);
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart(".autos");
            }
            throw e;
        }
        try {
            FfiConverterUInt32.checkType(value.business);
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart(".business");
            }
            throw e;
        }
        try {
            FfiConverterUInt32.checkType(value.career);
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart(".career");
            }
            throw e;
        }
        try {
            FfiConverterUInt32.checkType(value.education);
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart(".education");
            }
            throw e;
        }
        try {
            FfiConverterUInt32.checkType(value.fashion);
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart(".fashion");
            }
            throw e;
        }
        try {
            FfiConverterUInt32.checkType(value.finance);
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart(".finance");
            }
            throw e;
        }
        try {
            FfiConverterUInt32.checkType(value.food);
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart(".food");
            }
            throw e;
        }
        try {
            FfiConverterUInt32.checkType(value.government);
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart(".government");
            }
            throw e;
        }
        try {
            FfiConverterUInt32.checkType(value.hobbies);
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart(".hobbies");
            }
            throw e;
        }
        try {
            FfiConverterUInt32.checkType(value.home);
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart(".home");
            }
            throw e;
        }
        try {
            FfiConverterUInt32.checkType(value.news);
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart(".news");
            }
            throw e;
        }
        try {
            FfiConverterUInt32.checkType(value.realEstate);
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart(".realEstate");
            }
            throw e;
        }
        try {
            FfiConverterUInt32.checkType(value.society);
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart(".society");
            }
            throw e;
        }
        try {
            FfiConverterUInt32.checkType(value.sports);
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart(".sports");
            }
            throw e;
        }
        try {
            FfiConverterUInt32.checkType(value.tech);
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart(".tech");
            }
            throw e;
        }
        try {
            FfiConverterUInt32.checkType(value.travel);
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart(".travel");
            }
            throw e;
        }
    }
}

/**
 * List of possible interests for a domain.  Domains can have be associated with one or multiple
 * interests.  `Inconclusive` is used for domains in the user's top sites that we can't classify
 * because there's no corresponding entry in the interest database.
 */
export const Interest = Object.freeze({
    /**
     * INCONCLUSIVE
     */
    INCONCLUSIVE: 0,
    /**
     * ANIMALS
     */
    ANIMALS: 1,
    /**
     * ARTS
     */
    ARTS: 2,
    /**
     * AUTOS
     */
    AUTOS: 3,
    /**
     * BUSINESS
     */
    BUSINESS: 4,
    /**
     * CAREER
     */
    CAREER: 5,
    /**
     * EDUCATION
     */
    EDUCATION: 6,
    /**
     * FASHION
     */
    FASHION: 7,
    /**
     * FINANCE
     */
    FINANCE: 8,
    /**
     * FOOD
     */
    FOOD: 9,
    /**
     * GOVERNMENT
     */
    GOVERNMENT: 10,
    /**
     * HOBBIES
     */
    HOBBIES: 12,
    /**
     * HOME
     */
    HOME: 13,
    /**
     * NEWS
     */
    NEWS: 14,
    /**
     * REAL_ESTATE
     */
    REAL_ESTATE: 15,
    /**
     * SOCIETY
     */
    SOCIETY: 16,
    /**
     * SPORTS
     */
    SPORTS: 17,
    /**
     * TECH
     */
    TECH: 18,
    /**
     * TRAVEL
     */
    TRAVEL: 19,
});

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

    static read(dataStream) {
        // Use sequential indices (1-based) for the wire format to match the Rust scaffolding
        switch (dataStream.readInt32()) {
            case 1:
                return Interest.INCONCLUSIVE
            case 2:
                return Interest.ANIMALS
            case 3:
                return Interest.ARTS
            case 4:
                return Interest.AUTOS
            case 5:
                return Interest.BUSINESS
            case 6:
                return Interest.CAREER
            case 7:
                return Interest.EDUCATION
            case 8:
                return Interest.FASHION
            case 9:
                return Interest.FINANCE
            case 10:
                return Interest.FOOD
            case 11:
                return Interest.GOVERNMENT
            case 12:
                return Interest.HOBBIES
            case 13:
                return Interest.HOME
            case 14:
                return Interest.NEWS
            case 15:
                return Interest.REAL_ESTATE
            case 16:
                return Interest.SOCIETY
            case 17:
                return Interest.SPORTS
            case 18:
                return Interest.TECH
            case 19:
                return Interest.TRAVEL
            default:
                throw new UniFFITypeError("Unknown Interest variant");
        }
    }

    static write(dataStream, value) {
        // Use sequential indices (1-based) for the wire format to match the Rust scaffolding
        if (value === Interest.INCONCLUSIVE) {
            dataStream.writeInt32(1);
            return;
        }
        if (value === Interest.ANIMALS) {
            dataStream.writeInt32(2);
            return;
        }
        if (value === Interest.ARTS) {
            dataStream.writeInt32(3);
            return;
        }
        if (value === Interest.AUTOS) {
            dataStream.writeInt32(4);
            return;
        }
        if (value === Interest.BUSINESS) {
            dataStream.writeInt32(5);
            return;
        }
        if (value === Interest.CAREER) {
            dataStream.writeInt32(6);
            return;
        }
        if (value === Interest.EDUCATION) {
            dataStream.writeInt32(7);
            return;
        }
        if (value === Interest.FASHION) {
            dataStream.writeInt32(8);
            return;
        }
        if (value === Interest.FINANCE) {
            dataStream.writeInt32(9);
            return;
        }
        if (value === Interest.FOOD) {
            dataStream.writeInt32(10);
            return;
        }
        if (value === Interest.GOVERNMENT) {
            dataStream.writeInt32(11);
            return;
        }
        if (value === Interest.HOBBIES) {
            dataStream.writeInt32(12);
            return;
        }
        if (value === Interest.HOME) {
            dataStream.writeInt32(13);
            return;
        }
        if (value === Interest.NEWS) {
            dataStream.writeInt32(14);
            return;
        }
        if (value === Interest.REAL_ESTATE) {
            dataStream.writeInt32(15);
            return;
        }
        if (value === Interest.SOCIETY) {
            dataStream.writeInt32(16);
            return;
        }
        if (value === Interest.SPORTS) {
            dataStream.writeInt32(17);
            return;
        }
        if (value === Interest.TECH) {
            dataStream.writeInt32(18);
            return;
        }
        if (value === Interest.TRAVEL) {
            dataStream.writeInt32(19);
            return;
        }
        throw new UniFFITypeError("Unknown Interest 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 Interest`);
      }
    }
}

/**
 * Errors we return via the public interface.
 */
export class RelevancyApiError extends Error {}


/**
 * Unexpected
 */
export class Unexpected extends RelevancyApiError {

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

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

    static errorClass = RelevancyApiError;
}
// 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;
            }
        })
    }
}



/**
 * RelevancyStoreInterface
 */
export class RelevancyStoreInterface {
    /**
     * Initializes probability distributions for any uninitialized items (arms) within a bandit model.
     * 
     * This method takes a `bandit` identifier and a list of `arms` (items) and ensures that each arm
     * in the list has an initialized probability distribution in the database. For each arm, if the
     * probability distribution does not already exist, it will be created, using Beta(1,1) as default,
     * which represents uniform distribution.
     * @param {string} bandit
     * @param {Array.<string>} arms
     */
    async banditInit(
        bandit, 
        arms) {
      throw Error("banditInit not implemented");
    }
    /**
     * Selects the optimal item (arm) to display to the user based on a multi-armed bandit model.
     * 
     * This method takes in a `bandit` identifier and a list of possible `arms` (items) and uses a
     * Thompson sampling approach to select the arm with the highest probability of success.
     * For each arm, it retrieves the Beta distribution parameters (alpha and beta) from the
     * database, creates a Beta distribution, and samples from it to estimate the arm's probability
     * of success. The arm with the highest sampled probability is selected and returned.
     * @param {string} bandit
     * @param {Array.<string>} arms
     * @returns {Promise<string>}}
     */
    async banditSelect(
        bandit, 
        arms) {
      throw Error("banditSelect not implemented");
    }
    /**
     * Updates the bandit model's arm data based on user interaction (selection or non-selection).
     * 
     * This method takes in a `bandit` identifier, an `arm` identifier, and a `selected` flag.
     * If `selected` is true, it updates the model to reflect a successful selection of the arm,
     * reinforcing its positive reward probability. If `selected` is false, it updates the
     * beta (failure) distribution of the arm, reflecting a lack of selection and reinforcing
     * its likelihood of a negative outcome.
     * @param {string} bandit
     * @param {string} arm
     * @param {boolean} selected
     */
    async banditUpdate(
        bandit, 
        arm, 
        selected) {
      throw Error("banditUpdate not implemented");
    }
    /**
     * Close any open resources (for example databases)
     * 
     * Calling `close` will interrupt any in-progress queries on other threads.
     */
    close() {
      throw Error("close not implemented");
    }
    /**
     * Download the interest data from remote settings if needed
     */
    async ensureInterestDataPopulated() {
      throw Error("ensureInterestDataPopulated not implemented");
    }
    /**
     * Retrieves the data for a specific bandit and arm.
     * @param {string} bandit
     * @param {string} arm
     * @returns {Promise<BanditData>}}
     */
    async getBanditData(
        bandit, 
        arm) {
      throw Error("getBanditData not implemented");
    }
    /**
     * Ingest top URLs to build the user's interest vector.
     * 
     * Consumer should pass a list of the user's top URLs by frecency to this method.  It will
     * then:
     * 
     * - Download the URL interest data from remote settings.  Eventually this should be cached /
     * stored in the database, but for now it would be fine to download fresh data each time.
     * - Match the user's top URls against the interest data to build up their interest vector.
     * - Store the user's interest vector in the database.
     * 
     * This method may execute for a long time and should only be called from a worker thread.
     * @param {Array.<string>} topUrlsByFrecency
     * @returns {Promise<InterestVector>}}
     */
    async ingest(
        topUrlsByFrecency) {
      throw Error("ingest not implemented");
    }
    /**
     * Interrupt any current database queries
     */
    interrupt() {
      throw Error("interrupt not implemented");
    }
    /**
     * Get the user's interest vector directly.
     * 
     * This runs after [Self::ingest].  It returns the interest vector directly so that the
     * consumer can show it in an `about:` page.
     * @returns {Promise<InterestVector>}}
     */
    async userInterestVector() {
      throw Error("userInterestVector not implemented");
    }

}

/**
 * RelevancyStore
 */
export class RelevancyStore extends RelevancyStoreInterface {
    // 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];
    }
    /**
     * Construct a new RelevancyStore
     * 
     * This is non-blocking since databases and other resources are lazily opened.
     * @param {string} dbPath
     * @param {RemoteSettingsService} remoteSettings
     * @returns {RelevancyStore}
     */
    static init(
        dbPath, 
        remoteSettings) {
       
        FfiConverterString.checkType(dbPath);
        FfiConverterTypeRemoteSettingsService.checkType(remoteSettings);
        const result = UniFFIScaffolding.callSync(
            143, // uniffi_relevancy_fn_constructor_relevancystore_new
            FfiConverterString.lower(dbPath),
            FfiConverterTypeRemoteSettingsService.lower(remoteSettings),
        )
        return handleRustResult(
            result,
            FfiConverterTypeRelevancyStore.lift.bind(FfiConverterTypeRelevancyStore),
            null,
        )
    }

    /**
     * Initializes probability distributions for any uninitialized items (arms) within a bandit model.
     * 
     * This method takes a `bandit` identifier and a list of `arms` (items) and ensures that each arm
     * in the list has an initialized probability distribution in the database. For each arm, if the
     * probability distribution does not already exist, it will be created, using Beta(1,1) as default,
     * which represents uniform distribution.
     * @param {string} bandit
     * @param {Array.<string>} arms
     */
    async banditInit(
        bandit, 
        arms) {
       
        FfiConverterString.checkType(bandit);
        FfiConverterSequenceString.checkType(arms);
        const result = await UniFFIScaffolding.callAsyncWrapper(
            144, // uniffi_relevancy_fn_method_relevancystore_bandit_init
            FfiConverterTypeRelevancyStore.lowerReceiver(this),
            FfiConverterString.lower(bandit),
            FfiConverterSequenceString.lower(arms),
        )
        return handleRustResult(
            result,
            (result) => undefined,
            FfiConverterTypeRelevancyApiError.lift.bind(FfiConverterTypeRelevancyApiError),
        )
    }

    /**
     * Selects the optimal item (arm) to display to the user based on a multi-armed bandit model.
     * 
     * This method takes in a `bandit` identifier and a list of possible `arms` (items) and uses a
     * Thompson sampling approach to select the arm with the highest probability of success.
     * For each arm, it retrieves the Beta distribution parameters (alpha and beta) from the
     * database, creates a Beta distribution, and samples from it to estimate the arm's probability
     * of success. The arm with the highest sampled probability is selected and returned.
     * @param {string} bandit
     * @param {Array.<string>} arms
     * @returns {Promise<string>}}
     */
    async banditSelect(
        bandit, 
        arms) {
       
        FfiConverterString.checkType(bandit);
        FfiConverterSequenceString.checkType(arms);
        const result = await UniFFIScaffolding.callAsyncWrapper(
            145, // uniffi_relevancy_fn_method_relevancystore_bandit_select
            FfiConverterTypeRelevancyStore.lowerReceiver(this),
            FfiConverterString.lower(bandit),
            FfiConverterSequenceString.lower(arms),
        )
        return handleRustResult(
            result,
            FfiConverterString.lift.bind(FfiConverterString),
            FfiConverterTypeRelevancyApiError.lift.bind(FfiConverterTypeRelevancyApiError),
        )
    }

    /**
     * Updates the bandit model's arm data based on user interaction (selection or non-selection).
     * 
     * This method takes in a `bandit` identifier, an `arm` identifier, and a `selected` flag.
     * If `selected` is true, it updates the model to reflect a successful selection of the arm,
     * reinforcing its positive reward probability. If `selected` is false, it updates the
     * beta (failure) distribution of the arm, reflecting a lack of selection and reinforcing
     * its likelihood of a negative outcome.
     * @param {string} bandit
     * @param {string} arm
     * @param {boolean} selected
     */
    async banditUpdate(
        bandit, 
        arm, 
        selected) {
       
        FfiConverterString.checkType(bandit);
        FfiConverterString.checkType(arm);
        FfiConverterBoolean.checkType(selected);
        const result = await UniFFIScaffolding.callAsyncWrapper(
            146, // uniffi_relevancy_fn_method_relevancystore_bandit_update
            FfiConverterTypeRelevancyStore.lowerReceiver(this),
            FfiConverterString.lower(bandit),
            FfiConverterString.lower(arm),
            FfiConverterBoolean.lower(selected),
        )
        return handleRustResult(
            result,
            (result) => undefined,
            FfiConverterTypeRelevancyApiError.lift.bind(FfiConverterTypeRelevancyApiError),
        )
    }

    /**
     * Close any open resources (for example databases)
     * 
     * Calling `close` will interrupt any in-progress queries on other threads.
     */
    close() {
       
        const result = UniFFIScaffolding.callSync(
            147, // uniffi_relevancy_fn_method_relevancystore_close
            FfiConverterTypeRelevancyStore.lowerReceiver(this),
        )
        return handleRustResult(
            result,
            (result) => undefined,
            null,
        )
    }

    /**
     * Download the interest data from remote settings if needed
     */
    async ensureInterestDataPopulated() {
       
        const result = await UniFFIScaffolding.callAsyncWrapper(
            148, // uniffi_relevancy_fn_method_relevancystore_ensure_interest_data_populated
            FfiConverterTypeRelevancyStore.lowerReceiver(this),
        )
        return handleRustResult(
            result,
            (result) => undefined,
            FfiConverterTypeRelevancyApiError.lift.bind(FfiConverterTypeRelevancyApiError),
        )
    }

    /**
     * Retrieves the data for a specific bandit and arm.
     * @param {string} bandit
     * @param {string} arm
     * @returns {Promise<BanditData>}}
     */
    async getBanditData(
        bandit, 
        arm) {
       
        FfiConverterString.checkType(bandit);
        FfiConverterString.checkType(arm);
        const result = await UniFFIScaffolding.callAsyncWrapper(
            149, // uniffi_relevancy_fn_method_relevancystore_get_bandit_data
            FfiConverterTypeRelevancyStore.lowerReceiver(this),
            FfiConverterString.lower(bandit),
            FfiConverterString.lower(arm),
        )
        return handleRustResult(
            result,
            FfiConverterTypeBanditData.lift.bind(FfiConverterTypeBanditData),
            FfiConverterTypeRelevancyApiError.lift.bind(FfiConverterTypeRelevancyApiError),
        )
    }

    /**
     * Ingest top URLs to build the user's interest vector.
     * 
     * Consumer should pass a list of the user's top URLs by frecency to this method.  It will
     * then:
     * 
     * - Download the URL interest data from remote settings.  Eventually this should be cached /
     * stored in the database, but for now it would be fine to download fresh data each time.
     * - Match the user's top URls against the interest data to build up their interest vector.
     * - Store the user's interest vector in the database.
     * 
     * This method may execute for a long time and should only be called from a worker thread.
     * @param {Array.<string>} topUrlsByFrecency
     * @returns {Promise<InterestVector>}}
     */
    async ingest(
        topUrlsByFrecency) {
       
        FfiConverterSequenceString.checkType(topUrlsByFrecency);
        const result = await UniFFIScaffolding.callAsyncWrapper(
            150, // uniffi_relevancy_fn_method_relevancystore_ingest
            FfiConverterTypeRelevancyStore.lowerReceiver(this),
            FfiConverterSequenceString.lower(topUrlsByFrecency),
        )
        return handleRustResult(
            result,
            FfiConverterTypeInterestVector.lift.bind(FfiConverterTypeInterestVector),
            FfiConverterTypeRelevancyApiError.lift.bind(FfiConverterTypeRelevancyApiError),
        )
    }

    /**
     * Interrupt any current database queries
     */
    interrupt() {
       
        const result = UniFFIScaffolding.callSync(
            151, // uniffi_relevancy_fn_method_relevancystore_interrupt
            FfiConverterTypeRelevancyStore.lowerReceiver(this),
        )
        return handleRustResult(
            result,
            (result) => undefined,
            null,
        )
    }

    /**
     * Get the user's interest vector directly.
     * 
     * This runs after [Self::ingest].  It returns the interest vector directly so that the
     * consumer can show it in an `about:` page.
     * @returns {Promise<InterestVector>}}
     */
    async userInterestVector() {
       
        const result = await UniFFIScaffolding.callAsyncWrapper(
            152, // uniffi_relevancy_fn_method_relevancystore_user_interest_vector
            FfiConverterTypeRelevancyStore.lowerReceiver(this),
        )
        return handleRustResult(
            result,
            FfiConverterTypeInterestVector.lift.bind(FfiConverterTypeInterestVector),
            FfiConverterTypeRelevancyApiError.lift.bind(FfiConverterTypeRelevancyApiError),
        )
    }

}

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

    static lower(value) {
        const ptr = value[uniffiObjectPtr];
        if (!(ptr instanceof UniFFIPointer)) {
            throw new UniFFITypeError("Object is not a 'RelevancyStore' 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(17));
    }

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

    static computeSize(value) {
        return 8;
    }
}

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

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

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

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




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

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