feat(ext/ffi): infer symbol types (#13221)

Co-authored-by: sinclairzx81 <sinclairzx81@users.noreply.github.com>
This commit is contained in:
Divy Srivastava 2022-01-10 21:03:25 +05:30 committed by GitHub
parent 994ac6d49b
commit d8e96d2742
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 195 additions and 10 deletions

View file

@ -121,13 +121,60 @@ declare namespace Deno {
| "pointer";
/** A foreign function as defined by its parameter and result types */
export interface ForeignFunction {
parameters: NativeType[];
result: NativeType;
export interface ForeignFunction<
Parameters extends readonly NativeType[] = readonly NativeType[],
Result extends NativeType = NativeType,
NonBlocking extends boolean = boolean,
> {
parameters: Parameters;
result: Result;
/** When true, function calls will run on a dedicated blocking thread and will return a Promise resolving to the `result`. */
nonblocking?: boolean;
nonblocking?: NonBlocking;
}
/** A foreign function interface descriptor */
export interface ForeignFunctionInterface {
[name: string]: ForeignFunction;
}
/** All possible number types interfacing with foreign functions */
type StaticNativeNumberType = Exclude<NativeType, "void" | "pointer">;
/** Infers a foreign function return type */
type StaticForeignFunctionResult<T extends NativeType> = T extends "void"
? void
: T extends StaticNativeNumberType ? number
: T extends "pointer" ? UnsafePointer
: never;
type StaticForeignFunctionParameter<T> = T extends "void" ? void
: T extends StaticNativeNumberType ? number
: T extends "pointer" ? Deno.UnsafePointer | Deno.TypedArray
: unknown;
/** Infers a foreign function parameter list. */
type StaticForeignFunctionParameters<T extends readonly NativeType[]> = [
...{
[K in keyof T]: StaticForeignFunctionParameter<T[K]>;
},
];
/** Infers a foreign function */
type StaticForeignFunction<T extends ForeignFunction> = (
...args: StaticForeignFunctionParameters<T["parameters"]>
) => ConditionalAsync<
T["nonblocking"],
StaticForeignFunctionResult<T["result"]>
>;
type ConditionalAsync<IsAsync extends boolean | undefined, T> =
IsAsync extends true ? Promise<T> : T;
/** Infers a foreign function interface */
type StaticForeignFunctionInterface<T extends ForeignFunctionInterface> = {
[K in keyof T]: StaticForeignFunction<T[K]>;
};
type TypedArray =
| Int8Array
| Uint8Array
@ -202,10 +249,9 @@ declare namespace Deno {
}
/** A dynamic library resource */
export interface DynamicLibrary<S extends Record<string, ForeignFunction>> {
export interface DynamicLibrary<S extends ForeignFunctionInterface> {
/** All of the registered symbols along with functions for calling them */
symbols: { [K in keyof S]: (...args: unknown[]) => unknown };
symbols: StaticForeignFunctionInterface<S>;
close(): void;
}
@ -213,7 +259,7 @@ declare namespace Deno {
*
* Opens a dynamic library and registers symbols
*/
export function dlopen<S extends Record<string, ForeignFunction>>(
export function dlopen<S extends ForeignFunctionInterface>(
filename: string | URL,
symbols: S,
): DynamicLibrary<S>;