diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0dc7b4b --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/.vscode \ No newline at end of file diff --git a/types/ffi/mod.ts b/types/ffi/mod.ts new file mode 100644 index 0000000..2cb8ffd --- /dev/null +++ b/types/ffi/mod.ts @@ -0,0 +1,3 @@ +export * from "./pointer_value.ts"; +export * from "./pointer_view.ts"; +export * from "./pointer.ts"; diff --git a/types/ffi/pointer.ts b/types/ffi/pointer.ts new file mode 100644 index 0000000..ba73d20 --- /dev/null +++ b/types/ffi/pointer.ts @@ -0,0 +1,38 @@ +import type { AlignedType, SizedType } from "../types.ts"; +import { pointerView } from "./pointer_view.ts"; + +export class Pointer implements AlignedType { + byteLength: number; + byteAlign: number; + type: SizedType; + pointerType: AlignedType; + + constructor( + type: SizedType, + pointerType: AlignedType = pointerView, + ) { + this.byteAlign = pointerType.byteAlign; + this.byteLength = pointerType.byteLength; + this.type = type; + this.pointerType = pointerType; + } + + read(dataView: DataView, byteOffset = 0): T { + return this.type.read( + new DataView( + this.pointerType.read(dataView, byteOffset).getArrayBuffer( + this.type.byteLength, + ), + ), + ); + } + + write(value: T, dataView: DataView, byteOffset = 0) { + const buffer = new ArrayBuffer(this.type.byteLength); + this.type.write(value, new DataView(buffer)); + const pointerView = new Deno.UnsafePointerView( + Deno.UnsafePointer.of(buffer)!, + ); + this.pointerType.write(pointerView, dataView, byteOffset); + } +} diff --git a/types/ffi/pointer_value.ts b/types/ffi/pointer_value.ts new file mode 100644 index 0000000..d15c0fa --- /dev/null +++ b/types/ffi/pointer_value.ts @@ -0,0 +1,32 @@ +import type { AlignedType } from "../types.ts"; +import { u64 } from "../mod.ts"; + +export class PointerValue implements AlignedType { + byteLength: number; + byteAlign: number; + pointerType: AlignedType; + + constructor( + pointerType: AlignedType = u64, + ) { + this.byteAlign = pointerType.byteAlign; + this.byteLength = pointerType.byteLength; + this.pointerType = pointerType; + } + + read(dataView: DataView, byteOffset = 0): Deno.PointerValue { + return Deno.UnsafePointer.create( + this.pointerType.read(dataView, byteOffset), + ); + } + + write(value: Deno.PointerValue, dataView: DataView, byteOffset = 0) { + this.pointerType.write( + Deno.UnsafePointer.value(value), + dataView, + byteOffset, + ); + } +} + +export const pointerValue = new PointerValue(); diff --git a/types/ffi/pointer_view.ts b/types/ffi/pointer_view.ts new file mode 100644 index 0000000..e0bdfe3 --- /dev/null +++ b/types/ffi/pointer_view.ts @@ -0,0 +1,28 @@ +import type { AlignedType } from "../types.ts"; +import { pointerValue } from "./pointer_value.ts"; + +export class PointerView implements AlignedType { + byteLength: number; + byteAlign: number; + pointerType: AlignedType; + + constructor( + pointerType: AlignedType = pointerValue, + ) { + this.byteAlign = pointerType.byteAlign; + this.byteLength = pointerType.byteLength; + this.pointerType = pointerType; + } + + read(dataView: DataView, byteOffset = 0): Deno.UnsafePointerView { + return new Deno.UnsafePointerView( + this.pointerType.read(dataView, byteOffset)!, + ); + } + + write(value: Deno.UnsafePointerView, dataView: DataView, byteOffset = 0) { + this.pointerType.write(value.pointer, dataView, byteOffset); + } +} + +export const pointerView = new PointerView();