// 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,
};
/**
 * Check that key is still valid using the output of `create_canary`.
 * @param {string} canary
 * @param {string} text
 * @param {string} encryptionKey
 * @returns {boolean}
 */
export function checkCanary(
    canary, 
    text, 
    encryptionKey) {
   
FfiConverterString.checkType(canary);
FfiConverterString.checkType(text);
FfiConverterString.checkType(encryptionKey);
const result = UniFFIScaffolding.callSync(
    14, // uniffi_logins_fn_func_check_canary
    FfiConverterString.lower(canary),
    FfiConverterString.lower(text),
    FfiConverterString.lower(encryptionKey),
)
return handleRustResult(
    result,
    FfiConverterBoolean.lift.bind(FfiConverterBoolean),
    FfiConverterTypeLoginsApiError.lift.bind(FfiConverterTypeLoginsApiError),
)
}

/**
 * Create a "canary" string, which can be used to test if the encryption
 * @param {string} text
 * @param {string} encryptionKey
 * @returns {string}
 */
export function createCanary(
    text, 
    encryptionKey) {
   
FfiConverterString.checkType(text);
FfiConverterString.checkType(encryptionKey);
const result = UniFFIScaffolding.callSync(
    15, // uniffi_logins_fn_func_create_canary
    FfiConverterString.lower(text),
    FfiConverterString.lower(encryptionKey),
)
return handleRustResult(
    result,
    FfiConverterString.lift.bind(FfiConverterString),
    FfiConverterTypeLoginsApiError.lift.bind(FfiConverterTypeLoginsApiError),
)
}

/**
 * We expose the crypto primitives on the namespace
 * Create a new, random, encryption key.
 * @returns {string}
 */
export function createKey() {
   
const result = UniFFIScaffolding.callSync(
    16, // uniffi_logins_fn_func_create_key
)
return handleRustResult(
    result,
    FfiConverterString.lift.bind(FfiConverterString),
    FfiConverterTypeLoginsApiError.lift.bind(FfiConverterTypeLoginsApiError),
)
}

/**
 * createLoginStoreWithNssKeymanager
 * @param {string} path
 * @param {PrimaryPasswordAuthenticator} primaryPasswordAuthenticator
 * @returns {LoginStore}
 */
export function createLoginStoreWithNssKeymanager(
    path, 
    primaryPasswordAuthenticator) {
   
FfiConverterString.checkType(path);
FfiConverterTypePrimaryPasswordAuthenticator.checkType(primaryPasswordAuthenticator);
const result = UniFFIScaffolding.callSync(
    17, // uniffi_logins_fn_func_create_login_store_with_nss_keymanager
    FfiConverterString.lower(path),
    FfiConverterTypePrimaryPasswordAuthenticator.lower(primaryPasswordAuthenticator),
)
return handleRustResult(
    result,
    FfiConverterTypeLoginStore.lift.bind(FfiConverterTypeLoginStore),
    FfiConverterTypeLoginsApiError.lift.bind(FfiConverterTypeLoginsApiError),
)
}

/**
 * Create a LoginStore with StaticKeyManager by passing in a db path and a
 * static key
 * @param {string} path
 * @param {string} key
 * @returns {LoginStore}
 */
export function createLoginStoreWithStaticKeyManager(
    path, 
    key) {
   
FfiConverterString.checkType(path);
FfiConverterString.checkType(key);
const result = UniFFIScaffolding.callSync(
    18, // uniffi_logins_fn_func_create_login_store_with_static_key_manager
    FfiConverterString.lower(path),
    FfiConverterString.lower(key),
)
return handleRustResult(
    result,
    FfiConverterTypeLoginStore.lift.bind(FfiConverterTypeLoginStore),
    null,
)
}

/**
 * Similar to create_static_key_manager above, create a
 * ManagedEncryptorDecryptor by passing in a KeyManager
 * @param {KeyManager} keyManager
 * @returns {EncryptorDecryptor}
 */
export function createManagedEncdec(
    keyManager) {
   
FfiConverterTypeKeyManager.checkType(keyManager);
const result = UniFFIScaffolding.callSync(
    19, // uniffi_logins_fn_func_create_managed_encdec
    FfiConverterTypeKeyManager.lower(keyManager),
)
return handleRustResult(
    result,
    FfiConverterTypeEncryptorDecryptor.lift.bind(FfiConverterTypeEncryptorDecryptor),
    null,
)
}

/**
 * Utility function to create a StaticKeyManager to be used for the time
 * being until support lands for [trait implementation of an UniFFI
 * interface](https://mozilla.github.io/uniffi-rs/next/proc_macro/index.html#structs-implementing-traits)
 * in UniFFI.
 * @param {string} key
 * @returns {KeyManager}
 */
export function createStaticKeyManager(
    key) {
   
FfiConverterString.checkType(key);
const result = UniFFIScaffolding.callSync(
    20, // uniffi_logins_fn_func_create_static_key_manager
    FfiConverterString.lower(key),
)
return handleRustResult(
    result,
    FfiConverterTypeKeyManager.lift.bind(FfiConverterTypeKeyManager),
    null,
)
}






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

    static read(dataStream) {
        const code = dataStream.readUint8(0);
        switch (code) {
            case 0:
                return null
            case 1:
                return FfiConverterInt64.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);
        FfiConverterInt64.write(dataStream, value)
    }

    static computeSize(value) {
        if (value === null || value === undefined) {
            return 1;
        }
        return 1 + FfiConverterInt64.computeSize(value)
    }
}
// Export the FFIConverter object to make external types work.
export class FfiConverterOptionalString extends FfiConverterArrayBuffer {
    static checkType(value) {
        if (value !== undefined && value !== null) {
            FfiConverterString.checkType(value)
        }
    }

    static read(dataStream) {
        const code = dataStream.readUint8(0);
        switch (code) {
            case 0:
                return null
            case 1:
                return FfiConverterString.read(dataStream)
            default:
                throw 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 login stored in the database
 */
export class Login {
    constructor(
        {
            id, 
            timesUsed, 
            timeCreated, 
            timeLastUsed, 
            timePasswordChanged, 
            timeLastBreachAlertDismissed, 
            origin, 
            httpRealm, 
            formActionOrigin, 
            usernameField, 
            passwordField, 
            password, 
            username
        } = {
            id: undefined, 
            timesUsed: undefined, 
            timeCreated: undefined, 
            timeLastUsed: undefined, 
            timePasswordChanged: undefined, 
            timeLastBreachAlertDismissed: undefined, 
            origin: undefined, 
            httpRealm: undefined, 
            formActionOrigin: undefined, 
            usernameField: undefined, 
            passwordField: undefined, 
            password: undefined, 
            username: undefined
        }
    ) {
        try {
            FfiConverterString.checkType(id)
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart("id");
            }
            throw e;
        }
        try {
            FfiConverterInt64.checkType(timesUsed)
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart("timesUsed");
            }
            throw e;
        }
        try {
            FfiConverterInt64.checkType(timeCreated)
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart("timeCreated");
            }
            throw e;
        }
        try {
            FfiConverterInt64.checkType(timeLastUsed)
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart("timeLastUsed");
            }
            throw e;
        }
        try {
            FfiConverterInt64.checkType(timePasswordChanged)
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart("timePasswordChanged");
            }
            throw e;
        }
        try {
            FfiConverterOptionalInt64.checkType(timeLastBreachAlertDismissed)
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart("timeLastBreachAlertDismissed");
            }
            throw e;
        }
        try {
            FfiConverterString.checkType(origin)
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart("origin");
            }
            throw e;
        }
        try {
            FfiConverterOptionalString.checkType(httpRealm)
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart("httpRealm");
            }
            throw e;
        }
        try {
            FfiConverterOptionalString.checkType(formActionOrigin)
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart("formActionOrigin");
            }
            throw e;
        }
        try {
            FfiConverterString.checkType(usernameField)
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart("usernameField");
            }
            throw e;
        }
        try {
            FfiConverterString.checkType(passwordField)
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart("passwordField");
            }
            throw e;
        }
        try {
            FfiConverterString.checkType(password)
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart("password");
            }
            throw e;
        }
        try {
            FfiConverterString.checkType(username)
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart("username");
            }
            throw e;
        }
        /**
         * @type {string}
         */
        this.id = id;
        /**
         * @type {number}
         */
        this.timesUsed = timesUsed;
        /**
         * @type {number}
         */
        this.timeCreated = timeCreated;
        /**
         * @type {number}
         */
        this.timeLastUsed = timeLastUsed;
        /**
         * @type {number}
         */
        this.timePasswordChanged = timePasswordChanged;
        /**
         * @type {?number}
         */
        this.timeLastBreachAlertDismissed = timeLastBreachAlertDismissed;
        /**
         * @type {string}
         */
        this.origin = origin;
        /**
         * @type {?string}
         */
        this.httpRealm = httpRealm;
        /**
         * @type {?string}
         */
        this.formActionOrigin = formActionOrigin;
        /**
         * @type {string}
         */
        this.usernameField = usernameField;
        /**
         * @type {string}
         */
        this.passwordField = passwordField;
        /**
         * @type {string}
         */
        this.password = password;
        /**
         * @type {string}
         */
        this.username = username;
    }

    equals(other) {
        return (
            this.id == other.id
            && this.timesUsed == other.timesUsed
            && this.timeCreated == other.timeCreated
            && this.timeLastUsed == other.timeLastUsed
            && this.timePasswordChanged == other.timePasswordChanged
            && this.timeLastBreachAlertDismissed == other.timeLastBreachAlertDismissed
            && this.origin == other.origin
            && this.httpRealm == other.httpRealm
            && this.formActionOrigin == other.formActionOrigin
            && this.usernameField == other.usernameField
            && this.passwordField == other.passwordField
            && this.password == other.password
            && this.username == other.username
        )
    }
}

// Export the FFIConverter object to make external types work.
export class FfiConverterTypeLogin extends FfiConverterArrayBuffer {
    static read(dataStream) {
        return new Login({
            id: FfiConverterString.read(dataStream),
            timesUsed: FfiConverterInt64.read(dataStream),
            timeCreated: FfiConverterInt64.read(dataStream),
            timeLastUsed: FfiConverterInt64.read(dataStream),
            timePasswordChanged: FfiConverterInt64.read(dataStream),
            timeLastBreachAlertDismissed: FfiConverterOptionalInt64.read(dataStream),
            origin: FfiConverterString.read(dataStream),
            httpRealm: FfiConverterOptionalString.read(dataStream),
            formActionOrigin: FfiConverterOptionalString.read(dataStream),
            usernameField: FfiConverterString.read(dataStream),
            passwordField: FfiConverterString.read(dataStream),
            password: FfiConverterString.read(dataStream),
            username: FfiConverterString.read(dataStream),
        });
    }
    static write(dataStream, value) {
        FfiConverterString.write(dataStream, value.id);
        FfiConverterInt64.write(dataStream, value.timesUsed);
        FfiConverterInt64.write(dataStream, value.timeCreated);
        FfiConverterInt64.write(dataStream, value.timeLastUsed);
        FfiConverterInt64.write(dataStream, value.timePasswordChanged);
        FfiConverterOptionalInt64.write(dataStream, value.timeLastBreachAlertDismissed);
        FfiConverterString.write(dataStream, value.origin);
        FfiConverterOptionalString.write(dataStream, value.httpRealm);
        FfiConverterOptionalString.write(dataStream, value.formActionOrigin);
        FfiConverterString.write(dataStream, value.usernameField);
        FfiConverterString.write(dataStream, value.passwordField);
        FfiConverterString.write(dataStream, value.password);
        FfiConverterString.write(dataStream, value.username);
    }

    static computeSize(value) {
        let totalSize = 0;
        totalSize += FfiConverterString.computeSize(value.id);
        totalSize += FfiConverterInt64.computeSize(value.timesUsed);
        totalSize += FfiConverterInt64.computeSize(value.timeCreated);
        totalSize += FfiConverterInt64.computeSize(value.timeLastUsed);
        totalSize += FfiConverterInt64.computeSize(value.timePasswordChanged);
        totalSize += FfiConverterOptionalInt64.computeSize(value.timeLastBreachAlertDismissed);
        totalSize += FfiConverterString.computeSize(value.origin);
        totalSize += FfiConverterOptionalString.computeSize(value.httpRealm);
        totalSize += FfiConverterOptionalString.computeSize(value.formActionOrigin);
        totalSize += FfiConverterString.computeSize(value.usernameField);
        totalSize += FfiConverterString.computeSize(value.passwordField);
        totalSize += FfiConverterString.computeSize(value.password);
        totalSize += FfiConverterString.computeSize(value.username);
        return totalSize
    }

    static checkType(value) {
        super.checkType(value);
        if (!(value instanceof Login)) {
            throw new UniFFITypeError(`Expected 'Login', found '${typeof value}'`);
        }
        try {
            FfiConverterString.checkType(value.id);
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart(".id");
            }
            throw e;
        }
        try {
            FfiConverterInt64.checkType(value.timesUsed);
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart(".timesUsed");
            }
            throw e;
        }
        try {
            FfiConverterInt64.checkType(value.timeCreated);
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart(".timeCreated");
            }
            throw e;
        }
        try {
            FfiConverterInt64.checkType(value.timeLastUsed);
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart(".timeLastUsed");
            }
            throw e;
        }
        try {
            FfiConverterInt64.checkType(value.timePasswordChanged);
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart(".timePasswordChanged");
            }
            throw e;
        }
        try {
            FfiConverterOptionalInt64.checkType(value.timeLastBreachAlertDismissed);
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart(".timeLastBreachAlertDismissed");
            }
            throw e;
        }
        try {
            FfiConverterString.checkType(value.origin);
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart(".origin");
            }
            throw e;
        }
        try {
            FfiConverterOptionalString.checkType(value.httpRealm);
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart(".httpRealm");
            }
            throw e;
        }
        try {
            FfiConverterOptionalString.checkType(value.formActionOrigin);
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart(".formActionOrigin");
            }
            throw e;
        }
        try {
            FfiConverterString.checkType(value.usernameField);
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart(".usernameField");
            }
            throw e;
        }
        try {
            FfiConverterString.checkType(value.passwordField);
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart(".passwordField");
            }
            throw e;
        }
        try {
            FfiConverterString.checkType(value.password);
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart(".password");
            }
            throw e;
        }
        try {
            FfiConverterString.checkType(value.username);
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart(".username");
            }
            throw e;
        }
    }
}
/**
 * A login entry from the user, not linked to any database record.
 * The add/update APIs input these.
 */
export class LoginEntry {
    constructor(
        {
            origin, 
            httpRealm, 
            formActionOrigin, 
            usernameField, 
            passwordField, 
            password, 
            username
        } = {
            origin: undefined, 
            httpRealm: undefined, 
            formActionOrigin: undefined, 
            usernameField: undefined, 
            passwordField: undefined, 
            password: undefined, 
            username: undefined
        }
    ) {
        try {
            FfiConverterString.checkType(origin)
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart("origin");
            }
            throw e;
        }
        try {
            FfiConverterOptionalString.checkType(httpRealm)
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart("httpRealm");
            }
            throw e;
        }
        try {
            FfiConverterOptionalString.checkType(formActionOrigin)
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart("formActionOrigin");
            }
            throw e;
        }
        try {
            FfiConverterString.checkType(usernameField)
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart("usernameField");
            }
            throw e;
        }
        try {
            FfiConverterString.checkType(passwordField)
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart("passwordField");
            }
            throw e;
        }
        try {
            FfiConverterString.checkType(password)
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart("password");
            }
            throw e;
        }
        try {
            FfiConverterString.checkType(username)
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart("username");
            }
            throw e;
        }
        /**
         * @type {string}
         */
        this.origin = origin;
        /**
         * @type {?string}
         */
        this.httpRealm = httpRealm;
        /**
         * @type {?string}
         */
        this.formActionOrigin = formActionOrigin;
        /**
         * @type {string}
         */
        this.usernameField = usernameField;
        /**
         * @type {string}
         */
        this.passwordField = passwordField;
        /**
         * @type {string}
         */
        this.password = password;
        /**
         * @type {string}
         */
        this.username = username;
    }

    equals(other) {
        return (
            this.origin == other.origin
            && this.httpRealm == other.httpRealm
            && this.formActionOrigin == other.formActionOrigin
            && this.usernameField == other.usernameField
            && this.passwordField == other.passwordField
            && this.password == other.password
            && this.username == other.username
        )
    }
}

// Export the FFIConverter object to make external types work.
export class FfiConverterTypeLoginEntry extends FfiConverterArrayBuffer {
    static read(dataStream) {
        return new LoginEntry({
            origin: FfiConverterString.read(dataStream),
            httpRealm: FfiConverterOptionalString.read(dataStream),
            formActionOrigin: FfiConverterOptionalString.read(dataStream),
            usernameField: FfiConverterString.read(dataStream),
            passwordField: FfiConverterString.read(dataStream),
            password: FfiConverterString.read(dataStream),
            username: FfiConverterString.read(dataStream),
        });
    }
    static write(dataStream, value) {
        FfiConverterString.write(dataStream, value.origin);
        FfiConverterOptionalString.write(dataStream, value.httpRealm);
        FfiConverterOptionalString.write(dataStream, value.formActionOrigin);
        FfiConverterString.write(dataStream, value.usernameField);
        FfiConverterString.write(dataStream, value.passwordField);
        FfiConverterString.write(dataStream, value.password);
        FfiConverterString.write(dataStream, value.username);
    }

    static computeSize(value) {
        let totalSize = 0;
        totalSize += FfiConverterString.computeSize(value.origin);
        totalSize += FfiConverterOptionalString.computeSize(value.httpRealm);
        totalSize += FfiConverterOptionalString.computeSize(value.formActionOrigin);
        totalSize += FfiConverterString.computeSize(value.usernameField);
        totalSize += FfiConverterString.computeSize(value.passwordField);
        totalSize += FfiConverterString.computeSize(value.password);
        totalSize += FfiConverterString.computeSize(value.username);
        return totalSize
    }

    static checkType(value) {
        super.checkType(value);
        if (!(value instanceof LoginEntry)) {
            throw new UniFFITypeError(`Expected 'LoginEntry', found '${typeof value}'`);
        }
        try {
            FfiConverterString.checkType(value.origin);
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart(".origin");
            }
            throw e;
        }
        try {
            FfiConverterOptionalString.checkType(value.httpRealm);
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart(".httpRealm");
            }
            throw e;
        }
        try {
            FfiConverterOptionalString.checkType(value.formActionOrigin);
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart(".formActionOrigin");
            }
            throw e;
        }
        try {
            FfiConverterString.checkType(value.usernameField);
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart(".usernameField");
            }
            throw e;
        }
        try {
            FfiConverterString.checkType(value.passwordField);
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart(".passwordField");
            }
            throw e;
        }
        try {
            FfiConverterString.checkType(value.password);
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart(".password");
            }
            throw e;
        }
        try {
            FfiConverterString.checkType(value.username);
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart(".username");
            }
            throw e;
        }
    }
}
/**
 * Metadata fields managed internally by the library.
 * These are automatically set on `add()` and updated on operations like `touch()` and `update()`.
 * Not included in LoginEntry; use `add_with_meta()` when importing records with existing metadata.
 */
export class LoginMeta {
    constructor(
        {
            id, 
            timesUsed, 
            timeCreated, 
            timeLastUsed, 
            timePasswordChanged, 
            timeLastBreachAlertDismissed
        } = {
            id: undefined, 
            timesUsed: undefined, 
            timeCreated: undefined, 
            timeLastUsed: undefined, 
            timePasswordChanged: undefined, 
            timeLastBreachAlertDismissed: undefined
        }
    ) {
        try {
            FfiConverterString.checkType(id)
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart("id");
            }
            throw e;
        }
        try {
            FfiConverterInt64.checkType(timesUsed)
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart("timesUsed");
            }
            throw e;
        }
        try {
            FfiConverterInt64.checkType(timeCreated)
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart("timeCreated");
            }
            throw e;
        }
        try {
            FfiConverterInt64.checkType(timeLastUsed)
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart("timeLastUsed");
            }
            throw e;
        }
        try {
            FfiConverterInt64.checkType(timePasswordChanged)
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart("timePasswordChanged");
            }
            throw e;
        }
        try {
            FfiConverterOptionalInt64.checkType(timeLastBreachAlertDismissed)
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart("timeLastBreachAlertDismissed");
            }
            throw e;
        }
        /**
         * @type {string}
         */
        this.id = id;
        /**
         * @type {number}
         */
        this.timesUsed = timesUsed;
        /**
         * @type {number}
         */
        this.timeCreated = timeCreated;
        /**
         * @type {number}
         */
        this.timeLastUsed = timeLastUsed;
        /**
         * @type {number}
         */
        this.timePasswordChanged = timePasswordChanged;
        /**
         * @type {?number}
         */
        this.timeLastBreachAlertDismissed = timeLastBreachAlertDismissed;
    }

    equals(other) {
        return (
            this.id == other.id
            && this.timesUsed == other.timesUsed
            && this.timeCreated == other.timeCreated
            && this.timeLastUsed == other.timeLastUsed
            && this.timePasswordChanged == other.timePasswordChanged
            && this.timeLastBreachAlertDismissed == other.timeLastBreachAlertDismissed
        )
    }
}

// Export the FFIConverter object to make external types work.
export class FfiConverterTypeLoginMeta extends FfiConverterArrayBuffer {
    static read(dataStream) {
        return new LoginMeta({
            id: FfiConverterString.read(dataStream),
            timesUsed: FfiConverterInt64.read(dataStream),
            timeCreated: FfiConverterInt64.read(dataStream),
            timeLastUsed: FfiConverterInt64.read(dataStream),
            timePasswordChanged: FfiConverterInt64.read(dataStream),
            timeLastBreachAlertDismissed: FfiConverterOptionalInt64.read(dataStream),
        });
    }
    static write(dataStream, value) {
        FfiConverterString.write(dataStream, value.id);
        FfiConverterInt64.write(dataStream, value.timesUsed);
        FfiConverterInt64.write(dataStream, value.timeCreated);
        FfiConverterInt64.write(dataStream, value.timeLastUsed);
        FfiConverterInt64.write(dataStream, value.timePasswordChanged);
        FfiConverterOptionalInt64.write(dataStream, value.timeLastBreachAlertDismissed);
    }

    static computeSize(value) {
        let totalSize = 0;
        totalSize += FfiConverterString.computeSize(value.id);
        totalSize += FfiConverterInt64.computeSize(value.timesUsed);
        totalSize += FfiConverterInt64.computeSize(value.timeCreated);
        totalSize += FfiConverterInt64.computeSize(value.timeLastUsed);
        totalSize += FfiConverterInt64.computeSize(value.timePasswordChanged);
        totalSize += FfiConverterOptionalInt64.computeSize(value.timeLastBreachAlertDismissed);
        return totalSize
    }

    static checkType(value) {
        super.checkType(value);
        if (!(value instanceof LoginMeta)) {
            throw new UniFFITypeError(`Expected 'LoginMeta', found '${typeof value}'`);
        }
        try {
            FfiConverterString.checkType(value.id);
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart(".id");
            }
            throw e;
        }
        try {
            FfiConverterInt64.checkType(value.timesUsed);
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart(".timesUsed");
            }
            throw e;
        }
        try {
            FfiConverterInt64.checkType(value.timeCreated);
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart(".timeCreated");
            }
            throw e;
        }
        try {
            FfiConverterInt64.checkType(value.timeLastUsed);
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart(".timeLastUsed");
            }
            throw e;
        }
        try {
            FfiConverterInt64.checkType(value.timePasswordChanged);
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart(".timePasswordChanged");
            }
            throw e;
        }
        try {
            FfiConverterOptionalInt64.checkType(value.timeLastBreachAlertDismissed);
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart(".timeLastBreachAlertDismissed");
            }
            throw e;
        }
    }
}
/**
 * A login together with record fields, handed over to the store API; ie a login persisted
 * elsewhere, useful for migrations
 */
export class LoginEntryWithMeta {
    constructor(
        {
            entry, 
            meta
        } = {
            entry: undefined, 
            meta: undefined
        }
    ) {
        try {
            FfiConverterTypeLoginEntry.checkType(entry)
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart("entry");
            }
            throw e;
        }
        try {
            FfiConverterTypeLoginMeta.checkType(meta)
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart("meta");
            }
            throw e;
        }
        /**
         * @type {LoginEntry}
         */
        this.entry = entry;
        /**
         * @type {LoginMeta}
         */
        this.meta = meta;
    }

    equals(other) {
        return (
            this.entry.equals(other.entry)
            && this.meta.equals(other.meta)
        )
    }
}

// Export the FFIConverter object to make external types work.
export class FfiConverterTypeLoginEntryWithMeta extends FfiConverterArrayBuffer {
    static read(dataStream) {
        return new LoginEntryWithMeta({
            entry: FfiConverterTypeLoginEntry.read(dataStream),
            meta: FfiConverterTypeLoginMeta.read(dataStream),
        });
    }
    static write(dataStream, value) {
        FfiConverterTypeLoginEntry.write(dataStream, value.entry);
        FfiConverterTypeLoginMeta.write(dataStream, value.meta);
    }

    static computeSize(value) {
        let totalSize = 0;
        totalSize += FfiConverterTypeLoginEntry.computeSize(value.entry);
        totalSize += FfiConverterTypeLoginMeta.computeSize(value.meta);
        return totalSize
    }

    static checkType(value) {
        super.checkType(value);
        if (!(value instanceof LoginEntryWithMeta)) {
            throw new UniFFITypeError(`Expected 'LoginEntryWithMeta', found '${typeof value}'`);
        }
        try {
            FfiConverterTypeLoginEntry.checkType(value.entry);
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart(".entry");
            }
            throw e;
        }
        try {
            FfiConverterTypeLoginMeta.checkType(value.meta);
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart(".meta");
            }
            throw e;
        }
    }
}


/**
 * Metrics tracking deletion of logins that cannot be decrypted, see `delete_undecryptable_records_for_remote_replacement`
 * for more details
 */
export class LoginsDeletionMetrics {
    constructor(
        {
            localDeleted, 
            mirrorDeleted
        } = {
            localDeleted: undefined, 
            mirrorDeleted: undefined
        }
    ) {
        try {
            FfiConverterUInt64.checkType(localDeleted)
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart("localDeleted");
            }
            throw e;
        }
        try {
            FfiConverterUInt64.checkType(mirrorDeleted)
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart("mirrorDeleted");
            }
            throw e;
        }
        /**
         * @type {number}
         */
        this.localDeleted = localDeleted;
        /**
         * @type {number}
         */
        this.mirrorDeleted = mirrorDeleted;
    }

    equals(other) {
        return (
            this.localDeleted == other.localDeleted
            && this.mirrorDeleted == other.mirrorDeleted
        )
    }
}

// Export the FFIConverter object to make external types work.
export class FfiConverterTypeLoginsDeletionMetrics extends FfiConverterArrayBuffer {
    static read(dataStream) {
        return new LoginsDeletionMetrics({
            localDeleted: FfiConverterUInt64.read(dataStream),
            mirrorDeleted: FfiConverterUInt64.read(dataStream),
        });
    }
    static write(dataStream, value) {
        FfiConverterUInt64.write(dataStream, value.localDeleted);
        FfiConverterUInt64.write(dataStream, value.mirrorDeleted);
    }

    static computeSize(value) {
        let totalSize = 0;
        totalSize += FfiConverterUInt64.computeSize(value.localDeleted);
        totalSize += FfiConverterUInt64.computeSize(value.mirrorDeleted);
        return totalSize
    }

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

/**
 * A bulk insert result entry, returned by `add_many` and `add_many_with_meta`
 */
export class BulkResultEntry {}
/**
 * Success
 */
BulkResultEntry.Success = class extends BulkResultEntry{
   constructor({login = undefined } = {}) {
                super();
            try {
                FfiConverterTypeLogin.checkType(login);
            } catch (e) {
                if (e instanceof UniFFITypeError) {
                    e.addItemDescriptionPart("login");
                }
                throw e;
            }
            this.login = login;
    }
}
/**
 * Error
 */
BulkResultEntry.Error = class extends BulkResultEntry{
   constructor({message = undefined } = {}) {
                super();
            try {
                FfiConverterString.checkType(message);
            } catch (e) {
                if (e instanceof UniFFITypeError) {
                    e.addItemDescriptionPart("message");
                }
                throw e;
            }
            this.message = message;
    }
}

// Export the FFIConverter object to make external types work.
export class FfiConverterTypeBulkResultEntry 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 BulkResultEntry.Success({
                    login: FfiConverterTypeLogin.read(dataStream)
                });
            case 2:
                return new BulkResultEntry.Error({
                    message: FfiConverterString.read(dataStream)
                });
            default:
                throw new UniFFITypeError("Unknown BulkResultEntry variant");
        }
    }

    static write(dataStream, value) {
        // Use sequential indices (1-based) for the wire format to match the Rust scaffolding
        if (value instanceof BulkResultEntry.Success) {
            dataStream.writeInt32(1);
            FfiConverterTypeLogin.write(dataStream, value.login);
            return;
        }
        if (value instanceof BulkResultEntry.Error) {
            dataStream.writeInt32(2);
            FfiConverterString.write(dataStream, value.message);
            return;
        }
        throw new UniFFITypeError("Unknown BulkResultEntry variant");
    }

    static computeSize(value) {
        // Size of the Int indicating the variant
        let totalSize = 4;
        if (value instanceof BulkResultEntry.Success) {
            totalSize += FfiConverterTypeLogin.computeSize(value.login);
            return totalSize;
        }
        if (value instanceof BulkResultEntry.Error) {
            totalSize += FfiConverterString.computeSize(value.message);
            return totalSize;
        }
        throw new UniFFITypeError("Unknown BulkResultEntry variant");
    }

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

/**
 * LoginOrErrorMessage
 */
export const LoginOrErrorMessage = Object.freeze({
    /**
     * LOGIN
     */
    LOGIN: 0,
    /**
     * STRING
     */
    STRING: 1,
});

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

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

    static write(dataStream, value) {
        // Use sequential indices (1-based) for the wire format to match the Rust scaffolding
        if (value === LoginOrErrorMessage.LOGIN) {
            dataStream.writeInt32(1);
            return;
        }
        if (value === LoginOrErrorMessage.STRING) {
            dataStream.writeInt32(2);
            return;
        }
        throw new UniFFITypeError("Unknown LoginOrErrorMessage 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 LoginOrErrorMessage`);
      }
    }
}

/**
 * These are the errors returned by our public API.
 */
export class LoginsApiError extends Error {}


/**
 * NSS not initialized.
 */
export class NssUninitialized extends LoginsApiError {

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

/**
 * NSS error during authentication
 */
export class NssAuthenticationError extends LoginsApiError {

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

/**
 * error during authentication (in PrimaryPasswordAuthenticator)
 */
export class AuthenticationError extends LoginsApiError {

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

/**
 * authentication has been cancelled.
 */
export class AuthenticationCanceled extends LoginsApiError {

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

/**
 * The login data supplied is invalid. The reason will indicate what's wrong with it.
 */
export class InvalidRecord extends LoginsApiError {

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

/**
 * Asking to do something with a guid which doesn't exist.
 */
export class NoSuchRecord extends LoginsApiError {

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

/**
 * Encryption key is missing.
 */
export class MissingKey extends LoginsApiError {

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

/**
 * Encryption key is not valid.
 */
export class InvalidKey extends LoginsApiError {

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

/**
 * encryption failed
 */
export class EncryptionFailed extends LoginsApiError {

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

/**
 * decryption failed
 */
export class DecryptionFailed extends LoginsApiError {

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

/**
 * An operation was interrupted at the request of the consuming app.
 */
export class Interrupted extends LoginsApiError {

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

/**
 * something internal went wrong which doesn't have a public error value
 * because the consuming app can not reasonably take any action to resolve it.
 * The underlying error will have been logged and reported.
 * (ideally would just be `Unexpected`, but that would be a breaking change)
 */
export class UnexpectedLoginsApiError extends LoginsApiError {

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

// Export the FFIConverter object to make external types work.
export class FfiConverterTypeLoginsApiError extends FfiConverterArrayBuffer {
    static read(dataStream) {
        switch (dataStream.readInt32()) {
            case 1:
                return new NssUninitialized(
                    );
            case 2:
                return new NssAuthenticationError(
                    FfiConverterString.read(dataStream)
                    );
            case 3:
                return new AuthenticationError(
                    FfiConverterString.read(dataStream)
                    );
            case 4:
                return new AuthenticationCanceled(
                    );
            case 5:
                return new InvalidRecord(
                    FfiConverterString.read(dataStream)
                    );
            case 6:
                return new NoSuchRecord(
                    FfiConverterString.read(dataStream)
                    );
            case 7:
                return new MissingKey(
                    );
            case 8:
                return new InvalidKey(
                    );
            case 9:
                return new EncryptionFailed(
                    FfiConverterString.read(dataStream)
                    );
            case 10:
                return new DecryptionFailed(
                    FfiConverterString.read(dataStream)
                    );
            case 11:
                return new Interrupted(
                    FfiConverterString.read(dataStream)
                    );
            case 12:
                return new UnexpectedLoginsApiError(
                    FfiConverterString.read(dataStream)
                    );
            default:
                throw new UniFFITypeError("Unknown LoginsApiError variant");
        }
    }
    static computeSize(value) {
        // Size of the Int indicating the variant
        let totalSize = 4;
        if (value instanceof NssUninitialized) {
            return totalSize;
        }
        if (value instanceof NssAuthenticationError) {
            totalSize += FfiConverterString.computeSize(value.reason);
            return totalSize;
        }
        if (value instanceof AuthenticationError) {
            totalSize += FfiConverterString.computeSize(value.reason);
            return totalSize;
        }
        if (value instanceof AuthenticationCanceled) {
            return totalSize;
        }
        if (value instanceof InvalidRecord) {
            totalSize += FfiConverterString.computeSize(value.reason);
            return totalSize;
        }
        if (value instanceof NoSuchRecord) {
            totalSize += FfiConverterString.computeSize(value.reason);
            return totalSize;
        }
        if (value instanceof MissingKey) {
            return totalSize;
        }
        if (value instanceof InvalidKey) {
            return totalSize;
        }
        if (value instanceof EncryptionFailed) {
            totalSize += FfiConverterString.computeSize(value.reason);
            return totalSize;
        }
        if (value instanceof DecryptionFailed) {
            totalSize += FfiConverterString.computeSize(value.reason);
            return totalSize;
        }
        if (value instanceof Interrupted) {
            totalSize += FfiConverterString.computeSize(value.reason);
            return totalSize;
        }
        if (value instanceof UnexpectedLoginsApiError) {
            totalSize += FfiConverterString.computeSize(value.reason);
            return totalSize;
        }
        throw new UniFFITypeError("Unknown LoginsApiError variant");
    }
    static write(dataStream, value) {
        if (value instanceof NssUninitialized) {
            dataStream.writeInt32(1);
            return;
        }
        if (value instanceof NssAuthenticationError) {
            dataStream.writeInt32(2);
            FfiConverterString.write(dataStream, value.reason);
            return;
        }
        if (value instanceof AuthenticationError) {
            dataStream.writeInt32(3);
            FfiConverterString.write(dataStream, value.reason);
            return;
        }
        if (value instanceof AuthenticationCanceled) {
            dataStream.writeInt32(4);
            return;
        }
        if (value instanceof InvalidRecord) {
            dataStream.writeInt32(5);
            FfiConverterString.write(dataStream, value.reason);
            return;
        }
        if (value instanceof NoSuchRecord) {
            dataStream.writeInt32(6);
            FfiConverterString.write(dataStream, value.reason);
            return;
        }
        if (value instanceof MissingKey) {
            dataStream.writeInt32(7);
            return;
        }
        if (value instanceof InvalidKey) {
            dataStream.writeInt32(8);
            return;
        }
        if (value instanceof EncryptionFailed) {
            dataStream.writeInt32(9);
            FfiConverterString.write(dataStream, value.reason);
            return;
        }
        if (value instanceof DecryptionFailed) {
            dataStream.writeInt32(10);
            FfiConverterString.write(dataStream, value.reason);
            return;
        }
        if (value instanceof Interrupted) {
            dataStream.writeInt32(11);
            FfiConverterString.write(dataStream, value.reason);
            return;
        }
        if (value instanceof UnexpectedLoginsApiError) {
            dataStream.writeInt32(12);
            FfiConverterString.write(dataStream, value.reason);
            return;
        }
        throw new UniFFITypeError("Unknown LoginsApiError variant");
    }

    static errorClass = LoginsApiError;
}



/**
 * EncryptorDecryptor
 */
export class EncryptorDecryptor {
    /**
     * decrypt
     * @param {string} ciphertext
     * @returns {string}
     */
    decrypt(
        ciphertext) {
      throw Error("decrypt not implemented");
    }
    /**
     * encrypt
     * @param {string} cleartext
     * @returns {string}
     */
    encrypt(
        cleartext) {
      throw Error("encrypt not implemented");
    }

}

/**
 * EncryptorDecryptor
 */
export class EncryptorDecryptorImpl extends EncryptorDecryptor {
    // 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];
    }

    /**
     * decrypt
     * @param {string} ciphertext
     * @returns {string}
     */
    decrypt(
        ciphertext) {
       
        FfiConverterBytes.checkType(ciphertext);
        const result = UniFFIScaffolding.callSync(
            21, // uniffi_logins_fn_method_encryptordecryptor_decrypt
            FfiConverterTypeEncryptorDecryptor.lowerReceiver(this),
            FfiConverterBytes.lower(ciphertext),
        )
        return handleRustResult(
            result,
            FfiConverterBytes.lift.bind(FfiConverterBytes),
            FfiConverterTypeLoginsApiError.lift.bind(FfiConverterTypeLoginsApiError),
        )
    }

    /**
     * encrypt
     * @param {string} cleartext
     * @returns {string}
     */
    encrypt(
        cleartext) {
       
        FfiConverterBytes.checkType(cleartext);
        const result = UniFFIScaffolding.callSync(
            22, // uniffi_logins_fn_method_encryptordecryptor_encrypt
            FfiConverterTypeEncryptorDecryptor.lowerReceiver(this),
            FfiConverterBytes.lower(cleartext),
        )
        return handleRustResult(
            result,
            FfiConverterBytes.lift.bind(FfiConverterBytes),
            FfiConverterTypeLoginsApiError.lift.bind(FfiConverterTypeLoginsApiError),
        )
    }

}

// FfiConverter for a trait interface.  This is a hybrid of the FFIConverter regular interfaces and
// for callback interfaces.
//
// Export the FFIConverter object to make external types work.
export class FfiConverterTypeEncryptorDecryptor extends FfiConverter {
    static lift(handle) {
        if (handle instanceof UniFFIPointer) {
          // Rust handle.  Construct an object from it
          const opts = {};
          opts[constructUniffiObject] = handle;
          return new EncryptorDecryptorImpl(opts);
        } else {
          // JS handle.  Get the JS object from the callback handler
          return uniffiCallbackHandlerLoginsEncryptorDecryptor.takeCallbackObj(handle)
        }
    }

    static lower(value) {
        const ptr = value[uniffiObjectPtr];
        if (ptr instanceof UniFFIPointer) {
          // Rust-implemented interface, return the ptr.  The C++ code will clone it.
          return ptr;
        } else {
          // JS-implemented interface, store the object in the handle map and return the handle
          if (!(value instanceof EncryptorDecryptor)) {
              throw new UniFFITypeError("expected 'EncryptorDecryptor' subclass");
          }
          return uniffiCallbackHandlerLoginsEncryptorDecryptor.storeCallbackObj(value)
        }
    }

    // lowerReceiver is used when calling methods on an interface we got from Rust, 
    // it treats value like a regular interface.
    static lowerReceiver(value) {
        const ptr = value[uniffiObjectPtr];
        if (!(ptr instanceof UniFFIPointer)) {
            throw new UniFFITypeError("Object is not a 'EncryptorDecryptorImpl' instance");
        }
        return ptr;
    }

    static read(dataStream) {
        return this.lift(dataStream.readHandleOrPointer(4))
    }

    static write(dataStream, value) {
        if (value[uniffiObjectPtr] instanceof UniFFIPointer) {
          // Rust-implemented interface, return the ptr.
          dataStream.writePointer(4, this.lower(value));
        } else {
          dataStream.writeInt64(this.lower(value))
        }
    }

    static computeSize(value) {
        return 8;
    }
}

const uniffiCallbackHandlerLoginsEncryptorDecryptor = new UniFFICallbackHandler(
    "EncryptorDecryptor",
    2,
    [
        new UniFFICallbackMethodHandler(
            "decrypt",
            [
                FfiConverterBytes,
            ],
            FfiConverterBytes.lower.bind(FfiConverterBytes),
            (e) => {
              if (e instanceof LoginsApiError) {
                return FfiConverterTypeLoginsApiError.lower(e);
              }
              throw e;
            }
        ),
        new UniFFICallbackMethodHandler(
            "encrypt",
            [
                FfiConverterBytes,
            ],
            FfiConverterBytes.lower.bind(FfiConverterBytes),
            (e) => {
              if (e instanceof LoginsApiError) {
                return FfiConverterTypeLoginsApiError.lower(e);
              }
              throw e;
            }
        ),
    ]
);

// Allow the shutdown-related functionality to be tested in the unit tests
UnitTestObjs.uniffiCallbackHandlerLoginsEncryptorDecryptor = uniffiCallbackHandlerLoginsEncryptorDecryptor;

/**
 * KeyManager
 */
export class KeyManager {
    /**
     * getKey
     * @returns {string}
     */
    getKey() {
      throw Error("getKey not implemented");
    }

}

/**
 * KeyManager
 */
export class KeyManagerImpl extends KeyManager {
    // 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];
    }

    /**
     * getKey
     * @returns {string}
     */
    getKey() {
       
        const result = UniFFIScaffolding.callSync(
            23, // uniffi_logins_fn_method_keymanager_get_key
            FfiConverterTypeKeyManager.lowerReceiver(this),
        )
        return handleRustResult(
            result,
            FfiConverterBytes.lift.bind(FfiConverterBytes),
            FfiConverterTypeLoginsApiError.lift.bind(FfiConverterTypeLoginsApiError),
        )
    }

}

// FfiConverter for a trait interface.  This is a hybrid of the FFIConverter regular interfaces and
// for callback interfaces.
//
// Export the FFIConverter object to make external types work.
export class FfiConverterTypeKeyManager extends FfiConverter {
    static lift(handle) {
        if (handle instanceof UniFFIPointer) {
          // Rust handle.  Construct an object from it
          const opts = {};
          opts[constructUniffiObject] = handle;
          return new KeyManagerImpl(opts);
        } else {
          // JS handle.  Get the JS object from the callback handler
          return uniffiCallbackHandlerLoginsKeyManager.takeCallbackObj(handle)
        }
    }

    static lower(value) {
        const ptr = value[uniffiObjectPtr];
        if (ptr instanceof UniFFIPointer) {
          // Rust-implemented interface, return the ptr.  The C++ code will clone it.
          return ptr;
        } else {
          // JS-implemented interface, store the object in the handle map and return the handle
          if (!(value instanceof KeyManager)) {
              throw new UniFFITypeError("expected 'KeyManager' subclass");
          }
          return uniffiCallbackHandlerLoginsKeyManager.storeCallbackObj(value)
        }
    }

    // lowerReceiver is used when calling methods on an interface we got from Rust, 
    // it treats value like a regular interface.
    static lowerReceiver(value) {
        const ptr = value[uniffiObjectPtr];
        if (!(ptr instanceof UniFFIPointer)) {
            throw new UniFFITypeError("Object is not a 'KeyManagerImpl' instance");
        }
        return ptr;
    }

    static read(dataStream) {
        return this.lift(dataStream.readHandleOrPointer(5))
    }

    static write(dataStream, value) {
        if (value[uniffiObjectPtr] instanceof UniFFIPointer) {
          // Rust-implemented interface, return the ptr.
          dataStream.writePointer(5, this.lower(value));
        } else {
          dataStream.writeInt64(this.lower(value))
        }
    }

    static computeSize(value) {
        return 8;
    }
}

const uniffiCallbackHandlerLoginsKeyManager = new UniFFICallbackHandler(
    "KeyManager",
    3,
    [
        new UniFFICallbackMethodHandler(
            "getKey",
            [
            ],
            FfiConverterBytes.lower.bind(FfiConverterBytes),
            (e) => {
              if (e instanceof LoginsApiError) {
                return FfiConverterTypeLoginsApiError.lower(e);
              }
              throw e;
            }
        ),
    ]
);

// Allow the shutdown-related functionality to be tested in the unit tests
UnitTestObjs.uniffiCallbackHandlerLoginsKeyManager = uniffiCallbackHandlerLoginsKeyManager;
// Export the FFIConverter object to make external types work.
export class FfiConverterSequenceTypeLoginEntry extends FfiConverterArrayBuffer {
    static read(dataStream) {
        const len = dataStream.readInt32();
        const arr = [];
        for (let i = 0; i < len; i++) {
            arr.push(FfiConverterTypeLoginEntry.read(dataStream));
        }
        return arr;
    }

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

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

    static checkType(value) {
        if (!Array.isArray(value)) {
            throw new UniFFITypeError(`${value} is not an array`);
        }
        value.forEach((innerValue, idx) => {
            try {
                FfiConverterTypeLoginEntry.checkType(innerValue);
            } catch (e) {
                if (e instanceof UniFFITypeError) {
                    e.addItemDescriptionPart(`[${idx}]`);
                }
                throw e;
            }
        })
    }
}
// Export the FFIConverter object to make external types work.
export class FfiConverterSequenceTypeBulkResultEntry extends FfiConverterArrayBuffer {
    static read(dataStream) {
        const len = dataStream.readInt32();
        const arr = [];
        for (let i = 0; i < len; i++) {
            arr.push(FfiConverterTypeBulkResultEntry.read(dataStream));
        }
        return arr;
    }

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

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

    static checkType(value) {
        if (!Array.isArray(value)) {
            throw new UniFFITypeError(`${value} is not an array`);
        }
        value.forEach((innerValue, idx) => {
            try {
                FfiConverterTypeBulkResultEntry.checkType(innerValue);
            } catch (e) {
                if (e instanceof UniFFITypeError) {
                    e.addItemDescriptionPart(`[${idx}]`);
                }
                throw e;
            }
        })
    }
}
// Export the FFIConverter object to make external types work.
export class FfiConverterSequenceTypeLoginEntryWithMeta extends FfiConverterArrayBuffer {
    static read(dataStream) {
        const len = dataStream.readInt32();
        const arr = [];
        for (let i = 0; i < len; i++) {
            arr.push(FfiConverterTypeLoginEntryWithMeta.read(dataStream));
        }
        return arr;
    }

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

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

    static checkType(value) {
        if (!Array.isArray(value)) {
            throw new UniFFITypeError(`${value} is not an array`);
        }
        value.forEach((innerValue, idx) => {
            try {
                FfiConverterTypeLoginEntryWithMeta.checkType(innerValue);
            } catch (e) {
                if (e instanceof UniFFITypeError) {
                    e.addItemDescriptionPart(`[${idx}]`);
                }
                throw e;
            }
        })
    }
}
// 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 FfiConverterSequenceBoolean extends FfiConverterArrayBuffer {
    static read(dataStream) {
        const len = dataStream.readInt32();
        const arr = [];
        for (let i = 0; i < len; i++) {
            arr.push(FfiConverterBoolean.read(dataStream));
        }
        return arr;
    }

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

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

    static checkType(value) {
        if (!Array.isArray(value)) {
            throw new UniFFITypeError(`${value} is not an array`);
        }
        value.forEach((innerValue, idx) => {
            try {
                FfiConverterBoolean.checkType(innerValue);
            } catch (e) {
                if (e instanceof UniFFITypeError) {
                    e.addItemDescriptionPart(`[${idx}]`);
                }
                throw e;
            }
        })
    }
}
// Export the FFIConverter object to make external types work.
export class FfiConverterOptionalTypeLogin extends FfiConverterArrayBuffer {
    static checkType(value) {
        if (value !== undefined && value !== null) {
            FfiConverterTypeLogin.checkType(value)
        }
    }

    static read(dataStream) {
        const code = dataStream.readUint8(0);
        switch (code) {
            case 0:
                return null
            case 1:
                return FfiConverterTypeLogin.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);
        FfiConverterTypeLogin.write(dataStream, value)
    }

    static computeSize(value) {
        if (value === null || value === undefined) {
            return 1;
        }
        return 1 + FfiConverterTypeLogin.computeSize(value)
    }
}
// Export the FFIConverter object to make external types work.
export class FfiConverterSequenceTypeLogin extends FfiConverterArrayBuffer {
    static read(dataStream) {
        const len = dataStream.readInt32();
        const arr = [];
        for (let i = 0; i < len; i++) {
            arr.push(FfiConverterTypeLogin.read(dataStream));
        }
        return arr;
    }

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

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

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

/**
 * LoginStoreInterface
 */
export class LoginStoreInterface {
    /**
     * add
     * @param {LoginEntry} login
     * @returns {Promise<Login>}}
     */
    async add(
        login) {
      throw Error("add not implemented");
    }
    /**
     * addMany
     * @param {Array.<LoginEntry>} logins
     * @returns {Promise<Array.<BulkResultEntry[keyof BulkResultEntry]>>}}
     */
    async addMany(
        logins) {
      throw Error("addMany not implemented");
    }
    /**
     * addManyWithMeta
     * @param {Array.<LoginEntryWithMeta>} entriesWithMeta
     * @returns {Promise<Array.<BulkResultEntry[keyof BulkResultEntry]>>}}
     */
    async addManyWithMeta(
        entriesWithMeta) {
      throw Error("addManyWithMeta not implemented");
    }
    /**
     * addOrUpdate
     * @param {LoginEntry} login
     * @returns {Promise<Login>}}
     */
    async addOrUpdate(
        login) {
      throw Error("addOrUpdate not implemented");
    }
    /**
     * addWithMeta
     * @param {LoginEntryWithMeta} entryWithMeta
     * @returns {Promise<Login>}}
     */
    async addWithMeta(
        entryWithMeta) {
      throw Error("addWithMeta not implemented");
    }
    /**
     * Checks multiple logins for password reuse in a single batch operation.
     * 
     * Returns the GUIDs of logins whose passwords match any password in the breach database.
     * This is more efficient than calling `is_potentially_vulnerable_password()` repeatedly,
     * as it decrypts the breach database only once.
     * @param {Array.<string>} ids
     * @returns {Promise<Array.<string>>}}
     */
    async arePotentiallyVulnerablePasswords(
        ids) {
      throw Error("arePotentiallyVulnerablePasswords not implemented");
    }
    /**
     * count
     * @returns {Promise<number>}}
     */
    async count() {
      throw Error("count not implemented");
    }
    /**
     * countByFormActionOrigin
     * @param {string} formActionOrigin
     * @returns {Promise<number>}}
     */
    async countByFormActionOrigin(
        formActionOrigin) {
      throw Error("countByFormActionOrigin not implemented");
    }
    /**
     * countByOrigin
     * @param {string} origin
     * @returns {Promise<number>}}
     */
    async countByOrigin(
        origin) {
      throw Error("countByOrigin not implemented");
    }
    /**
     * delete
     * @param {string} id
     * @returns {Promise<boolean>}}
     */
    async delete(
        id) {
      throw Error("delete not implemented");
    }
    /**
     * deleteMany
     * @param {Array.<string>} ids
     * @returns {Promise<Array.<boolean>>}}
     */
    async deleteMany(
        ids) {
      throw Error("deleteMany not implemented");
    }
    /**
     * The `delete_undecryptable_records_for_remote_replacement` function locally deletes stored logins
     * that cannot be decrypted and sets the last sync time to 0 so any existing server records can be downloaded
     * and overwrite the locally deleted records.
     * 
     * NB: This function was created to unblock iOS logins users who are unable to sync logins and should not be used
     * outside of this use case.
     * @returns {Promise<LoginsDeletionMetrics>}}
     */
    async deleteUndecryptableRecordsForRemoteReplacement() {
      throw Error("deleteUndecryptableRecordsForRemoteReplacement not implemented");
    }
    /**
     * findLoginToUpdate
     * @param {LoginEntry} look
     * @returns {Promise<?Login>}}
     */
    async findLoginToUpdate(
        look) {
      throw Error("findLoginToUpdate not implemented");
    }
    /**
     * get
     * @param {string} id
     * @returns {Promise<?Login>}}
     */
    async get(
        id) {
      throw Error("get not implemented");
    }
    /**
     * getByBaseDomain
     * @param {string} baseDomain
     * @returns {Promise<Array.<Login>>}}
     */
    async getByBaseDomain(
        baseDomain) {
      throw Error("getByBaseDomain not implemented");
    }
    /**
     * getCheckpoint
     * @returns {Promise<?string>}}
     */
    async getCheckpoint() {
      throw Error("getCheckpoint not implemented");
    }
    /**
     * hasLoginsByBaseDomain
     * @param {string} baseDomain
     * @returns {Promise<boolean>}}
     */
    async hasLoginsByBaseDomain(
        baseDomain) {
      throw Error("hasLoginsByBaseDomain not implemented");
    }
    /**
     * isEmpty
     * @returns {Promise<boolean>}}
     */
    async isEmpty() {
      throw Error("isEmpty not implemented");
    }
    /**
     * Checks if a login's password matches any password in the local breach database.
     * 
     * Returns true if this login's password appears in the breachesL table, indicating
     * that the same password has been breached on a different domain (password reuse).
     * This is independent of whether this specific login has been marked as breached.
     * @param {string} id
     * @returns {Promise<boolean>}}
     */
    async isPotentiallyVulnerablePassword(
        id) {
      throw Error("isPotentiallyVulnerablePassword not implemented");
    }
    /**
     * list
     * @returns {Promise<Array.<Login>>}}
     */
    async list() {
      throw Error("list not implemented");
    }
    /**
     * Stores that the user dismissed the breach alert for a login.
     * @param {string} id
     */
    async recordBreachAlertDismissal(
        id) {
      throw Error("recordBreachAlertDismissal not implemented");
    }
    /**
     * Stores the time at which the user dismissed the breach alert for a login.
     * @param {string} id
     * @param {number} timestamp
     */
    async recordBreachAlertDismissalTime(
        id, 
        timestamp) {
      throw Error("recordBreachAlertDismissalTime not implemented");
    }
    /**
     * Records a list of potentially vulnerable passwords in the breach database.
     * 
     * This is used to bulk-populate the breachesL table with known breached passwords,
     * typically during import operations or when syncing breach data.
     * Passwords are encrypted before storage and duplicates are automatically filtered out.
     * @param {Array.<string>} passwords
     */
    async recordPotentiallyVulnerablePasswords(
        passwords) {
      throw Error("recordPotentiallyVulnerablePasswords not implemented");
    }
    /**
     * registerWithSyncManager
     */
    async registerWithSyncManager() {
      throw Error("registerWithSyncManager not implemented");
    }
    /**
     * reset
     */
    async reset() {
      throw Error("reset not implemented");
    }
    /**
     * Removes all recorded breaches.
     */
    async resetAllBreaches() {
      throw Error("resetAllBreaches not implemented");
    }
    /**
     * Run maintenance on the DB
     * 
     * This is intended to be run during idle time and will take steps / to clean up / shrink the
     * database.
     */
    async runMaintenance() {
      throw Error("runMaintenance not implemented");
    }
    /**
     * setCheckpoint
     * @param {string} checkpoint
     */
    async setCheckpoint(
        checkpoint) {
      throw Error("setCheckpoint not implemented");
    }
    /**
     * shutdown
     */
    shutdown() {
      throw Error("shutdown not implemented");
    }
    /**
     * touch
     * @param {string} id
     */
    async touch(
        id) {
      throw Error("touch not implemented");
    }
    /**
     * update
     * @param {string} id
     * @param {LoginEntry} login
     * @returns {Promise<Login>}}
     */
    async update(
        id, 
        login) {
      throw Error("update not implemented");
    }
    /**
     * Clear out locally stored logins data
     * 
     * If sync is enabled, then we will try to recover the data on the next sync.
     * 
     * The main reason to call this is when regenerating a new encryption key.
     * In that case, there's no reason to keep around the local data since it can't be decrypted.
     * Calling `wipe_local` is better than keeping around these un-decryptable logins, since we
     * might be able to recover the data via sync.
     * 
     * This is a no-op for freshly created databases, so it's safe to call this whenever a key is
     * generated.
     */
    async wipeLocal() {
      throw Error("wipeLocal not implemented");
    }

}

/**
 * LoginStore
 */
export class LoginStore extends LoginStoreInterface {
    // 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
     * @param {string} path
     * @param {EncryptorDecryptor} encdec
     * @returns {Promise<LoginStore>}}
     */
    static async init(
        path, 
        encdec) {
       
        FfiConverterString.checkType(path);
        FfiConverterTypeEncryptorDecryptor.checkType(encdec);
        const result = await UniFFIScaffolding.callAsyncWrapper(
            24, // uniffi_logins_fn_constructor_loginstore_new
            FfiConverterString.lower(path),
            FfiConverterTypeEncryptorDecryptor.lower(encdec),
        )
        return handleRustResult(
            result,
            FfiConverterTypeLoginStore.lift.bind(FfiConverterTypeLoginStore),
            FfiConverterTypeLoginsApiError.lift.bind(FfiConverterTypeLoginsApiError),
        )
    }

    /**
     * add
     * @param {LoginEntry} login
     * @returns {Promise<Login>}}
     */
    async add(
        login) {
       
        FfiConverterTypeLoginEntry.checkType(login);
        const result = await UniFFIScaffolding.callAsyncWrapper(
            25, // uniffi_logins_fn_method_loginstore_add
            FfiConverterTypeLoginStore.lowerReceiver(this),
            FfiConverterTypeLoginEntry.lower(login),
        )
        return handleRustResult(
            result,
            FfiConverterTypeLogin.lift.bind(FfiConverterTypeLogin),
            FfiConverterTypeLoginsApiError.lift.bind(FfiConverterTypeLoginsApiError),
        )
    }

    /**
     * addMany
     * @param {Array.<LoginEntry>} logins
     * @returns {Promise<Array.<BulkResultEntry[keyof BulkResultEntry]>>}}
     */
    async addMany(
        logins) {
       
        FfiConverterSequenceTypeLoginEntry.checkType(logins);
        const result = await UniFFIScaffolding.callAsyncWrapper(
            26, // uniffi_logins_fn_method_loginstore_add_many
            FfiConverterTypeLoginStore.lowerReceiver(this),
            FfiConverterSequenceTypeLoginEntry.lower(logins),
        )
        return handleRustResult(
            result,
            FfiConverterSequenceTypeBulkResultEntry.lift.bind(FfiConverterSequenceTypeBulkResultEntry),
            FfiConverterTypeLoginsApiError.lift.bind(FfiConverterTypeLoginsApiError),
        )
    }

    /**
     * addManyWithMeta
     * @param {Array.<LoginEntryWithMeta>} entriesWithMeta
     * @returns {Promise<Array.<BulkResultEntry[keyof BulkResultEntry]>>}}
     */
    async addManyWithMeta(
        entriesWithMeta) {
       
        FfiConverterSequenceTypeLoginEntryWithMeta.checkType(entriesWithMeta);
        const result = await UniFFIScaffolding.callAsyncWrapper(
            27, // uniffi_logins_fn_method_loginstore_add_many_with_meta
            FfiConverterTypeLoginStore.lowerReceiver(this),
            FfiConverterSequenceTypeLoginEntryWithMeta.lower(entriesWithMeta),
        )
        return handleRustResult(
            result,
            FfiConverterSequenceTypeBulkResultEntry.lift.bind(FfiConverterSequenceTypeBulkResultEntry),
            FfiConverterTypeLoginsApiError.lift.bind(FfiConverterTypeLoginsApiError),
        )
    }

    /**
     * addOrUpdate
     * @param {LoginEntry} login
     * @returns {Promise<Login>}}
     */
    async addOrUpdate(
        login) {
       
        FfiConverterTypeLoginEntry.checkType(login);
        const result = await UniFFIScaffolding.callAsyncWrapper(
            28, // uniffi_logins_fn_method_loginstore_add_or_update
            FfiConverterTypeLoginStore.lowerReceiver(this),
            FfiConverterTypeLoginEntry.lower(login),
        )
        return handleRustResult(
            result,
            FfiConverterTypeLogin.lift.bind(FfiConverterTypeLogin),
            FfiConverterTypeLoginsApiError.lift.bind(FfiConverterTypeLoginsApiError),
        )
    }

    /**
     * addWithMeta
     * @param {LoginEntryWithMeta} entryWithMeta
     * @returns {Promise<Login>}}
     */
    async addWithMeta(
        entryWithMeta) {
       
        FfiConverterTypeLoginEntryWithMeta.checkType(entryWithMeta);
        const result = await UniFFIScaffolding.callAsyncWrapper(
            29, // uniffi_logins_fn_method_loginstore_add_with_meta
            FfiConverterTypeLoginStore.lowerReceiver(this),
            FfiConverterTypeLoginEntryWithMeta.lower(entryWithMeta),
        )
        return handleRustResult(
            result,
            FfiConverterTypeLogin.lift.bind(FfiConverterTypeLogin),
            FfiConverterTypeLoginsApiError.lift.bind(FfiConverterTypeLoginsApiError),
        )
    }

    /**
     * Checks multiple logins for password reuse in a single batch operation.
     * 
     * Returns the GUIDs of logins whose passwords match any password in the breach database.
     * This is more efficient than calling `is_potentially_vulnerable_password()` repeatedly,
     * as it decrypts the breach database only once.
     * @param {Array.<string>} ids
     * @returns {Promise<Array.<string>>}}
     */
    async arePotentiallyVulnerablePasswords(
        ids) {
       
        FfiConverterSequenceString.checkType(ids);
        const result = await UniFFIScaffolding.callAsyncWrapper(
            30, // uniffi_logins_fn_method_loginstore_are_potentially_vulnerable_passwords
            FfiConverterTypeLoginStore.lowerReceiver(this),
            FfiConverterSequenceString.lower(ids),
        )
        return handleRustResult(
            result,
            FfiConverterSequenceString.lift.bind(FfiConverterSequenceString),
            FfiConverterTypeLoginsApiError.lift.bind(FfiConverterTypeLoginsApiError),
        )
    }

    /**
     * count
     * @returns {Promise<number>}}
     */
    async count() {
       
        const result = await UniFFIScaffolding.callAsyncWrapper(
            31, // uniffi_logins_fn_method_loginstore_count
            FfiConverterTypeLoginStore.lowerReceiver(this),
        )
        return handleRustResult(
            result,
            FfiConverterInt64.lift.bind(FfiConverterInt64),
            FfiConverterTypeLoginsApiError.lift.bind(FfiConverterTypeLoginsApiError),
        )
    }

    /**
     * countByFormActionOrigin
     * @param {string} formActionOrigin
     * @returns {Promise<number>}}
     */
    async countByFormActionOrigin(
        formActionOrigin) {
       
        FfiConverterString.checkType(formActionOrigin);
        const result = await UniFFIScaffolding.callAsyncWrapper(
            32, // uniffi_logins_fn_method_loginstore_count_by_form_action_origin
            FfiConverterTypeLoginStore.lowerReceiver(this),
            FfiConverterString.lower(formActionOrigin),
        )
        return handleRustResult(
            result,
            FfiConverterInt64.lift.bind(FfiConverterInt64),
            FfiConverterTypeLoginsApiError.lift.bind(FfiConverterTypeLoginsApiError),
        )
    }

    /**
     * countByOrigin
     * @param {string} origin
     * @returns {Promise<number>}}
     */
    async countByOrigin(
        origin) {
       
        FfiConverterString.checkType(origin);
        const result = await UniFFIScaffolding.callAsyncWrapper(
            33, // uniffi_logins_fn_method_loginstore_count_by_origin
            FfiConverterTypeLoginStore.lowerReceiver(this),
            FfiConverterString.lower(origin),
        )
        return handleRustResult(
            result,
            FfiConverterInt64.lift.bind(FfiConverterInt64),
            FfiConverterTypeLoginsApiError.lift.bind(FfiConverterTypeLoginsApiError),
        )
    }

    /**
     * delete
     * @param {string} id
     * @returns {Promise<boolean>}}
     */
    async delete(
        id) {
       
        FfiConverterString.checkType(id);
        const result = await UniFFIScaffolding.callAsyncWrapper(
            34, // uniffi_logins_fn_method_loginstore_delete
            FfiConverterTypeLoginStore.lowerReceiver(this),
            FfiConverterString.lower(id),
        )
        return handleRustResult(
            result,
            FfiConverterBoolean.lift.bind(FfiConverterBoolean),
            FfiConverterTypeLoginsApiError.lift.bind(FfiConverterTypeLoginsApiError),
        )
    }

    /**
     * deleteMany
     * @param {Array.<string>} ids
     * @returns {Promise<Array.<boolean>>}}
     */
    async deleteMany(
        ids) {
       
        FfiConverterSequenceString.checkType(ids);
        const result = await UniFFIScaffolding.callAsyncWrapper(
            35, // uniffi_logins_fn_method_loginstore_delete_many
            FfiConverterTypeLoginStore.lowerReceiver(this),
            FfiConverterSequenceString.lower(ids),
        )
        return handleRustResult(
            result,
            FfiConverterSequenceBoolean.lift.bind(FfiConverterSequenceBoolean),
            FfiConverterTypeLoginsApiError.lift.bind(FfiConverterTypeLoginsApiError),
        )
    }

    /**
     * The `delete_undecryptable_records_for_remote_replacement` function locally deletes stored logins
     * that cannot be decrypted and sets the last sync time to 0 so any existing server records can be downloaded
     * and overwrite the locally deleted records.
     * 
     * NB: This function was created to unblock iOS logins users who are unable to sync logins and should not be used
     * outside of this use case.
     * @returns {Promise<LoginsDeletionMetrics>}}
     */
    async deleteUndecryptableRecordsForRemoteReplacement() {
       
        const result = await UniFFIScaffolding.callAsyncWrapper(
            36, // uniffi_logins_fn_method_loginstore_delete_undecryptable_records_for_remote_replacement
            FfiConverterTypeLoginStore.lowerReceiver(this),
        )
        return handleRustResult(
            result,
            FfiConverterTypeLoginsDeletionMetrics.lift.bind(FfiConverterTypeLoginsDeletionMetrics),
            FfiConverterTypeLoginsApiError.lift.bind(FfiConverterTypeLoginsApiError),
        )
    }

    /**
     * findLoginToUpdate
     * @param {LoginEntry} look
     * @returns {Promise<?Login>}}
     */
    async findLoginToUpdate(
        look) {
       
        FfiConverterTypeLoginEntry.checkType(look);
        const result = await UniFFIScaffolding.callAsyncWrapper(
            37, // uniffi_logins_fn_method_loginstore_find_login_to_update
            FfiConverterTypeLoginStore.lowerReceiver(this),
            FfiConverterTypeLoginEntry.lower(look),
        )
        return handleRustResult(
            result,
            FfiConverterOptionalTypeLogin.lift.bind(FfiConverterOptionalTypeLogin),
            FfiConverterTypeLoginsApiError.lift.bind(FfiConverterTypeLoginsApiError),
        )
    }

    /**
     * get
     * @param {string} id
     * @returns {Promise<?Login>}}
     */
    async get(
        id) {
       
        FfiConverterString.checkType(id);
        const result = await UniFFIScaffolding.callAsyncWrapper(
            38, // uniffi_logins_fn_method_loginstore_get
            FfiConverterTypeLoginStore.lowerReceiver(this),
            FfiConverterString.lower(id),
        )
        return handleRustResult(
            result,
            FfiConverterOptionalTypeLogin.lift.bind(FfiConverterOptionalTypeLogin),
            FfiConverterTypeLoginsApiError.lift.bind(FfiConverterTypeLoginsApiError),
        )
    }

    /**
     * getByBaseDomain
     * @param {string} baseDomain
     * @returns {Promise<Array.<Login>>}}
     */
    async getByBaseDomain(
        baseDomain) {
       
        FfiConverterString.checkType(baseDomain);
        const result = await UniFFIScaffolding.callAsyncWrapper(
            39, // uniffi_logins_fn_method_loginstore_get_by_base_domain
            FfiConverterTypeLoginStore.lowerReceiver(this),
            FfiConverterString.lower(baseDomain),
        )
        return handleRustResult(
            result,
            FfiConverterSequenceTypeLogin.lift.bind(FfiConverterSequenceTypeLogin),
            FfiConverterTypeLoginsApiError.lift.bind(FfiConverterTypeLoginsApiError),
        )
    }

    /**
     * getCheckpoint
     * @returns {Promise<?string>}}
     */
    async getCheckpoint() {
       
        const result = await UniFFIScaffolding.callAsyncWrapper(
            40, // uniffi_logins_fn_method_loginstore_get_checkpoint
            FfiConverterTypeLoginStore.lowerReceiver(this),
        )
        return handleRustResult(
            result,
            FfiConverterOptionalString.lift.bind(FfiConverterOptionalString),
            FfiConverterTypeLoginsApiError.lift.bind(FfiConverterTypeLoginsApiError),
        )
    }

    /**
     * hasLoginsByBaseDomain
     * @param {string} baseDomain
     * @returns {Promise<boolean>}}
     */
    async hasLoginsByBaseDomain(
        baseDomain) {
       
        FfiConverterString.checkType(baseDomain);
        const result = await UniFFIScaffolding.callAsyncWrapper(
            41, // uniffi_logins_fn_method_loginstore_has_logins_by_base_domain
            FfiConverterTypeLoginStore.lowerReceiver(this),
            FfiConverterString.lower(baseDomain),
        )
        return handleRustResult(
            result,
            FfiConverterBoolean.lift.bind(FfiConverterBoolean),
            FfiConverterTypeLoginsApiError.lift.bind(FfiConverterTypeLoginsApiError),
        )
    }

    /**
     * isEmpty
     * @returns {Promise<boolean>}}
     */
    async isEmpty() {
       
        const result = await UniFFIScaffolding.callAsyncWrapper(
            42, // uniffi_logins_fn_method_loginstore_is_empty
            FfiConverterTypeLoginStore.lowerReceiver(this),
        )
        return handleRustResult(
            result,
            FfiConverterBoolean.lift.bind(FfiConverterBoolean),
            FfiConverterTypeLoginsApiError.lift.bind(FfiConverterTypeLoginsApiError),
        )
    }

    /**
     * Checks if a login's password matches any password in the local breach database.
     * 
     * Returns true if this login's password appears in the breachesL table, indicating
     * that the same password has been breached on a different domain (password reuse).
     * This is independent of whether this specific login has been marked as breached.
     * @param {string} id
     * @returns {Promise<boolean>}}
     */
    async isPotentiallyVulnerablePassword(
        id) {
       
        FfiConverterString.checkType(id);
        const result = await UniFFIScaffolding.callAsyncWrapper(
            43, // uniffi_logins_fn_method_loginstore_is_potentially_vulnerable_password
            FfiConverterTypeLoginStore.lowerReceiver(this),
            FfiConverterString.lower(id),
        )
        return handleRustResult(
            result,
            FfiConverterBoolean.lift.bind(FfiConverterBoolean),
            FfiConverterTypeLoginsApiError.lift.bind(FfiConverterTypeLoginsApiError),
        )
    }

    /**
     * list
     * @returns {Promise<Array.<Login>>}}
     */
    async list() {
       
        const result = await UniFFIScaffolding.callAsyncWrapper(
            44, // uniffi_logins_fn_method_loginstore_list
            FfiConverterTypeLoginStore.lowerReceiver(this),
        )
        return handleRustResult(
            result,
            FfiConverterSequenceTypeLogin.lift.bind(FfiConverterSequenceTypeLogin),
            FfiConverterTypeLoginsApiError.lift.bind(FfiConverterTypeLoginsApiError),
        )
    }

    /**
     * Stores that the user dismissed the breach alert for a login.
     * @param {string} id
     */
    async recordBreachAlertDismissal(
        id) {
       
        FfiConverterString.checkType(id);
        const result = await UniFFIScaffolding.callAsyncWrapper(
            45, // uniffi_logins_fn_method_loginstore_record_breach_alert_dismissal
            FfiConverterTypeLoginStore.lowerReceiver(this),
            FfiConverterString.lower(id),
        )
        return handleRustResult(
            result,
            (result) => undefined,
            FfiConverterTypeLoginsApiError.lift.bind(FfiConverterTypeLoginsApiError),
        )
    }

    /**
     * Stores the time at which the user dismissed the breach alert for a login.
     * @param {string} id
     * @param {number} timestamp
     */
    async recordBreachAlertDismissalTime(
        id, 
        timestamp) {
       
        FfiConverterString.checkType(id);
        FfiConverterInt64.checkType(timestamp);
        const result = await UniFFIScaffolding.callAsyncWrapper(
            46, // uniffi_logins_fn_method_loginstore_record_breach_alert_dismissal_time
            FfiConverterTypeLoginStore.lowerReceiver(this),
            FfiConverterString.lower(id),
            FfiConverterInt64.lower(timestamp),
        )
        return handleRustResult(
            result,
            (result) => undefined,
            FfiConverterTypeLoginsApiError.lift.bind(FfiConverterTypeLoginsApiError),
        )
    }

    /**
     * Records a list of potentially vulnerable passwords in the breach database.
     * 
     * This is used to bulk-populate the breachesL table with known breached passwords,
     * typically during import operations or when syncing breach data.
     * Passwords are encrypted before storage and duplicates are automatically filtered out.
     * @param {Array.<string>} passwords
     */
    async recordPotentiallyVulnerablePasswords(
        passwords) {
       
        FfiConverterSequenceString.checkType(passwords);
        const result = await UniFFIScaffolding.callAsyncWrapper(
            47, // uniffi_logins_fn_method_loginstore_record_potentially_vulnerable_passwords
            FfiConverterTypeLoginStore.lowerReceiver(this),
            FfiConverterSequenceString.lower(passwords),
        )
        return handleRustResult(
            result,
            (result) => undefined,
            FfiConverterTypeLoginsApiError.lift.bind(FfiConverterTypeLoginsApiError),
        )
    }

    /**
     * registerWithSyncManager
     */
    async registerWithSyncManager() {
       
        const result = await UniFFIScaffolding.callAsyncWrapper(
            48, // uniffi_logins_fn_method_loginstore_register_with_sync_manager
            FfiConverterTypeLoginStore.lowerReceiver(this),
        )
        return handleRustResult(
            result,
            (result) => undefined,
            null,
        )
    }

    /**
     * reset
     */
    async reset() {
       
        const result = await UniFFIScaffolding.callAsyncWrapper(
            49, // uniffi_logins_fn_method_loginstore_reset
            FfiConverterTypeLoginStore.lowerReceiver(this),
        )
        return handleRustResult(
            result,
            (result) => undefined,
            FfiConverterTypeLoginsApiError.lift.bind(FfiConverterTypeLoginsApiError),
        )
    }

    /**
     * Removes all recorded breaches.
     */
    async resetAllBreaches() {
       
        const result = await UniFFIScaffolding.callAsyncWrapper(
            50, // uniffi_logins_fn_method_loginstore_reset_all_breaches
            FfiConverterTypeLoginStore.lowerReceiver(this),
        )
        return handleRustResult(
            result,
            (result) => undefined,
            FfiConverterTypeLoginsApiError.lift.bind(FfiConverterTypeLoginsApiError),
        )
    }

    /**
     * Run maintenance on the DB
     * 
     * This is intended to be run during idle time and will take steps / to clean up / shrink the
     * database.
     */
    async runMaintenance() {
       
        const result = await UniFFIScaffolding.callAsyncWrapper(
            51, // uniffi_logins_fn_method_loginstore_run_maintenance
            FfiConverterTypeLoginStore.lowerReceiver(this),
        )
        return handleRustResult(
            result,
            (result) => undefined,
            FfiConverterTypeLoginsApiError.lift.bind(FfiConverterTypeLoginsApiError),
        )
    }

    /**
     * setCheckpoint
     * @param {string} checkpoint
     */
    async setCheckpoint(
        checkpoint) {
       
        FfiConverterString.checkType(checkpoint);
        const result = await UniFFIScaffolding.callAsyncWrapper(
            52, // uniffi_logins_fn_method_loginstore_set_checkpoint
            FfiConverterTypeLoginStore.lowerReceiver(this),
            FfiConverterString.lower(checkpoint),
        )
        return handleRustResult(
            result,
            (result) => undefined,
            FfiConverterTypeLoginsApiError.lift.bind(FfiConverterTypeLoginsApiError),
        )
    }

    /**
     * shutdown
     */
    shutdown() {
       
        const result = UniFFIScaffolding.callSync(
            53, // uniffi_logins_fn_method_loginstore_shutdown
            FfiConverterTypeLoginStore.lowerReceiver(this),
        )
        return handleRustResult(
            result,
            (result) => undefined,
            null,
        )
    }

    /**
     * touch
     * @param {string} id
     */
    async touch(
        id) {
       
        FfiConverterString.checkType(id);
        const result = await UniFFIScaffolding.callAsyncWrapper(
            54, // uniffi_logins_fn_method_loginstore_touch
            FfiConverterTypeLoginStore.lowerReceiver(this),
            FfiConverterString.lower(id),
        )
        return handleRustResult(
            result,
            (result) => undefined,
            FfiConverterTypeLoginsApiError.lift.bind(FfiConverterTypeLoginsApiError),
        )
    }

    /**
     * update
     * @param {string} id
     * @param {LoginEntry} login
     * @returns {Promise<Login>}}
     */
    async update(
        id, 
        login) {
       
        FfiConverterString.checkType(id);
        FfiConverterTypeLoginEntry.checkType(login);
        const result = await UniFFIScaffolding.callAsyncWrapper(
            55, // uniffi_logins_fn_method_loginstore_update
            FfiConverterTypeLoginStore.lowerReceiver(this),
            FfiConverterString.lower(id),
            FfiConverterTypeLoginEntry.lower(login),
        )
        return handleRustResult(
            result,
            FfiConverterTypeLogin.lift.bind(FfiConverterTypeLogin),
            FfiConverterTypeLoginsApiError.lift.bind(FfiConverterTypeLoginsApiError),
        )
    }

    /**
     * Clear out locally stored logins data
     * 
     * If sync is enabled, then we will try to recover the data on the next sync.
     * 
     * The main reason to call this is when regenerating a new encryption key.
     * In that case, there's no reason to keep around the local data since it can't be decrypted.
     * Calling `wipe_local` is better than keeping around these un-decryptable logins, since we
     * might be able to recover the data via sync.
     * 
     * This is a no-op for freshly created databases, so it's safe to call this whenever a key is
     * generated.
     */
    async wipeLocal() {
       
        const result = await UniFFIScaffolding.callAsyncWrapper(
            56, // uniffi_logins_fn_method_loginstore_wipe_local
            FfiConverterTypeLoginStore.lowerReceiver(this),
        )
        return handleRustResult(
            result,
            (result) => undefined,
            FfiConverterTypeLoginsApiError.lift.bind(FfiConverterTypeLoginsApiError),
        )
    }

}

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

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

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

    static computeSize(value) {
        return 8;
    }
}


/**
 * ManagedEncryptorDecryptorInterface
 */
export class ManagedEncryptorDecryptorInterface {

}

/**
 * ManagedEncryptorDecryptor
 */
export class ManagedEncryptorDecryptor extends ManagedEncryptorDecryptorInterface {
    // 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
     * @param {KeyManager} keyManager
     * @returns {ManagedEncryptorDecryptor}
     */
    static init(
        keyManager) {
       
        FfiConverterTypeKeyManager.checkType(keyManager);
        const result = UniFFIScaffolding.callSync(
            57, // uniffi_logins_fn_constructor_managedencryptordecryptor_new
            FfiConverterTypeKeyManager.lower(keyManager),
        )
        return handleRustResult(
            result,
            FfiConverterTypeManagedEncryptorDecryptor.lift.bind(FfiConverterTypeManagedEncryptorDecryptor),
            null,
        )
    }

}

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

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

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

    static computeSize(value) {
        return 8;
    }
}


/**
 * Use the `NSSKeyManager` to use NSS for key management.
 * 
 * NSS stores keys in `key4.db` within the profile and wraps the key with a key derived from the
 * primary password, if set. It defers to the provided `PrimaryPasswordAuthenticator`
 * implementation to handle user authentication.  Note that if no primary password is set, the
 * wrapping key is deterministically derived from an empty string.
 * 
 * Make sure to initialize NSS using `ensure_initialized_with_profile_dir` before creating a
 * NSSKeyManager.
 * 
 * # Examples
 * ```no_run
 * use async_trait::async_trait;
 * use logins::encryption::KeyManager;
 * use logins::{PrimaryPasswordAuthenticator, LoginsApiError, NSSKeyManager};
 * use std::sync::Arc;
 * 
 * struct MyPrimaryPasswordAuthenticator {}
 * 
 * #[async_trait]
 * impl PrimaryPasswordAuthenticator for MyPrimaryPasswordAuthenticator {
 * async fn get_primary_password(&self) -> Result<String, LoginsApiError> {
 * // Most likely, you would want to prompt for a password.
 * // let password = prompt_string("primary password").unwrap_or_default();
 * Ok("secret".to_string())
 * }
 * 
 * async fn on_authentication_success(&self) -> Result<(), LoginsApiError> {
 * println!("success");
 * Ok(())
 * }
 * 
 * async fn on_authentication_failure(&self) -> Result<(), LoginsApiError> {
 * println!("this did not work, please try again:");
 * Ok(())
 * }
 * }
 * let key_manager = NSSKeyManager::new(Arc::new(MyPrimaryPasswordAuthenticator {}));
 * assert_eq!(key_manager.get_key().unwrap().len(), 63);
 * ```
 */
export class NssKeyManagerInterface {
    /**
     * intoDynKeyManager
     * @returns {KeyManager}
     */
    intoDynKeyManager() {
      throw Error("intoDynKeyManager not implemented");
    }

}

/**
 * Use the `NSSKeyManager` to use NSS for key management.
 * 
 * NSS stores keys in `key4.db` within the profile and wraps the key with a key derived from the
 * primary password, if set. It defers to the provided `PrimaryPasswordAuthenticator`
 * implementation to handle user authentication.  Note that if no primary password is set, the
 * wrapping key is deterministically derived from an empty string.
 * 
 * Make sure to initialize NSS using `ensure_initialized_with_profile_dir` before creating a
 * NSSKeyManager.
 * 
 * # Examples
 * ```no_run
 * use async_trait::async_trait;
 * use logins::encryption::KeyManager;
 * use logins::{PrimaryPasswordAuthenticator, LoginsApiError, NSSKeyManager};
 * use std::sync::Arc;
 * 
 * struct MyPrimaryPasswordAuthenticator {}
 * 
 * #[async_trait]
 * impl PrimaryPasswordAuthenticator for MyPrimaryPasswordAuthenticator {
 * async fn get_primary_password(&self) -> Result<String, LoginsApiError> {
 * // Most likely, you would want to prompt for a password.
 * // let password = prompt_string("primary password").unwrap_or_default();
 * Ok("secret".to_string())
 * }
 * 
 * async fn on_authentication_success(&self) -> Result<(), LoginsApiError> {
 * println!("success");
 * Ok(())
 * }
 * 
 * async fn on_authentication_failure(&self) -> Result<(), LoginsApiError> {
 * println!("this did not work, please try again:");
 * Ok(())
 * }
 * }
 * let key_manager = NSSKeyManager::new(Arc::new(MyPrimaryPasswordAuthenticator {}));
 * assert_eq!(key_manager.get_key().unwrap().len(), 63);
 * ```
 */
export class NssKeyManager extends NssKeyManagerInterface {
    // 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];
    }
    /**
     * Initialize new `NSSKeyManager` with a given `PrimaryPasswordAuthenticator`.
     * There must be a previous initializiation of NSS before initializing
     * `NSSKeyManager`, otherwise this panics.
     * @param {PrimaryPasswordAuthenticator} primaryPasswordAuthenticator
     * @returns {NssKeyManager}
     */
    static init(
        primaryPasswordAuthenticator) {
       
        FfiConverterTypePrimaryPasswordAuthenticator.checkType(primaryPasswordAuthenticator);
        const result = UniFFIScaffolding.callSync(
            58, // uniffi_logins_fn_constructor_nsskeymanager_new
            FfiConverterTypePrimaryPasswordAuthenticator.lower(primaryPasswordAuthenticator),
        )
        return handleRustResult(
            result,
            FfiConverterTypeNSSKeyManager.lift.bind(FfiConverterTypeNSSKeyManager),
            null,
        )
    }

    /**
     * intoDynKeyManager
     * @returns {KeyManager}
     */
    intoDynKeyManager() {
       
        const result = UniFFIScaffolding.callSync(
            59, // uniffi_logins_fn_method_nsskeymanager_into_dyn_key_manager
            FfiConverterTypeNSSKeyManager.lowerReceiver(this),
        )
        return handleRustResult(
            result,
            FfiConverterTypeKeyManager.lift.bind(FfiConverterTypeKeyManager),
            null,
        )
    }

}

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

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

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

    static computeSize(value) {
        return 8;
    }
}


/**
 * `PrimaryPasswordAuthenticator` is used in conjunction with `NSSKeyManager` to provide the
 * primary password and the success or failure actions of the authentication process.
 */
export class PrimaryPasswordAuthenticator {
    /**
     * Get a primary password for authentication, otherwise return the
     * AuthenticationCancelled error to cancel the authentication process.
     * @returns {Promise<string>}}
     */
    async getPrimaryPassword() {
      throw Error("getPrimaryPassword not implemented");
    }
    /**
     * onAuthenticationSuccess
     */
    async onAuthenticationSuccess() {
      throw Error("onAuthenticationSuccess not implemented");
    }
    /**
     * onAuthenticationFailure
     */
    async onAuthenticationFailure() {
      throw Error("onAuthenticationFailure not implemented");
    }

}

/**
 * `PrimaryPasswordAuthenticator` is used in conjunction with `NSSKeyManager` to provide the
 * primary password and the success or failure actions of the authentication process.
 */
export class PrimaryPasswordAuthenticatorImpl extends PrimaryPasswordAuthenticator {
    // 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];
    }

    /**
     * Get a primary password for authentication, otherwise return the
     * AuthenticationCancelled error to cancel the authentication process.
     * @returns {Promise<string>}}
     */
    async getPrimaryPassword() {
       
        const result = await UniFFIScaffolding.callAsync(
            60, // uniffi_logins_fn_method_primarypasswordauthenticator_get_primary_password
            FfiConverterTypePrimaryPasswordAuthenticator.lowerReceiver(this),
        )
        return handleRustResult(
            result,
            FfiConverterString.lift.bind(FfiConverterString),
            FfiConverterTypeLoginsApiError.lift.bind(FfiConverterTypeLoginsApiError),
        )
    }

    /**
     * onAuthenticationSuccess
     */
    async onAuthenticationSuccess() {
       
        const result = await UniFFIScaffolding.callAsync(
            61, // uniffi_logins_fn_method_primarypasswordauthenticator_on_authentication_success
            FfiConverterTypePrimaryPasswordAuthenticator.lowerReceiver(this),
        )
        return handleRustResult(
            result,
            (result) => undefined,
            FfiConverterTypeLoginsApiError.lift.bind(FfiConverterTypeLoginsApiError),
        )
    }

    /**
     * onAuthenticationFailure
     */
    async onAuthenticationFailure() {
       
        const result = await UniFFIScaffolding.callAsync(
            62, // uniffi_logins_fn_method_primarypasswordauthenticator_on_authentication_failure
            FfiConverterTypePrimaryPasswordAuthenticator.lowerReceiver(this),
        )
        return handleRustResult(
            result,
            (result) => undefined,
            FfiConverterTypeLoginsApiError.lift.bind(FfiConverterTypeLoginsApiError),
        )
    }

}

// FfiConverter for a trait interface.  This is a hybrid of the FFIConverter regular interfaces and
// for callback interfaces.
//
// Export the FFIConverter object to make external types work.
export class FfiConverterTypePrimaryPasswordAuthenticator extends FfiConverter {
    static lift(handle) {
        if (handle instanceof UniFFIPointer) {
          // Rust handle.  Construct an object from it
          const opts = {};
          opts[constructUniffiObject] = handle;
          return new PrimaryPasswordAuthenticatorImpl(opts);
        } else {
          // JS handle.  Get the JS object from the callback handler
          return uniffiCallbackHandlerLoginsPrimaryPasswordAuthenticator.takeCallbackObj(handle)
        }
    }

    static lower(value) {
        const ptr = value[uniffiObjectPtr];
        if (ptr instanceof UniFFIPointer) {
          // Rust-implemented interface, return the ptr.  The C++ code will clone it.
          return ptr;
        } else {
          // JS-implemented interface, store the object in the handle map and return the handle
          if (!(value instanceof PrimaryPasswordAuthenticator)) {
              throw new UniFFITypeError("expected 'PrimaryPasswordAuthenticator' subclass");
          }
          return uniffiCallbackHandlerLoginsPrimaryPasswordAuthenticator.storeCallbackObj(value)
        }
    }

    // lowerReceiver is used when calling methods on an interface we got from Rust, 
    // it treats value like a regular interface.
    static lowerReceiver(value) {
        const ptr = value[uniffiObjectPtr];
        if (!(ptr instanceof UniFFIPointer)) {
            throw new UniFFITypeError("Object is not a 'PrimaryPasswordAuthenticatorImpl' instance");
        }
        return ptr;
    }

    static read(dataStream) {
        return this.lift(dataStream.readHandleOrPointer(9))
    }

    static write(dataStream, value) {
        if (value[uniffiObjectPtr] instanceof UniFFIPointer) {
          // Rust-implemented interface, return the ptr.
          dataStream.writePointer(9, this.lower(value));
        } else {
          dataStream.writeInt64(this.lower(value))
        }
    }

    static computeSize(value) {
        return 8;
    }
}

const uniffiCallbackHandlerLoginsPrimaryPasswordAuthenticator = new UniFFICallbackHandler(
    "PrimaryPasswordAuthenticator",
    4,
    [
        new UniFFICallbackMethodHandler(
            "getPrimaryPassword",
            [
            ],
            FfiConverterString.lower.bind(FfiConverterString),
            (e) => {
              if (e instanceof LoginsApiError) {
                return FfiConverterTypeLoginsApiError.lower(e);
              }
              throw e;
            }
        ),
        new UniFFICallbackMethodHandler(
            "onAuthenticationSuccess",
            [
            ],
            (result) => undefined,
            (e) => {
              if (e instanceof LoginsApiError) {
                return FfiConverterTypeLoginsApiError.lower(e);
              }
              throw e;
            }
        ),
        new UniFFICallbackMethodHandler(
            "onAuthenticationFailure",
            [
            ],
            (result) => undefined,
            (e) => {
              if (e instanceof LoginsApiError) {
                return FfiConverterTypeLoginsApiError.lower(e);
              }
              throw e;
            }
        ),
    ]
);

// Allow the shutdown-related functionality to be tested in the unit tests
UnitTestObjs.uniffiCallbackHandlerLoginsPrimaryPasswordAuthenticator = uniffiCallbackHandlerLoginsPrimaryPasswordAuthenticator;

/**
 * StaticKeyManagerInterface
 */
export class StaticKeyManagerInterface {

}

/**
 * StaticKeyManager
 */
export class StaticKeyManager extends StaticKeyManagerInterface {
    // 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
     * @param {string} key
     * @returns {StaticKeyManager}
     */
    static init(
        key) {
       
        FfiConverterString.checkType(key);
        const result = UniFFIScaffolding.callSync(
            63, // uniffi_logins_fn_constructor_statickeymanager_new
            FfiConverterString.lower(key),
        )
        return handleRustResult(
            result,
            FfiConverterTypeStaticKeyManager.lift.bind(FfiConverterTypeStaticKeyManager),
            null,
        )
    }

}

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

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

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

    static computeSize(value) {
        return 8;
    }
}



