Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Get Arguments Directly From Pointers #17

Merged
merged 7 commits into from
Jan 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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)));
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This isn't quite correct. I think initArgument should return a pointer to a memory of the size of the interface (if given an interface) and not initialise a new object. Please advise!

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not entirely sure about that. If you managed to do it the better way, introduce it in a new PR.

};

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),
vixalien marked this conversation as resolved.
Show resolved Hide resolved
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