Skip to content

Commit

Permalink
Merge pull request #17 from vixalien/arguments
Browse files Browse the repository at this point in the history
Get Arguments Directly From Pointers
  • Loading branch information
ahgilak authored Jan 6, 2024
2 parents 69689bd + 3ea55c2 commit 97f83b8
Show file tree
Hide file tree
Showing 12 changed files with 77 additions and 89 deletions.
47 changes: 16 additions & 31 deletions src/types/argument.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,59 +24,44 @@ export function initArgument(type) {
g.base_info.unref(info);
return result;
}
default:
return 0n;
}
}

/**
/** This function is given a pointer OR a value, and must hence extract it
* @param {Deno.PointerObject} type
* @param {ArrayBufferLike} value
* @param {number | bigint} pointer
* @returns
*/
export function unboxArgument(type, value) {
const dataView = new ExtendedDataView(value);
export function unboxArgument(type, pointer) {
const tag = g.type_info.get_tag(type);
const pointer = dataView.getBigUint64();

switch (tag) {
case GITypeTag.VOID:
return;

case GITypeTag.UNICHAR:
return String.fromCharCode(dataView.getUint8());
// TODO: this code is very verbose, and might be uneeded
return String.fromCharCode(Number(BigInt.asIntN(8, BigInt(pointer))));

case GITypeTag.BOOLEAN:
return Boolean(dataView.getInt32());
return Boolean(pointer);

case GITypeTag.UINT8:
return dataView.getUint8();

case GITypeTag.INT8:
return dataView.getInt8();

case GITypeTag.UINT16:
return dataView.getUint16();

case GITypeTag.INT16:
return dataView.getInt16();

case GITypeTag.UINT32:
return dataView.getUint32();

case GITypeTag.INT32:
return dataView.getInt32();

case GITypeTag.FLOAT:
return Number(pointer);

case GITypeTag.UINT64:
return dataView.getBigUint64();

case GITypeTag.INT64:
return dataView.getBigInt64();

case GITypeTag.FLOAT:
return dataView.getFloat32();

case GITypeTag.DOUBLE:
return dataView.getFloat64();

return BigInt(pointer);
case GITypeTag.UTF8:
case GITypeTag.FILENAME: {
if (!pointer) {
Expand All @@ -89,12 +74,12 @@ export function unboxArgument(type, value) {
/* non-basic types */

case GITypeTag.ARRAY: {
return unboxArray(type, value, -1);
return unboxArray(type, pointer, -1);
}

case GITypeTag.GLIST:
case GITypeTag.GSLIST: {
return unboxList(type, value)
return unboxList(type, pointer);
}

case GITypeTag.INTERFACE: {
Expand All @@ -103,7 +88,7 @@ export function unboxArgument(type, value) {
}

const info = g.type_info.get_interface(type);
const result = unboxInterface(info, value);
const result = unboxInterface(info, pointer);
g.base_info.unref(info);
return result;
}
Expand Down
38 changes: 15 additions & 23 deletions src/types/argument/array.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { cast_u64_ptr, deref_buf } from "../../base_utils/convert.ts";
import { GITypeTag } from "../../bindings/enums.js";
import g from "../../bindings/mod.js";
import { ExtendedDataView } from "../../utils/dataview.js";
import { boxArgument, unboxArgument } from "../argument.js";
import { boxArgument } from "../argument.js";

function getTypeSize(typeTag) {
switch (typeTag) {
Expand Down Expand Up @@ -36,10 +36,12 @@ function getTypeSize(typeTag) {
}
}

export function unboxArray(type, value, length) {
const isZeroTerminated = length === -1;
const pointer = cast_u64_ptr(new ExtendedDataView(value).getBigUint64());
function getPointerUint8(pointer, offset) {
return new ExtendedDataView(deref_buf(cast_u64_ptr(pointer), 8, offset))
.getUint8();
}

export function unboxArray(type, pointer, length) {
if (!pointer) {
return null;
}
Expand All @@ -48,30 +50,20 @@ export function unboxArray(type, value, length) {
const paramTypeTag = g.type_info.get_tag(paramType);
const paramSize = getTypeSize(paramTypeTag);

if (isZeroTerminated) {
const result = [];
for (
let i = 0;
new ExtendedDataView(deref_buf(pointer, 1, i * paramSize))
.getUint8() !== 0;
i++
) {
result.push(
unboxArgument(
paramType,
deref_buf(pointer, paramSize, i * paramSize),
),
);
}
let buffer;

g.base_info.unref(paramType);
if (length === -1) {
let i = 0;
while (getPointerUint8(pointer, i * paramSize) !== 0) {
i++;
}

return result;
buffer = deref_buf(cast_u64_ptr(pointer), i * paramSize);
} else {
buffer = deref_buf(pointer, length);
}

const buffer = deref_buf(pointer, length);
const tag = g.type_info.get_tag(paramType);

g.base_info.unref(paramType);

switch (tag) {
Expand Down
9 changes: 6 additions & 3 deletions src/types/argument/interface.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@ export function boxInterface(info, value) {
case GIInfoType.OBJECT:
case GIInfoType.INTERFACE:
case GIInfoType.STRUCT:
return cast_ptr_u64(Reflect.getOwnMetadata("gi:ref", value));
return value
? cast_ptr_u64(Reflect.getOwnMetadata("gi:ref", value))
: null;
case GIInfoType.ENUM:
case GIInfoType.FLAGS:
return value;
Expand All @@ -32,8 +34,9 @@ export function boxInterface(info, value) {

export function unboxInterface(
info,
argValue,
pointer,
) {
const argValue = deref_buf(cast_u64_ptr(pointer), 8);
const dataView = new ExtendedDataView(argValue);
const type = g.base_info.get_type(info);
let gType = g.registered_type_info.get_g_type(info);
Expand All @@ -55,7 +58,7 @@ export function unboxInterface(
const result = Object.create(objectByGType(gType).prototype);
Reflect.defineMetadata(
"gi:ref",
cast_u64_ptr(dataView.getBigUint64()),
cast_u64_ptr(pointer),
result,
);
return result;
Expand Down
21 changes: 12 additions & 9 deletions src/types/argument/list.js
Original file line number Diff line number Diff line change
@@ -1,24 +1,27 @@
import { cast_u64_ptr, deref_buf } from "../../base_utils/convert.ts";
import g from "../../bindings/girepository.js";
import { ExtendedDataView } from "../../utils/dataview.js";
import { unboxArgument } from "../argument.js";

function getPointerUint64(pointer, offset) {
return new ExtendedDataView(deref_buf(cast_u64_ptr(pointer), 8, offset))
.getBigUint64();
}

/**
* @param {Deno.PointerValue} info
* @param {ArrayBufferLike} list
* @returns
*/
export function unboxList(info, list) {
export function unboxList(info, pointer) {
const paramType = g.type_info.get_param_type(info, 0);
const result = [];

while (true) {
const [dataPointer, nextPointer] = new BigUint64Array(list);
const data = deref_buf(cast_u64_ptr(dataPointer), 8);
result.push(unboxArgument(paramType, data));

if (!nextPointer) break;

list = deref_buf(cast_u64_ptr(nextPointer), 8);
let i = 0;
while (getPointerUint64(pointer, i * 8) !== 0) {
const value = getPointerUint64(pointer, i * 8);
result.push(unboxArgument(paramType, value));
i++;
}

g.base_info.unref(paramType);
Expand Down
17 changes: 11 additions & 6 deletions src/types/callable.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,15 @@ export function createArg(info) {
const transfer = g.arg_info.get_ownership_transfer(info);
const callerAllocates = g.arg_info.is_caller_allocates(info);
const isReturn = g.arg_info.is_return_value(info);
return { type, arrLength, isSkip, direction, transfer, callerAllocates, isReturn };
return {
type,
arrLength,
isSkip,
direction,
transfer,
callerAllocates,
isReturn,
};
}

export function parseCallableArgs(info) {
Expand All @@ -39,7 +47,6 @@ export function parseCallableArgs(info) {
(arg) => !(arg.direction & GIDirection.OUT),
);


const outArgsDetail = argDetails.filter(
(arg) => arg.direction & GIDirection.OUT,
);
Expand All @@ -62,14 +69,12 @@ export function parseCallableArgs(info) {
};

const initOutArgs = () => {
const outArgs = outArgsDetail.map((d) => initArgument(d.type));

return outArgs;
return new BigUint64Array(outArgsDetail.map((d) => initArgument(d.type)));
};

const parseOutArgs = (outArgs) => {
return outArgsDetail.map((d, i) => {
return unboxArgument(d.type, new BigUint64Array([outArgs[i]]).buffer);
return unboxArgument(d.type, outArgs[i]);
});
};

Expand Down
6 changes: 3 additions & 3 deletions src/types/callable/function.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,13 @@ export function createFunction(info) {
const outArgs = initOutArgs();

const error = new BigUint64Array(1);
const returnValue = new ArrayBuffer(8);
const returnValue = new BigUint64Array(1);

const success = g.function_info.invoke(
info,
new BigUint64Array(inArgs),
inArgs.length,
new BigUint64Array(outArgs),
outArgs,
outArgs.length,
returnValue,
error,
Expand All @@ -33,7 +33,7 @@ export function createFunction(info) {
throw createGError(error[0]);
}

const retVal = unboxArgument(returnType, returnValue);
const retVal = unboxArgument(returnType, returnValue[0]);

if (outArgs.length > 0) {
const parsedOutArgs = parseOutArgs(outArgs);
Expand Down
6 changes: 3 additions & 3 deletions src/types/callable/method.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,13 @@ export function createMethod(info) {
inArgs.unshift(cast_ptr_u64(caller));

const error = new BigUint64Array(1);
const returnValue = new ArrayBuffer(8);
const returnValue = new BigUint64Array(1);

const success = g.function_info.invoke(
info,
new BigUint64Array(inArgs),
inArgs.length,
new BigUint64Array(outArgs),
outArgs,
outArgs.length,
returnValue,
error,
Expand All @@ -36,7 +36,7 @@ export function createMethod(info) {
throw createGError(error[0]);
}

const retVal = unboxArgument(returnType, returnValue);
const retVal = unboxArgument(returnType, returnValue[0]);

if (outArgs.length > 0) {
return [retVal, ...parseOutArgs(outArgs)];
Expand Down
6 changes: 3 additions & 3 deletions src/types/callable/vfunc.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,14 @@ export function createVFunc(info) {
inArgs.unshift(cast_ptr_u64(caller));

const error = new BigUint64Array(1);
const returnValue = new ArrayBuffer(8);
const returnValue = new BigUint64Array(1);

const success = g.vfunc_info.invoke(
info,
implimentor,
new BigUint64Array(inArgs),
inArgs.length,
new BigUint64Array(outArgs),
outArgs,
outArgs.length,
returnValue,
error,
Expand All @@ -37,7 +37,7 @@ export function createVFunc(info) {
throw createGError(error[0]);
}

const retVal = unboxArgument(returnType, returnValue);
const retVal = unboxArgument(returnType, returnValue[0]);

if (outArgs.length > 0) {
return [retVal, ...parseOutArgs(outArgs)];
Expand Down
6 changes: 3 additions & 3 deletions src/types/callback.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import g from "../bindings/mod.js";
import { GITypeTag } from "../bindings/enums.js";
import { boxArgument, unboxArgument } from "./argument.js";
import { cast_ptr_u64, ref_buf } from "../base_utils/convert.ts";
import { cast_ptr_u64 } from "../base_utils/convert.ts";
import { createArg } from "./callable.js";

const nativeTypes = {
Expand Down Expand Up @@ -34,7 +34,7 @@ function parseArgs(

const result = nativeTypes[tag]
? value
: unboxArgument(argType, ref_buf(cast_ptr_u64(value)).buffer);
: unboxArgument(argType, cast_ptr_u64(value));

g.base_info.unref(argInfo);
g.base_info.unref(argType);
Expand Down Expand Up @@ -64,7 +64,7 @@ export function createCallback(
}

return new Deno.UnsafeCallback(
{ parameters, result: "buffer" },
{ parameters, result: ffiType(g.type_info.get_tag(returnType)) },
caller
? (_, ...args) =>
boxArgument(returnType, callback(caller, ...parseArgs(info, args)))
Expand Down
2 changes: 1 addition & 1 deletion src/types/constant.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export function createConstant(info) {
return null;
}

const result = unboxArgument(giType, giValue.buffer);
const result = unboxArgument(giType, giValue[0]);
g.base_info.unref(giType);

return result;
Expand Down
Loading

0 comments on commit 97f83b8

Please sign in to comment.