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

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



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

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

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

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

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

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

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

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

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

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


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

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

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

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

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

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

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

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

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

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

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

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


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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

class UniFFIInternalError extends UniFFIError {}

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

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

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

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

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

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

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

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

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

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

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

/**
 * RemoteCommandStore
 */
export class RemoteCommandStore {
    // Use `init` to instantiate this class.
    // DO NOT USE THIS CONSTRUCTOR DIRECTLY
    constructor(opts) {
        if (!Object.prototype.hasOwnProperty.call(opts, constructUniffiObject)) {
            throw new UniFFIError("Attempting to construct an object using the JavaScript constructor directly" +
            "Please use a UDL defined constructor, or the init function for the primary constructor")
        }
        if (!opts[constructUniffiObject] instanceof UniFFIPointer) {
            throw new UniFFIError("Attempting to create a UniFFI object with a pointer that is not an instance of UniFFIPointer")
        }
        this[uniffiObjectPtr] = opts[constructUniffiObject];
    }

    /**
     * Add a new command, after which it will be pending. Returns false if the command is already active.
     * @returns {Boolean}
     */
    addRemoteCommand(deviceId,command) {
        const liftResult = (result) => FfiConverterBool.lift(result);
        const liftError = (data) => FfiConverterTypeTabsApiError.lift(data);
        const functionCall = () => {
            try {
                FfiConverterString.checkType(deviceId)
            } catch (e) {
                if (e instanceof UniFFITypeError) {
                    e.addItemDescriptionPart("deviceId");
                }
                throw e;
            }
            try {
                FfiConverterTypeRemoteCommand.checkType(command)
            } catch (e) {
                if (e instanceof UniFFITypeError) {
                    e.addItemDescriptionPart("command");
                }
                throw e;
            }
            return UniFFIScaffolding.callAsyncWrapper(
                44, // tabs:uniffi_tabs_fn_method_remotecommandstore_add_remote_command
                FfiConverterTypeRemoteCommandStore.lower(this),
                FfiConverterString.lower(deviceId),
                FfiConverterTypeRemoteCommand.lower(command),
            )
        }
        try {
            return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
        }  catch (error) {
            return Promise.reject(error)
        }
    }

    /**
     * Add a new command with an explicit timestamp. Primarily used by tests.
     * @returns {Boolean}
     */
    addRemoteCommandAt(deviceId,command,when) {
        const liftResult = (result) => FfiConverterBool.lift(result);
        const liftError = (data) => FfiConverterTypeTabsApiError.lift(data);
        const functionCall = () => {
            try {
                FfiConverterString.checkType(deviceId)
            } catch (e) {
                if (e instanceof UniFFITypeError) {
                    e.addItemDescriptionPart("deviceId");
                }
                throw e;
            }
            try {
                FfiConverterTypeRemoteCommand.checkType(command)
            } catch (e) {
                if (e instanceof UniFFITypeError) {
                    e.addItemDescriptionPart("command");
                }
                throw e;
            }
            try {
                FfiConverterTypeTimestamp.checkType(when)
            } catch (e) {
                if (e instanceof UniFFITypeError) {
                    e.addItemDescriptionPart("when");
                }
                throw e;
            }
            return UniFFIScaffolding.callAsyncWrapper(
                45, // tabs:uniffi_tabs_fn_method_remotecommandstore_add_remote_command_at
                FfiConverterTypeRemoteCommandStore.lower(this),
                FfiConverterString.lower(deviceId),
                FfiConverterTypeRemoteCommand.lower(command),
                FfiConverterTypeTimestamp.lower(when),
            )
        }
        try {
            return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
        }  catch (error) {
            return Promise.reject(error)
        }
    }

    /**
     * Return all unsent commands. This is for the code sending the commands, result is sorted by time_requested.
     * @returns {Array.<PendingCommand>}
     */
    getUnsentCommands() {
        const liftResult = (result) => FfiConverterSequenceTypePendingCommand.lift(result);
        const liftError = (data) => FfiConverterTypeTabsApiError.lift(data);
        const functionCall = () => {
            return UniFFIScaffolding.callAsyncWrapper(
                46, // tabs:uniffi_tabs_fn_method_remotecommandstore_get_unsent_commands
                FfiConverterTypeRemoteCommandStore.lower(this),
            )
        }
        try {
            return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
        }  catch (error) {
            return Promise.reject(error)
        }
    }

    /**
     * Removes the remote command. Typically used to implement "undo" but may also be used by the queue
     * processor when it gives up trying to send a command.
     * @returns {Boolean}
     */
    removeRemoteCommand(deviceId,command) {
        const liftResult = (result) => FfiConverterBool.lift(result);
        const liftError = (data) => FfiConverterTypeTabsApiError.lift(data);
        const functionCall = () => {
            try {
                FfiConverterString.checkType(deviceId)
            } catch (e) {
                if (e instanceof UniFFITypeError) {
                    e.addItemDescriptionPart("deviceId");
                }
                throw e;
            }
            try {
                FfiConverterTypeRemoteCommand.checkType(command)
            } catch (e) {
                if (e instanceof UniFFITypeError) {
                    e.addItemDescriptionPart("command");
                }
                throw e;
            }
            return UniFFIScaffolding.callAsyncWrapper(
                47, // tabs:uniffi_tabs_fn_method_remotecommandstore_remove_remote_command
                FfiConverterTypeRemoteCommandStore.lower(this),
                FfiConverterString.lower(deviceId),
                FfiConverterTypeRemoteCommand.lower(command),
            )
        }
        try {
            return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
        }  catch (error) {
            return Promise.reject(error)
        }
    }

    /**
     * Flag a command as sent.
     * @returns {Boolean}
     */
    setPendingCommandSent(command) {
        const liftResult = (result) => FfiConverterBool.lift(result);
        const liftError = (data) => FfiConverterTypeTabsApiError.lift(data);
        const functionCall = () => {
            try {
                FfiConverterTypePendingCommand.checkType(command)
            } catch (e) {
                if (e instanceof UniFFITypeError) {
                    e.addItemDescriptionPart("command");
                }
                throw e;
            }
            return UniFFIScaffolding.callAsyncWrapper(
                48, // tabs:uniffi_tabs_fn_method_remotecommandstore_set_pending_command_sent
                FfiConverterTypeRemoteCommandStore.lower(this),
                FfiConverterTypePendingCommand.lower(command),
            )
        }
        try {
            return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
        }  catch (error) {
            return Promise.reject(error)
        }
    }

}

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

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

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

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

    static computeSize(value) {
        return 8;
    }
}

/**
 * Note the canonical docs for this are in https://searchfox.org/mozilla-central/source/services/interfaces/mozIBridgedSyncEngine.idl
 * It's only actually used in desktop, but it's fine to expose this everywhere.
 * NOTE: all timestamps here are milliseconds.
 */
export class TabsBridgedEngine {
    // Use `init` to instantiate this class.
    // DO NOT USE THIS CONSTRUCTOR DIRECTLY
    constructor(opts) {
        if (!Object.prototype.hasOwnProperty.call(opts, constructUniffiObject)) {
            throw new UniFFIError("Attempting to construct an object using the JavaScript constructor directly" +
            "Please use a UDL defined constructor, or the init function for the primary constructor")
        }
        if (!opts[constructUniffiObject] instanceof UniFFIPointer) {
            throw new UniFFIError("Attempting to create a UniFFI object with a pointer that is not an instance of UniFFIPointer")
        }
        this[uniffiObjectPtr] = opts[constructUniffiObject];
    }

    /**
     * apply
     * @returns {Array.<string>}
     */
    apply() {
        const liftResult = (result) => FfiConverterSequencestring.lift(result);
        const liftError = (data) => FfiConverterTypeTabsApiError.lift(data);
        const functionCall = () => {
            return UniFFIScaffolding.callAsyncWrapper(
                49, // tabs:uniffi_tabs_fn_method_tabsbridgedengine_apply
                FfiConverterTypeTabsBridgedEngine.lower(this),
            )
        }
        try {
            return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
        }  catch (error) {
            return Promise.reject(error)
        }
    }

    /**
     * ensureCurrentSyncId
     * @returns {string}
     */
    ensureCurrentSyncId(newSyncId) {
        const liftResult = (result) => FfiConverterString.lift(result);
        const liftError = (data) => FfiConverterTypeTabsApiError.lift(data);
        const functionCall = () => {
            try {
                FfiConverterString.checkType(newSyncId)
            } catch (e) {
                if (e instanceof UniFFITypeError) {
                    e.addItemDescriptionPart("newSyncId");
                }
                throw e;
            }
            return UniFFIScaffolding.callAsyncWrapper(
                50, // tabs:uniffi_tabs_fn_method_tabsbridgedengine_ensure_current_sync_id
                FfiConverterTypeTabsBridgedEngine.lower(this),
                FfiConverterString.lower(newSyncId),
            )
        }
        try {
            return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
        }  catch (error) {
            return Promise.reject(error)
        }
    }

    /**
     * lastSync
     * @returns {number}
     */
    lastSync() {
        const liftResult = (result) => FfiConverterI64.lift(result);
        const liftError = (data) => FfiConverterTypeTabsApiError.lift(data);
        const functionCall = () => {
            return UniFFIScaffolding.callAsyncWrapper(
                51, // tabs:uniffi_tabs_fn_method_tabsbridgedengine_last_sync
                FfiConverterTypeTabsBridgedEngine.lower(this),
            )
        }
        try {
            return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
        }  catch (error) {
            return Promise.reject(error)
        }
    }

    /**
     * prepareForSync
     */
    prepareForSync(clientData) {
        const liftResult = (result) => undefined;
        const liftError = (data) => FfiConverterTypeTabsApiError.lift(data);
        const functionCall = () => {
            try {
                FfiConverterString.checkType(clientData)
            } catch (e) {
                if (e instanceof UniFFITypeError) {
                    e.addItemDescriptionPart("clientData");
                }
                throw e;
            }
            return UniFFIScaffolding.callAsyncWrapper(
                52, // tabs:uniffi_tabs_fn_method_tabsbridgedengine_prepare_for_sync
                FfiConverterTypeTabsBridgedEngine.lower(this),
                FfiConverterString.lower(clientData),
            )
        }
        try {
            return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
        }  catch (error) {
            return Promise.reject(error)
        }
    }

    /**
     * reset
     */
    reset() {
        const liftResult = (result) => undefined;
        const liftError = (data) => FfiConverterTypeTabsApiError.lift(data);
        const functionCall = () => {
            return UniFFIScaffolding.callAsyncWrapper(
                53, // tabs:uniffi_tabs_fn_method_tabsbridgedengine_reset
                FfiConverterTypeTabsBridgedEngine.lower(this),
            )
        }
        try {
            return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
        }  catch (error) {
            return Promise.reject(error)
        }
    }

    /**
     * resetSyncId
     * @returns {string}
     */
    resetSyncId() {
        const liftResult = (result) => FfiConverterString.lift(result);
        const liftError = (data) => FfiConverterTypeTabsApiError.lift(data);
        const functionCall = () => {
            return UniFFIScaffolding.callAsyncWrapper(
                54, // tabs:uniffi_tabs_fn_method_tabsbridgedengine_reset_sync_id
                FfiConverterTypeTabsBridgedEngine.lower(this),
            )
        }
        try {
            return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
        }  catch (error) {
            return Promise.reject(error)
        }
    }

    /**
     * setLastSync
     */
    setLastSync(lastSync) {
        const liftResult = (result) => undefined;
        const liftError = (data) => FfiConverterTypeTabsApiError.lift(data);
        const functionCall = () => {
            try {
                FfiConverterI64.checkType(lastSync)
            } catch (e) {
                if (e instanceof UniFFITypeError) {
                    e.addItemDescriptionPart("lastSync");
                }
                throw e;
            }
            return UniFFIScaffolding.callAsyncWrapper(
                55, // tabs:uniffi_tabs_fn_method_tabsbridgedengine_set_last_sync
                FfiConverterTypeTabsBridgedEngine.lower(this),
                FfiConverterI64.lower(lastSync),
            )
        }
        try {
            return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
        }  catch (error) {
            return Promise.reject(error)
        }
    }

    /**
     * setUploaded
     */
    setUploaded(newTimestamp,uploadedIds) {
        const liftResult = (result) => undefined;
        const liftError = (data) => FfiConverterTypeTabsApiError.lift(data);
        const functionCall = () => {
            try {
                FfiConverterI64.checkType(newTimestamp)
            } catch (e) {
                if (e instanceof UniFFITypeError) {
                    e.addItemDescriptionPart("newTimestamp");
                }
                throw e;
            }
            try {
                FfiConverterSequenceTypeTabsGuid.checkType(uploadedIds)
            } catch (e) {
                if (e instanceof UniFFITypeError) {
                    e.addItemDescriptionPart("uploadedIds");
                }
                throw e;
            }
            return UniFFIScaffolding.callAsyncWrapper(
                56, // tabs:uniffi_tabs_fn_method_tabsbridgedengine_set_uploaded
                FfiConverterTypeTabsBridgedEngine.lower(this),
                FfiConverterI64.lower(newTimestamp),
                FfiConverterSequenceTypeTabsGuid.lower(uploadedIds),
            )
        }
        try {
            return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
        }  catch (error) {
            return Promise.reject(error)
        }
    }

    /**
     * storeIncoming
     */
    storeIncoming(incomingEnvelopesAsJson) {
        const liftResult = (result) => undefined;
        const liftError = (data) => FfiConverterTypeTabsApiError.lift(data);
        const functionCall = () => {
            try {
                FfiConverterSequencestring.checkType(incomingEnvelopesAsJson)
            } catch (e) {
                if (e instanceof UniFFITypeError) {
                    e.addItemDescriptionPart("incomingEnvelopesAsJson");
                }
                throw e;
            }
            return UniFFIScaffolding.callAsyncWrapper(
                57, // tabs:uniffi_tabs_fn_method_tabsbridgedengine_store_incoming
                FfiConverterTypeTabsBridgedEngine.lower(this),
                FfiConverterSequencestring.lower(incomingEnvelopesAsJson),
            )
        }
        try {
            return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
        }  catch (error) {
            return Promise.reject(error)
        }
    }

    /**
     * syncFinished
     */
    syncFinished() {
        const liftResult = (result) => undefined;
        const liftError = (data) => FfiConverterTypeTabsApiError.lift(data);
        const functionCall = () => {
            return UniFFIScaffolding.callAsyncWrapper(
                58, // tabs:uniffi_tabs_fn_method_tabsbridgedengine_sync_finished
                FfiConverterTypeTabsBridgedEngine.lower(this),
            )
        }
        try {
            return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
        }  catch (error) {
            return Promise.reject(error)
        }
    }

    /**
     * syncId
     * @returns {?string}
     */
    syncId() {
        const liftResult = (result) => FfiConverterOptionalstring.lift(result);
        const liftError = (data) => FfiConverterTypeTabsApiError.lift(data);
        const functionCall = () => {
            return UniFFIScaffolding.callAsyncWrapper(
                59, // tabs:uniffi_tabs_fn_method_tabsbridgedengine_sync_id
                FfiConverterTypeTabsBridgedEngine.lower(this),
            )
        }
        try {
            return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
        }  catch (error) {
            return Promise.reject(error)
        }
    }

    /**
     * syncStarted
     */
    syncStarted() {
        const liftResult = (result) => undefined;
        const liftError = (data) => FfiConverterTypeTabsApiError.lift(data);
        const functionCall = () => {
            return UniFFIScaffolding.callAsyncWrapper(
                60, // tabs:uniffi_tabs_fn_method_tabsbridgedengine_sync_started
                FfiConverterTypeTabsBridgedEngine.lower(this),
            )
        }
        try {
            return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
        }  catch (error) {
            return Promise.reject(error)
        }
    }

    /**
     * wipe
     */
    wipe() {
        const liftResult = (result) => undefined;
        const liftError = (data) => FfiConverterTypeTabsApiError.lift(data);
        const functionCall = () => {
            return UniFFIScaffolding.callAsyncWrapper(
                61, // tabs:uniffi_tabs_fn_method_tabsbridgedengine_wipe
                FfiConverterTypeTabsBridgedEngine.lower(this),
            )
        }
        try {
            return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
        }  catch (error) {
            return Promise.reject(error)
        }
    }

}

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

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

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

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

    static computeSize(value) {
        return 8;
    }
}

/**
 * TabsStore
 */
export class TabsStore {
    // Use `init` to instantiate this class.
    // DO NOT USE THIS CONSTRUCTOR DIRECTLY
    constructor(opts) {
        if (!Object.prototype.hasOwnProperty.call(opts, constructUniffiObject)) {
            throw new UniFFIError("Attempting to construct an object using the JavaScript constructor directly" +
            "Please use a UDL defined constructor, or the init function for the primary constructor")
        }
        if (!opts[constructUniffiObject] instanceof UniFFIPointer) {
            throw new UniFFIError("Attempting to create a UniFFI object with a pointer that is not an instance of UniFFIPointer")
        }
        this[uniffiObjectPtr] = opts[constructUniffiObject];
    }
    /**
     * init
     * @returns {TabsStore}
     */
    static init(path) {
        const liftResult = (result) => FfiConverterTypeTabsStore.lift(result);
        const liftError = null;
        const functionCall = () => {
            try {
                FfiConverterString.checkType(path)
            } catch (e) {
                if (e instanceof UniFFITypeError) {
                    e.addItemDescriptionPart("path");
                }
                throw e;
            }
            return UniFFIScaffolding.callAsyncWrapper(
                68, // tabs:uniffi_tabs_fn_constructor_tabsstore_new
                FfiConverterString.lower(path),
            )
        }
        try {
            return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
        }  catch (error) {
            return Promise.reject(error)
        }}

    /**
     * bridgedEngine
     * @returns {TabsBridgedEngine}
     */
    bridgedEngine() {
        const liftResult = (result) => FfiConverterTypeTabsBridgedEngine.lift(result);
        const liftError = null;
        const functionCall = () => {
            return UniFFIScaffolding.callAsyncWrapper(
                62, // tabs:uniffi_tabs_fn_method_tabsstore_bridged_engine
                FfiConverterTypeTabsStore.lower(this),
            )
        }
        try {
            return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
        }  catch (error) {
            return Promise.reject(error)
        }
    }

    /**
     * closeConnection
     */
    closeConnection() {
        const liftResult = (result) => undefined;
        const liftError = null;
        const functionCall = () => {
            return UniFFIScaffolding.callAsyncWrapper(
                63, // tabs:uniffi_tabs_fn_method_tabsstore_close_connection
                FfiConverterTypeTabsStore.lower(this),
            )
        }
        try {
            return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
        }  catch (error) {
            return Promise.reject(error)
        }
    }

    /**
     * getAll
     * @returns {Array.<ClientRemoteTabs>}
     */
    getAll() {
        const liftResult = (result) => FfiConverterSequenceTypeClientRemoteTabs.lift(result);
        const liftError = null;
        const functionCall = () => {
            return UniFFIScaffolding.callAsyncWrapper(
                64, // tabs:uniffi_tabs_fn_method_tabsstore_get_all
                FfiConverterTypeTabsStore.lower(this),
            )
        }
        try {
            return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
        }  catch (error) {
            return Promise.reject(error)
        }
    }

    /**
     * newRemoteCommandStore
     * @returns {RemoteCommandStore}
     */
    newRemoteCommandStore() {
        const liftResult = (result) => FfiConverterTypeRemoteCommandStore.lift(result);
        const liftError = null;
        const functionCall = () => {
            return UniFFIScaffolding.callAsyncWrapper(
                65, // tabs:uniffi_tabs_fn_method_tabsstore_new_remote_command_store
                FfiConverterTypeTabsStore.lower(this),
            )
        }
        try {
            return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
        }  catch (error) {
            return Promise.reject(error)
        }
    }

    /**
     * registerWithSyncManager
     */
    registerWithSyncManager() {
        const liftResult = (result) => undefined;
        const liftError = null;
        const functionCall = () => {
            return UniFFIScaffolding.callAsyncWrapper(
                66, // tabs:uniffi_tabs_fn_method_tabsstore_register_with_sync_manager
                FfiConverterTypeTabsStore.lower(this),
            )
        }
        try {
            return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
        }  catch (error) {
            return Promise.reject(error)
        }
    }

    /**
     * setLocalTabs
     */
    setLocalTabs(remoteTabs) {
        const liftResult = (result) => undefined;
        const liftError = null;
        const functionCall = () => {
            try {
                FfiConverterSequenceTypeRemoteTabRecord.checkType(remoteTabs)
            } catch (e) {
                if (e instanceof UniFFITypeError) {
                    e.addItemDescriptionPart("remoteTabs");
                }
                throw e;
            }
            return UniFFIScaffolding.callAsyncWrapper(
                67, // tabs:uniffi_tabs_fn_method_tabsstore_set_local_tabs
                FfiConverterTypeTabsStore.lower(this),
                FfiConverterSequenceTypeRemoteTabRecord.lower(remoteTabs),
            )
        }
        try {
            return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
        }  catch (error) {
            return Promise.reject(error)
        }
    }

}

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

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

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

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

    static computeSize(value) {
        return 8;
    }
}

/**
 * ClientRemoteTabs
 */
export class ClientRemoteTabs {
    constructor({ clientId, clientName, deviceType, lastModified, remoteTabs } = {}) {
        try {
            FfiConverterString.checkType(clientId)
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart("clientId");
            }
            throw e;
        }
        try {
            FfiConverterString.checkType(clientName)
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart("clientName");
            }
            throw e;
        }
        try {
            FfiConverterTypeDeviceType.checkType(deviceType)
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart("deviceType");
            }
            throw e;
        }
        try {
            FfiConverterI64.checkType(lastModified)
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart("lastModified");
            }
            throw e;
        }
        try {
            FfiConverterSequenceTypeRemoteTabRecord.checkType(remoteTabs)
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart("remoteTabs");
            }
            throw e;
        }
        /**
         * @type {string}
         */
        this.clientId = clientId;
        /**
         * @type {string}
         */
        this.clientName = clientName;
        /**
         * @type {DeviceType}
         */
        this.deviceType = deviceType;
        /**
         * Number of ms since the unix epoch (as reported by the server's clock)
         * @type {number}
         */
        this.lastModified = lastModified;
        /**
         * @type {Array.<RemoteTabRecord>}
         */
        this.remoteTabs = remoteTabs;
    }

    equals(other) {
        return (
            this.clientId == other.clientId &&
            this.clientName == other.clientName &&
            this.deviceType == other.deviceType &&
            this.lastModified == other.lastModified &&
            this.remoteTabs == other.remoteTabs
        )
    }
}

// Export the FFIConverter object to make external types work.
export class FfiConverterTypeClientRemoteTabs extends FfiConverterArrayBuffer {
    static read(dataStream) {
        return new ClientRemoteTabs({
            clientId: FfiConverterString.read(dataStream),
            clientName: FfiConverterString.read(dataStream),
            deviceType: FfiConverterTypeDeviceType.read(dataStream),
            lastModified: FfiConverterI64.read(dataStream),
            remoteTabs: FfiConverterSequenceTypeRemoteTabRecord.read(dataStream),
        });
    }
    static write(dataStream, value) {
        FfiConverterString.write(dataStream, value.clientId);
        FfiConverterString.write(dataStream, value.clientName);
        FfiConverterTypeDeviceType.write(dataStream, value.deviceType);
        FfiConverterI64.write(dataStream, value.lastModified);
        FfiConverterSequenceTypeRemoteTabRecord.write(dataStream, value.remoteTabs);
    }

    static computeSize(value) {
        let totalSize = 0;
        totalSize += FfiConverterString.computeSize(value.clientId);
        totalSize += FfiConverterString.computeSize(value.clientName);
        totalSize += FfiConverterTypeDeviceType.computeSize(value.deviceType);
        totalSize += FfiConverterI64.computeSize(value.lastModified);
        totalSize += FfiConverterSequenceTypeRemoteTabRecord.computeSize(value.remoteTabs);
        return totalSize
    }

    static checkType(value) {
        super.checkType(value);
        if (!(value instanceof ClientRemoteTabs)) {
            throw new UniFFITypeError(`Expected 'ClientRemoteTabs', found '${typeof value}'`);
        }
        try {
            FfiConverterString.checkType(value.clientId);
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart(".clientId");
            }
            throw e;
        }
        try {
            FfiConverterString.checkType(value.clientName);
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart(".clientName");
            }
            throw e;
        }
        try {
            FfiConverterTypeDeviceType.checkType(value.deviceType);
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart(".deviceType");
            }
            throw e;
        }
        try {
            FfiConverterI64.checkType(value.lastModified);
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart(".lastModified");
            }
            throw e;
        }
        try {
            FfiConverterSequenceTypeRemoteTabRecord.checkType(value.remoteTabs);
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart(".remoteTabs");
            }
            throw e;
        }
    }
}

/**
 * Represents a "pending" command.
 */
export class PendingCommand {
    constructor({ deviceId, command, timeRequested, timeSent } = {}) {
        try {
            FfiConverterString.checkType(deviceId)
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart("deviceId");
            }
            throw e;
        }
        try {
            FfiConverterTypeRemoteCommand.checkType(command)
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart("command");
            }
            throw e;
        }
        try {
            FfiConverterTypeTimestamp.checkType(timeRequested)
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart("timeRequested");
            }
            throw e;
        }
        try {
            FfiConverterOptionalTypeTimestamp.checkType(timeSent)
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart("timeSent");
            }
            throw e;
        }
        /**
         * @type {string}
         */
        this.deviceId = deviceId;
        /**
         * @type {RemoteCommand}
         */
        this.command = command;
        /**
         * @type {Timestamp}
         */
        this.timeRequested = timeRequested;
        /**
         * @type {?Timestamp}
         */
        this.timeSent = timeSent;
    }

    equals(other) {
        return (
            this.deviceId == other.deviceId &&
            this.command == other.command &&
            this.timeRequested == other.timeRequested &&
            this.timeSent == other.timeSent
        )
    }
}

// Export the FFIConverter object to make external types work.
export class FfiConverterTypePendingCommand extends FfiConverterArrayBuffer {
    static read(dataStream) {
        return new PendingCommand({
            deviceId: FfiConverterString.read(dataStream),
            command: FfiConverterTypeRemoteCommand.read(dataStream),
            timeRequested: FfiConverterTypeTimestamp.read(dataStream),
            timeSent: FfiConverterOptionalTypeTimestamp.read(dataStream),
        });
    }
    static write(dataStream, value) {
        FfiConverterString.write(dataStream, value.deviceId);
        FfiConverterTypeRemoteCommand.write(dataStream, value.command);
        FfiConverterTypeTimestamp.write(dataStream, value.timeRequested);
        FfiConverterOptionalTypeTimestamp.write(dataStream, value.timeSent);
    }

    static computeSize(value) {
        let totalSize = 0;
        totalSize += FfiConverterString.computeSize(value.deviceId);
        totalSize += FfiConverterTypeRemoteCommand.computeSize(value.command);
        totalSize += FfiConverterTypeTimestamp.computeSize(value.timeRequested);
        totalSize += FfiConverterOptionalTypeTimestamp.computeSize(value.timeSent);
        return totalSize
    }

    static checkType(value) {
        super.checkType(value);
        if (!(value instanceof PendingCommand)) {
            throw new UniFFITypeError(`Expected 'PendingCommand', found '${typeof value}'`);
        }
        try {
            FfiConverterString.checkType(value.deviceId);
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart(".deviceId");
            }
            throw e;
        }
        try {
            FfiConverterTypeRemoteCommand.checkType(value.command);
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart(".command");
            }
            throw e;
        }
        try {
            FfiConverterTypeTimestamp.checkType(value.timeRequested);
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart(".timeRequested");
            }
            throw e;
        }
        try {
            FfiConverterOptionalTypeTimestamp.checkType(value.timeSent);
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart(".timeSent");
            }
            throw e;
        }
    }
}

/**
 * RemoteTabRecord
 */
export class RemoteTabRecord {
    constructor({ title, urlHistory, icon, lastUsed, inactive = false } = {}) {
        try {
            FfiConverterString.checkType(title)
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart("title");
            }
            throw e;
        }
        try {
            FfiConverterSequencestring.checkType(urlHistory)
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart("urlHistory");
            }
            throw e;
        }
        try {
            FfiConverterOptionalstring.checkType(icon)
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart("icon");
            }
            throw e;
        }
        try {
            FfiConverterI64.checkType(lastUsed)
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart("lastUsed");
            }
            throw e;
        }
        try {
            FfiConverterBool.checkType(inactive)
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart("inactive");
            }
            throw e;
        }
        /**
         * @type {string}
         */
        this.title = title;
        /**
         * @type {Array.<string>}
         */
        this.urlHistory = urlHistory;
        /**
         * @type {?string}
         */
        this.icon = icon;
        /**
         * Number of ms since the unix epoch (as reported by the client's clock)
         * @type {number}
         */
        this.lastUsed = lastUsed;
        /**
         * @type {Boolean}
         */
        this.inactive = inactive;
    }

    equals(other) {
        return (
            this.title == other.title &&
            this.urlHistory == other.urlHistory &&
            this.icon == other.icon &&
            this.lastUsed == other.lastUsed &&
            this.inactive == other.inactive
        )
    }
}

// Export the FFIConverter object to make external types work.
export class FfiConverterTypeRemoteTabRecord extends FfiConverterArrayBuffer {
    static read(dataStream) {
        return new RemoteTabRecord({
            title: FfiConverterString.read(dataStream),
            urlHistory: FfiConverterSequencestring.read(dataStream),
            icon: FfiConverterOptionalstring.read(dataStream),
            lastUsed: FfiConverterI64.read(dataStream),
            inactive: FfiConverterBool.read(dataStream),
        });
    }
    static write(dataStream, value) {
        FfiConverterString.write(dataStream, value.title);
        FfiConverterSequencestring.write(dataStream, value.urlHistory);
        FfiConverterOptionalstring.write(dataStream, value.icon);
        FfiConverterI64.write(dataStream, value.lastUsed);
        FfiConverterBool.write(dataStream, value.inactive);
    }

    static computeSize(value) {
        let totalSize = 0;
        totalSize += FfiConverterString.computeSize(value.title);
        totalSize += FfiConverterSequencestring.computeSize(value.urlHistory);
        totalSize += FfiConverterOptionalstring.computeSize(value.icon);
        totalSize += FfiConverterI64.computeSize(value.lastUsed);
        totalSize += FfiConverterBool.computeSize(value.inactive);
        return totalSize
    }

    static checkType(value) {
        super.checkType(value);
        if (!(value instanceof RemoteTabRecord)) {
            throw new UniFFITypeError(`Expected 'RemoteTabRecord', found '${typeof value}'`);
        }
        try {
            FfiConverterString.checkType(value.title);
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart(".title");
            }
            throw e;
        }
        try {
            FfiConverterSequencestring.checkType(value.urlHistory);
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart(".urlHistory");
            }
            throw e;
        }
        try {
            FfiConverterOptionalstring.checkType(value.icon);
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart(".icon");
            }
            throw e;
        }
        try {
            FfiConverterI64.checkType(value.lastUsed);
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart(".lastUsed");
            }
            throw e;
        }
        try {
            FfiConverterBool.checkType(value.inactive);
        } catch (e) {
            if (e instanceof UniFFITypeError) {
                e.addItemDescriptionPart(".inactive");
            }
            throw e;
        }
    }
}


/**
 * A command which should be sent to a remote device.
 */
export class RemoteCommand {}
/**
 * CloseTab
 */
RemoteCommand.CloseTab = class extends RemoteCommand{
    constructor(
        url
        ) {
            super();
            this.url = url;
        }
}

// Export the FFIConverter object to make external types work.
export class FfiConverterTypeRemoteCommand extends FfiConverterArrayBuffer {
    static read(dataStream) {
        switch (dataStream.readInt32()) {
            case 1:
                return new RemoteCommand.CloseTab(
                    FfiConverterString.read(dataStream)
                    );
            default:
                throw new UniFFITypeError("Unknown RemoteCommand variant");
        }
    }

    static write(dataStream, value) {
        if (value instanceof RemoteCommand.CloseTab) {
            dataStream.writeInt32(1);
            FfiConverterString.write(dataStream, value.url);
            return;
        }
        throw new UniFFITypeError("Unknown RemoteCommand variant");
    }

    static computeSize(value) {
        // Size of the Int indicating the variant
        let totalSize = 4;
        if (value instanceof RemoteCommand.CloseTab) {
            totalSize += FfiConverterString.computeSize(value.url);
            return totalSize;
        }
        throw new UniFFITypeError("Unknown RemoteCommand variant");
    }

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





/**
 * TabsApiError
 */
export class TabsApiError extends Error {}


/**
 * SyncError
 */
export class SyncError extends TabsApiError {

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

/**
 * SqlError
 */
export class SqlError extends TabsApiError {

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

/**
 * UnexpectedTabsError
 */
export class UnexpectedTabsError extends TabsApiError {

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

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

    static errorClass = TabsApiError;
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

import {
  FfiConverterTypeDeviceType,
  DeviceType,
} from "resource://gre/modules/RustSync15.sys.mjs";

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

// Export the FFIConverter object to make external types work.
export class FfiConverterTypeTabsGuid extends FfiConverter {
    static lift(buf) {
        return FfiConverterString.lift(buf);    
    }
    
    static lower(buf) {
        return FfiConverterString.lower(buf);
    }
    
    static write(dataStream, value) {
        FfiConverterString.write(dataStream, value);
    } 
    
    static read(buf) {
        return FfiConverterString.read(buf);
    }
    
    static computeSize(value) {
        return FfiConverterString.computeSize(value);
    }
}
// TODO: We should also allow JS to customize the type eventually.

// Export the FFIConverter object to make external types work.
export class FfiConverterTypeTimestamp extends FfiConverter {
    static lift(buf) {
        return FfiConverterI64.lift(buf);    
    }
    
    static lower(buf) {
        return FfiConverterI64.lower(buf);
    }
    
    static write(dataStream, value) {
        FfiConverterI64.write(dataStream, value);
    } 
    
    static read(buf) {
        return FfiConverterI64.read(buf);
    }
    
    static computeSize(value) {
        return FfiConverterI64.computeSize(value);
    }
}
// TODO: We should also allow JS to customize the type eventually.




