declare module "node:ffi" {
    import { NonSharedBuffer } from "node:buffer";
    interface FunctionSignature {
        return?: ReturnType | undefined;
        arguments?: readonly ArgumentType[] | undefined;
    }
    interface FunctionDefinitions {
        [symbol: string]: FunctionSignature;
    }
    type CallbackFunction<R extends ReturnType = any, P extends readonly ArgumentType[] = any[]> = (
        ...args: { [K in keyof P]: ArgumentTypeMap[DataTypeMap[P[K]]] }
    ) => ReturnTypeMap[DataTypeMap[R]];
    interface WrappedFunction<R extends ReturnType = any, P extends readonly ArgumentType[] = any[]>
        extends CallbackFunction<R, P>
    {
        readonly pointer: bigint;
    }
    type CallbackFunctionFromSignature<T extends FunctionSignature> = CallbackFunction<
        ReturnTypeFromFunctionSignature<T>,
        ArgumentTypesFromFunctionSignature<T>
    >;
    type WrappedFunctionFromSignature<T extends FunctionSignature> = WrappedFunction<
        ReturnTypeFromFunctionSignature<T>,
        ArgumentTypesFromFunctionSignature<T>
    >;
    type WrappedFunctionsFromDefinitions<T extends FunctionDefinitions> = {
        [K in keyof T]: WrappedFunctionFromSignature<T[K]>;
    };
    type ReturnTypeFromFunctionSignature<T extends FunctionSignature> = "return" extends keyof T
        ? T extends { return: infer R extends ReturnType } ? R : any
        : "void";
    type ArgumentTypesFromFunctionSignature<T extends FunctionSignature> = "arguments" extends keyof T
        ? T extends { arguments: infer P extends readonly ArgumentType[] } ? P : any[]
        : [];
    interface DynamicLibraryResult<T extends FunctionDefinitions> extends Disposable {
        lib: DynamicLibrary;
        functions: WrappedFunctionsFromDefinitions<T>;
    }
    /**
     * The native shared library suffix for the current platform:
     *
     * * `'dylib'` on macOS
     * * `'so'` on Unix-like platforms
     * * `'dll'` on Windows
     *
     * This can be used to build portable library paths:
     *
     * ```js
     * const { suffix } = require('node:ffi');
     *
     * const path = `libsqlite3.${suffix}`;
     * ```
     * @since v26.1.0
     */
    const suffix: string;
    /**
     * Loads a dynamic library and resolves the requested function definitions.
     *
     * On Windows passing `null` is not supported.
     *
     * When `definitions` is omitted, `functions` is returned as an empty object until
     * symbols are resolved explicitly.
     *
     * The returned object also implements the explicit resource management protocol,
     * so it can be used with the `using` declaration. Disposing the returned
     * object closes the library handle.
     *
     * ```js
     * import { dlopen } from 'node:ffi';
     *
     * {
     *   using handle = dlopen('./mylib.so', {
     *     add_i32: { arguments: ['i32', 'i32'], return: 'i32' },
     *   });
     *   console.log(handle.functions.add_i32(20, 22));
     * } // handle.lib.close() is invoked automatically here.
     * ```
     *
     * ```js
     * import { dlopen } from 'node:ffi';
     *
     * const { lib, functions } = dlopen('./mylib.so', {
     *   add_i32: { arguments: ['i32', 'i32'], return: 'i32' },
     *   string_length: { arguments: ['pointer'], return: 'u64' },
     * });
     *
     * console.log(functions.add_i32(20, 22));
     * ```
     * @since v26.1.0
     * @param path Path to a dynamic library, or `null` to resolve symbols
     * from the current process image.
     * @param definitions Symbol definitions to resolve immediately.
     */
    function dlopen<const T extends FunctionDefinitions = {}>(
        path: string | null,
        definitions?: T,
    ): DynamicLibraryResult<T>;
    /**
     * Closes a dynamic library.
     *
     * This is equivalent to calling `handle.close()`.
     * @since v26.1.0
     */
    function dlclose(handle: DynamicLibrary): void;
    /**
     * Resolves a symbol address from a loaded library.
     *
     * This is equivalent to calling `handle.getSymbol(symbol)`.
     * @since v26.1.0
     */
    function dlsym(handle: DynamicLibrary, symbol: string): bigint;
    /**
     * @since v26.1.0
     */
    class DynamicLibrary {
        /**
         * Loads the dynamic library without resolving any functions eagerly.
         *
         * On Windows passing `null` is not supported.
         *
         * ```js
         * const { DynamicLibrary } = require('node:ffi');
         *
         * const lib = new DynamicLibrary('./mylib.so');
         * ```
         * @param path Path to a dynamic library, or `null` to resolve symbols
         * from the current process image.
         */
        constructor(path: string | null);
        /**
         * The path used to load the library.
         */
        readonly path: string;
        /**
         * An object containing previously resolved symbol addresses as `bigint` values.
         */
        readonly symbols: { [symbol: string]: bigint };
        /**
         * Closes the library handle.
         *
         * `DynamicLibrary` implements the explicit resource management protocol, so a
         * library instance can be managed with the `using` declaration. Leaving the
         * enclosing scope invokes `library.close()` automatically.
         *
         * ```js
         * import { DynamicLibrary } from 'node:ffi';
         *
         * {
         *   using lib = new DynamicLibrary('./mylib.so');
         *   // Use `lib` here; `lib.close()` is called when the block exits.
         * }
         * ```
         *
         * Calling `library.close()` (or disposing the library) more than once is a no-op.
         *
         * After a library has been closed:
         *
         * * Resolved function wrappers become invalid.
         * * Further symbol and function resolution throws.
         * * Registered callbacks are invalidated.
         *
         * Closing a library does not make previously exported callback pointers safe to
         * reuse. Node.js does not track or revoke callback pointers that have already
         * been handed to native code.
         *
         * If native code still holds a callback pointer after `library.close()` or after
         * `library.unregisterCallback(pointer)`, invoking that pointer has undefined
         * behavior, is not allowed, and is dangerous: it can crash the process, produce
         * incorrect output, or corrupt memory. Native code must stop using callback
         * addresses before the library is closed or before the callback is unregistered.
         *
         * Calling `library.close()` from one of the library's active callbacks is
         * unsupported and dangerous. The callback must return before the library is
         * closed.
         */
        close(): void;
        /**
         * Calls `library.close()`. This allows `DynamicLibrary` instances to be used with
         * the `using` declaration for automatic cleanup when the enclosing scope
         * exits. It is a no-op on a library that has already been closed.
         * @since v26.1.0
         */
        [Symbol.dispose](): void;
        /**
         * Resolves a symbol and returns a callable JavaScript wrapper.
         *
         * The returned function has a `.pointer` property containing the native function
         * address as a `bigint`.
         *
         * If the same symbol has already been resolved, requesting it again with a
         * different signature throws.
         *
         * ```js
         * const { DynamicLibrary } = require('node:ffi');
         *
         * const lib = new DynamicLibrary('./mylib.so');
         * const add = lib.getFunction('add_i32', {
         *   arguments: ['i32', 'i32'],
         *   return: 'i32',
         * });
         *
         * console.log(add(20, 22));
         * console.log(add.pointer);
         * ```
         */
        getFunction<const T extends FunctionSignature>(name: string, signature: T): WrappedFunctionFromSignature<T>;
        /**
         * When `definitions` is provided, resolves each named symbol and returns an
         * object containing callable wrappers.
         *
         * When `definitions` is omitted, returns wrappers for all functions that have
         * already been resolved on the library.
         */
        getFunctions(): { [symbol: string]: WrappedFunction };
        getFunctions<const T extends FunctionDefinitions>(definitions: T): WrappedFunctionsFromDefinitions<T>;
        /**
         * Resolves a symbol and returns its native address as a `bigint`.
         */
        getSymbol(name: string): bigint;
        /**
         * Returns an object containing all previously resolved symbol addresses.
         */
        getSymbols(): Record<string, bigint>;
        /**
         * Creates a native callback pointer backed by a JavaScript function.
         *
         * When `signature` is omitted, the callback uses a default `void ()` signature.
         *
         * The return value is the callback pointer address as a `bigint`. It can be
         * passed to native functions expecting a callback pointer.
         *
         * ```js
         * const { DynamicLibrary } = require('node:ffi');
         *
         * const lib = new DynamicLibrary('./mylib.so');
         *
         * const callback = lib.registerCallback(
         *   { arguments: ['i32'], return: 'i32' },
         *   (value) => value * 2,
         * );
         * ```
         *
         * Callbacks are subject to the following restrictions:
         *
         * * They must be invoked on the same system thread where they were created.
         * * They must not throw exceptions.
         * * They must not return promises.
         * * They must return a value compatible with the declared return type.
         * * They must not call `library.close()` on their owning library while running.
         * * They must not unregister themselves while running.
         *
         * Closing the owning library or unregistering the currently executing callback
         * from inside the callback is unsupported and dangerous. Doing so may crash the
         * process, produce incorrect output, or corrupt memory.
         */
        registerCallback(callback: () => void): bigint;
        registerCallback<const T extends FunctionSignature>(
            signature: T,
            callback: CallbackFunctionFromSignature<T>,
        ): bigint;
        /**
         * Releases a callback previously created with `library.registerCallback()`.
         *
         * Calling `library.unregisterCallback(pointer)` for a callback that is currently
         * executing is unsupported and dangerous. The callback must return before it is
         * unregistered.
         *
         * After `library.unregisterCallback(pointer)` returns, invoking that callback
         * pointer from native code has undefined behavior, is not allowed, and is
         * dangerous: it can crash the process, produce incorrect output, or corrupt
         * memory.
         */
        unregisterCallback(pointer: bigint): void;
        /**
         * Keeps the callback strongly referenced by JavaScript.
         */
        refCallback(pointer: bigint): void;
        /**
         * Allows the callback to become weakly referenced by JavaScript.
         *
         * If the callback function is later garbage collected, subsequent native
         * invocations become a no-op. Non-void return values are zero-initialized before
         * returning to native code.
         */
        unrefCallback(pointer: bigint): void;
    }
    function getInt8(pointer: bigint, offset?: number): number;
    function getUint8(pointer: bigint, offset?: number): number;
    function getInt16(pointer: bigint, offset?: number): number;
    function getUint16(pointer: bigint, offset?: number): number;
    function getInt32(pointer: bigint, offset?: number): number;
    function getUint32(pointer: bigint, offset?: number): number;
    function getInt64(pointer: bigint, offset?: number): bigint;
    function getUint64(pointer: bigint, offset?: number): bigint;
    function getFloat32(pointer: bigint, offset?: number): number;
    function getFloat64(pointer: bigint, offset?: number): number;
    function setInt8(pointer: bigint, offset: number, value: number): void;
    function setUint8(pointer: bigint, offset: number, value: number): void;
    function setInt16(pointer: bigint, offset: number, value: number): void;
    function setUint16(pointer: bigint, offset: number, value: number): void;
    function setInt32(pointer: bigint, offset: number, value: number): void;
    function setUint32(pointer: bigint, offset: number, value: number): void;
    function setInt64(pointer: bigint, offset: number, value: number | bigint): void;
    function setUint64(pointer: bigint, offset: number, value: number | bigint): void;
    function setFloat32(pointer: bigint, offset: number, value: number): void;
    function setFloat64(pointer: bigint, offset: number, value: number): void;
    /**
     * Reads a NUL-terminated UTF-8 string from native memory.
     *
     * If `pointer` is `0n`, `null` is returned.
     *
     * This function does not validate that `pointer` refers to readable memory or
     * that the pointed-to data is terminated with `\0`. Passing an invalid pointer,
     * a pointer to freed memory, or a pointer to bytes without a terminating NUL can
     * read unrelated memory, crash the process, or produce truncated or garbled
     * output.
     * @since v26.1.0
     */
    function toString(pointer: bigint): string | null;
    /**
     * Creates a `Buffer` from native memory.
     *
     * When `copy` is `true`, the returned `Buffer` owns its own copied memory.
     * When `copy` is `false`, the returned `Buffer` references the original native
     * memory directly.
     *
     * Using `copy: false` is a zero-copy escape hatch. The returned `Buffer` is a
     * writable view onto foreign memory, so writes in JavaScript update the original
     * native memory directly. The caller must guarantee that:
     *
     * * `pointer` remains valid for the entire lifetime of the returned `Buffer`.
     * * `length` stays within the allocated native region.
     * * no native code frees or repurposes that memory while JavaScript still uses
     *   the `Buffer`.
     * * Memory protection is observed. For example, read-only memory pages must not
     *   be written to.
     *
     * If these guarantees are not met, reading or writing the `Buffer` can corrupt
     * memory or crash the process.
     * @since v26.1.0
     * @param copy When `false`, creates a zero-copy view. **Default:** `true`.
     */
    function toBuffer(pointer: bigint, length: number, copy?: boolean): NonSharedBuffer;
    /**
     * Creates an `ArrayBuffer` from native memory.
     *
     * When `copy` is `true`, the returned `ArrayBuffer` contains copied bytes.
     * When `copy` is `false`, the returned `ArrayBuffer` references the original
     * native memory directly.
     *
     * The same lifetime and bounds requirements described for
     * `ffi.toBuffer(pointer, length, copy)` apply
     * here. With `copy: false`, the
     * returned `ArrayBuffer` is a zero-copy view of foreign memory and is only safe
     * while that memory remains allocated, unchanged in layout, and valid for the
     * entire exposed range.
     * @since v26.1.0
     * @param copy When `false`, creates a zero-copy view. **Default:** `true`.
     */
    function toArrayBuffer(pointer: bigint, length: number, copy?: boolean): ArrayBuffer;
    /**
     * Copies a JavaScript string into native memory and appends a trailing NUL
     * terminator.
     *
     * `length` must be large enough to hold the full encoded string plus the trailing
     * NUL terminator. For UTF-16 and UCS-2 encodings, the trailing terminator uses
     * two zero bytes.
     *
     * `pointer` must refer to writable native memory with at least `length` bytes of
     * available storage. This function does not allocate memory on its own.
     *
     * `string` must be a JavaScript string. `encoding` must be a string.
     * @since v26.1.0
     * @param encoding **Default:** `'utf8'`.
     */
    function exportString(string: string, pointer: bigint, length: number, encoding?: BufferEncoding): void;
    /**
     * Copies bytes from a `Buffer` into native memory.
     *
     * `length` must be at least `buffer.length`.
     *
     * `pointer` must refer to writable native memory with at least `length` bytes of
     * available storage. This function does not allocate memory on its own.
     *
     * `buffer` must be a Node.js `Buffer`.
     * @since v26.1.0
     */
    function exportBuffer(buffer: Buffer, pointer: bigint, length: number): void;
    /**
     * Copies bytes from an `ArrayBuffer` into native memory.
     *
     * `length` must be at least `arrayBuffer.byteLength`.
     *
     * `pointer` must refer to writable native memory with at least `length` bytes of
     * available storage. This function does not allocate memory on its own.
     * @since v26.1.0
     */
    function exportArrayBuffer(arrayBuffer: ArrayBuffer, pointer: bigint, length: number): void;
    /**
     * Copies bytes from an `ArrayBufferView` into native memory.
     *
     * `length` must be at least `arrayBufferView.byteLength`.
     *
     * `pointer` must refer to writable native memory with at least `length` bytes of
     * available storage. This function does not allocate memory on its own.
     * @since v26.1.0
     */
    function exportArrayBufferView(arrayBufferView: NodeJS.ArrayBufferView, pointer: bigint, length: number): void;
    /**
     * Returns the raw memory address of JavaScript-managed byte storage.
     *
     * This is unsafe and dangerous. The returned pointer can become invalid if the
     * underlying memory is detached, resized, transferred, or otherwise invalidated.
     * Using stale pointers can cause memory corruption or process crashes.
     * @since v26.1.0
     */
    function getRawPointer(source: ArrayBuffer | NodeJS.ArrayBufferView): bigint;
    type ReturnType = { [K in keyof DataTypeMap]: K }[keyof DataTypeMap];
    type ArgumentType = Exclude<ReturnType, "void">;
    interface DataTypeMap {
        void: "void";
        char: "number";
        bool: "number";
        i8: "number";
        int8: "number";
        u8: "number";
        uint8: "number";
        i16: "number";
        int16: "number";
        u16: "number";
        uint16: "number";
        i32: "number";
        int32: "number";
        u32: "number";
        uint32: "number";
        i64: "bigint";
        int64: "bigint";
        u64: "bigint";
        uint64: "bigint";
        float: "number";
        f32: "number";
        double: "number";
        f64: "number";
        pointer: "pointer";
        ptr: "pointer";
        function: "pointer";
        buffer: "pointer";
        arraybuffer: "pointer";
        string: "pointer";
        str: "pointer";
    }
    interface ArgumentTypeMap {
        "number": number;
        "bigint": bigint;
        "pointer": bigint | string | ArrayBuffer | NodeJS.ArrayBufferView | null;
    }
    interface ReturnTypeMap {
        // eslint-disable-next-line @typescript-eslint/no-invalid-void-type
        "void": void;
        "number": number;
        "bigint": bigint;
        "pointer": bigint;
    }
    enum types {
        VOID = "void",
        POINTER = "pointer",
        BUFFER = "buffer",
        ARRAY_BUFFER = "arraybuffer",
        FUNCTION = "function",
        BOOL = "bool",
        CHAR = "char",
        STRING = "string",
        FLOAT = "float",
        DOUBLE = "double",
        INT_8 = "int8",
        UINT_8 = "uint8",
        INT_16 = "int16",
        UINT_16 = "uint16",
        INT_32 = "int32",
        UINT_32 = "uint32",
        INT_64 = "int64",
        UINT_64 = "uint64",
        FLOAT_32 = "float32",
        FLOAT_64 = "float64",
    }
}
