node-ctypes 0.1.3 → 0.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +49 -27
- package/build/Release/ctypes-darwin-arm64.node +0 -0
- package/build/Release/ctypes-linux-arm64.node +0 -0
- package/build/Release/ctypes-linux-x64.node +0 -0
- package/build/Release/ctypes-win32-arm64.node +0 -0
- package/build/Release/ctypes-win32-x64.node +0 -0
- package/lib/index.d.ts +24 -127
- package/lib/index.js +239 -421
- package/package.json +1 -1
package/lib/index.js
CHANGED
|
@@ -23,12 +23,7 @@ const getNativeModulePath = (moduleName, nativeFile, config = "Release") => {
|
|
|
23
23
|
if (process.versions?.electron) {
|
|
24
24
|
const electronProcess = process;
|
|
25
25
|
if (electronProcess.resourcesPath) {
|
|
26
|
-
const unpackedPath = path.join(
|
|
27
|
-
electronProcess.resourcesPath,
|
|
28
|
-
"app.asar.unpacked",
|
|
29
|
-
"node_modules",
|
|
30
|
-
moduleName,
|
|
31
|
-
);
|
|
26
|
+
const unpackedPath = path.join(electronProcess.resourcesPath, "app.asar.unpacked", "node_modules", moduleName);
|
|
32
27
|
if (existsSync(buildPath(unpackedPath))) {
|
|
33
28
|
return buildPath(unpackedPath);
|
|
34
29
|
}
|
|
@@ -36,9 +31,7 @@ const getNativeModulePath = (moduleName, nativeFile, config = "Release") => {
|
|
|
36
31
|
}
|
|
37
32
|
|
|
38
33
|
// Check in current working directory's node_modules
|
|
39
|
-
const cwdPath = buildPath(
|
|
40
|
-
path.join(process.cwd(), "node_modules", moduleName),
|
|
41
|
-
);
|
|
34
|
+
const cwdPath = buildPath(path.join(process.cwd(), "node_modules", moduleName));
|
|
42
35
|
if (existsSync(cwdPath)) {
|
|
43
36
|
return cwdPath;
|
|
44
37
|
}
|
|
@@ -58,10 +51,7 @@ const getNativeModulePath = (moduleName, nativeFile, config = "Release") => {
|
|
|
58
51
|
}
|
|
59
52
|
}
|
|
60
53
|
|
|
61
|
-
throw new Error(
|
|
62
|
-
`Native module "${nativeFile}" not found for "${moduleName}". ` +
|
|
63
|
-
`Searched in Electron resources, node_modules, and local build.`,
|
|
64
|
-
);
|
|
54
|
+
throw new Error(`Native module "${nativeFile}" not found for "${moduleName}". ` + `Searched in Electron resources, node_modules, and local build.`);
|
|
65
55
|
};
|
|
66
56
|
|
|
67
57
|
// Load the native module
|
|
@@ -71,25 +61,13 @@ try {
|
|
|
71
61
|
} catch (e) {
|
|
72
62
|
const platform = process.platform;
|
|
73
63
|
const arch = process.arch;
|
|
74
|
-
nativeModulePath = getNativeModulePath(
|
|
75
|
-
"node-ctypes",
|
|
76
|
-
`ctypes-${platform}-${arch}.node`,
|
|
77
|
-
);
|
|
64
|
+
nativeModulePath = getNativeModulePath("node-ctypes", `ctypes-${platform}-${arch}.node`);
|
|
78
65
|
}
|
|
79
66
|
const require = createRequire(path.join(process.cwd(), "index.js"));
|
|
80
67
|
const native = require(nativeModulePath);
|
|
81
68
|
|
|
82
69
|
// Re-esporta le classi native
|
|
83
|
-
const {
|
|
84
|
-
Version,
|
|
85
|
-
Library,
|
|
86
|
-
FFIFunction,
|
|
87
|
-
Callback,
|
|
88
|
-
ThreadSafeCallback,
|
|
89
|
-
CType,
|
|
90
|
-
StructType,
|
|
91
|
-
ArrayType,
|
|
92
|
-
} = native;
|
|
70
|
+
const { Version, Library, FFIFunction, Callback, ThreadSafeCallback, CType, StructType, ArrayType } = native;
|
|
93
71
|
|
|
94
72
|
// Tipi predefiniti
|
|
95
73
|
const types = native.types;
|
|
@@ -112,10 +90,7 @@ function _toNativeType(type) {
|
|
|
112
90
|
return type._type;
|
|
113
91
|
}
|
|
114
92
|
// Struct/Union classes pass through
|
|
115
|
-
if (
|
|
116
|
-
typeof type === "function" &&
|
|
117
|
-
(type.prototype instanceof Structure || type.prototype instanceof Union)
|
|
118
|
-
) {
|
|
93
|
+
if (typeof type === "function" && (type.prototype instanceof Structure || type.prototype instanceof Union)) {
|
|
119
94
|
return type;
|
|
120
95
|
}
|
|
121
96
|
// Native CType objects pass through
|
|
@@ -132,18 +107,6 @@ function _toNativeTypes(types) {
|
|
|
132
107
|
return types.map(_toNativeType);
|
|
133
108
|
}
|
|
134
109
|
|
|
135
|
-
// ============================================================================
|
|
136
|
-
// Type Lookup Tables
|
|
137
|
-
// Centralizes type information to avoid duplicated switch statements
|
|
138
|
-
// ============================================================================
|
|
139
|
-
|
|
140
|
-
// TYPE_READERS removed - using SimpleCData._reader directly
|
|
141
|
-
|
|
142
|
-
// TYPE_WRITERS removed - using SimpleCData._writer directly
|
|
143
|
-
|
|
144
|
-
/** @type {Map<string, number>} */
|
|
145
|
-
// TYPE_SIZES removed - using SimpleCData._size directly
|
|
146
|
-
|
|
147
110
|
/**
|
|
148
111
|
* Carica una libreria dinamica
|
|
149
112
|
* @param {string|null} libPath - Percorso della libreria o null per l'eseguibile corrente
|
|
@@ -153,6 +116,62 @@ function load(libPath) {
|
|
|
153
116
|
return new Library(libPath);
|
|
154
117
|
}
|
|
155
118
|
|
|
119
|
+
/**
|
|
120
|
+
* Wrapper per funzioni con sintassi Python-like ctypes (argtypes/restype)
|
|
121
|
+
*/
|
|
122
|
+
class FunctionWrapper {
|
|
123
|
+
constructor(cdll, name) {
|
|
124
|
+
const argtypes = [];
|
|
125
|
+
let restype = undefined;
|
|
126
|
+
let cachedFunc = null;
|
|
127
|
+
|
|
128
|
+
// Create a function and proxy it to make it callable
|
|
129
|
+
const func = (...args) => {
|
|
130
|
+
if (restype === undefined) {
|
|
131
|
+
throw new Error(`Function ${name}: restype not set`);
|
|
132
|
+
}
|
|
133
|
+
if (!cachedFunc) {
|
|
134
|
+
cachedFunc = cdll.func(name, restype, argtypes);
|
|
135
|
+
}
|
|
136
|
+
return cachedFunc(...args);
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
// Proxy the function to intercept property access
|
|
140
|
+
return new Proxy(func, {
|
|
141
|
+
get(target, prop) {
|
|
142
|
+
if (prop === "argtypes") return argtypes;
|
|
143
|
+
if (prop === "restype") return restype;
|
|
144
|
+
if (prop === "errcheck") return cachedFunc ? cachedFunc.errcheck : undefined;
|
|
145
|
+
return target[prop];
|
|
146
|
+
},
|
|
147
|
+
set(target, prop, value) {
|
|
148
|
+
if (prop === "argtypes") {
|
|
149
|
+
argtypes.splice(0, argtypes.length, ...value);
|
|
150
|
+
cachedFunc = null; // Invalidate cache
|
|
151
|
+
return true;
|
|
152
|
+
}
|
|
153
|
+
if (prop === "restype") {
|
|
154
|
+
restype = value;
|
|
155
|
+
cachedFunc = null; // Invalidate cache
|
|
156
|
+
return true;
|
|
157
|
+
}
|
|
158
|
+
if (prop === "errcheck") {
|
|
159
|
+
if (!cachedFunc) {
|
|
160
|
+
if (restype === undefined) {
|
|
161
|
+
throw new Error(`Function ${name}: restype not set`);
|
|
162
|
+
}
|
|
163
|
+
cachedFunc = cdll.func(name, restype, argtypes);
|
|
164
|
+
}
|
|
165
|
+
cachedFunc.errcheck = value;
|
|
166
|
+
return true;
|
|
167
|
+
}
|
|
168
|
+
target[prop] = value;
|
|
169
|
+
return true;
|
|
170
|
+
},
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
156
175
|
/**
|
|
157
176
|
* Wrapper conveniente per CDLL (come in Python ctypes)
|
|
158
177
|
*/
|
|
@@ -160,6 +179,18 @@ class CDLL {
|
|
|
160
179
|
constructor(libPath) {
|
|
161
180
|
this._lib = new Library(libPath);
|
|
162
181
|
this._cache = new Map();
|
|
182
|
+
|
|
183
|
+
// Return a proxy to enable Python-like syntax: libc.abs.argtypes = [...]; libc.abs.restype = ...; libc.abs(...)
|
|
184
|
+
return new Proxy(this, {
|
|
185
|
+
get(target, prop, receiver) {
|
|
186
|
+
// Allow access to existing properties/methods
|
|
187
|
+
if (prop in target || typeof prop !== "string") {
|
|
188
|
+
return Reflect.get(target, prop, receiver);
|
|
189
|
+
}
|
|
190
|
+
// Assume it's a function name from the library
|
|
191
|
+
return new FunctionWrapper(target, prop);
|
|
192
|
+
},
|
|
193
|
+
});
|
|
163
194
|
}
|
|
164
195
|
|
|
165
196
|
/**
|
|
@@ -177,44 +208,99 @@ class CDLL {
|
|
|
177
208
|
return this._cache.get(cacheKey);
|
|
178
209
|
}
|
|
179
210
|
|
|
180
|
-
const ffiFunc = this._lib.func(
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
211
|
+
const ffiFunc = this._lib.func(name, _toNativeType(returnType), _toNativeTypes(argTypes), options);
|
|
212
|
+
|
|
213
|
+
// =========================================================================
|
|
214
|
+
// OPTIMIZATION: Create specialized wrapper based on argument types
|
|
215
|
+
// For primitive-only args, bypass the processing loop entirely
|
|
216
|
+
// =========================================================================
|
|
217
|
+
|
|
218
|
+
const argCount = argTypes.length;
|
|
219
|
+
|
|
220
|
+
// Check if all args are primitive types (no structs/buffers that need _buffer extraction)
|
|
221
|
+
const allPrimitive = argTypes.every((t) => {
|
|
222
|
+
if (typeof t === "function" && t._isSimpleCData) {
|
|
223
|
+
// SimpleCData types that are NOT pointers are primitive
|
|
224
|
+
const typeName = t._type;
|
|
225
|
+
return typeName !== "pointer" && typeName !== "char_p" && typeName !== "wchar_p";
|
|
226
|
+
}
|
|
227
|
+
if (typeof t === "string") {
|
|
228
|
+
return t !== "pointer" && t !== "char_p" && t !== "wchar_p" && t !== "void_p";
|
|
229
|
+
}
|
|
230
|
+
// CType objects from native - check if it's a pointer type
|
|
231
|
+
if (t && typeof t === "object" && t.name) {
|
|
232
|
+
return !t.name.includes("pointer") && !t.name.includes("char_p");
|
|
233
|
+
}
|
|
234
|
+
return false;
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
let callMethod;
|
|
238
|
+
|
|
239
|
+
if (argCount === 0) {
|
|
240
|
+
// FAST PATH: No arguments - direct call
|
|
241
|
+
callMethod = function () {
|
|
242
|
+
return ffiFunc.call();
|
|
243
|
+
};
|
|
244
|
+
} else if (allPrimitive) {
|
|
245
|
+
// FAST PATH: All primitive args - direct call without processing
|
|
246
|
+
switch (argCount) {
|
|
247
|
+
case 1:
|
|
248
|
+
callMethod = function (a0) {
|
|
249
|
+
return ffiFunc.call(a0);
|
|
250
|
+
};
|
|
251
|
+
break;
|
|
252
|
+
case 2:
|
|
253
|
+
callMethod = function (a0, a1) {
|
|
254
|
+
return ffiFunc.call(a0, a1);
|
|
255
|
+
};
|
|
256
|
+
break;
|
|
257
|
+
case 3:
|
|
258
|
+
callMethod = function (a0, a1, a2) {
|
|
259
|
+
return ffiFunc.call(a0, a1, a2);
|
|
260
|
+
};
|
|
261
|
+
break;
|
|
262
|
+
case 4:
|
|
263
|
+
callMethod = function (a0, a1, a2, a3) {
|
|
264
|
+
return ffiFunc.call(a0, a1, a2, a3);
|
|
265
|
+
};
|
|
266
|
+
break;
|
|
267
|
+
default:
|
|
268
|
+
// Fallback for many args
|
|
269
|
+
callMethod = function (...args) {
|
|
270
|
+
return ffiFunc.call(...args);
|
|
271
|
+
};
|
|
272
|
+
}
|
|
273
|
+
} else {
|
|
274
|
+
// SLOW PATH: Has buffer/struct args - need to extract _buffer
|
|
275
|
+
callMethod = function (...args) {
|
|
276
|
+
const processedArgs = [];
|
|
277
|
+
|
|
278
|
+
for (let i = 0; i < args.length; i++) {
|
|
279
|
+
const arg = args[i];
|
|
280
|
+
// Check for _buffer FIRST (handles Proxy-wrapped structs)
|
|
281
|
+
// This avoids calling Buffer.isBuffer() on Proxy which can cause issues
|
|
282
|
+
if (arg && typeof arg === "object") {
|
|
283
|
+
// Check for struct proxy FIRST - accessing _buffer on Proxy is safe
|
|
284
|
+
// but Buffer.isBuffer(proxy) can cause hangs
|
|
285
|
+
if (arg._buffer !== undefined && Buffer.isBuffer(arg._buffer)) {
|
|
286
|
+
// Struct proxy or object with _buffer
|
|
287
|
+
processedArgs.push(arg._buffer);
|
|
288
|
+
} else if (Buffer.isBuffer(arg)) {
|
|
289
|
+
// Already a buffer, use directly
|
|
290
|
+
processedArgs.push(arg);
|
|
291
|
+
} else {
|
|
292
|
+
// Other object, pass as-is
|
|
293
|
+
processedArgs.push(arg);
|
|
294
|
+
}
|
|
206
295
|
} else {
|
|
207
|
-
//
|
|
296
|
+
// Primitive value (number, string, bigint, null, undefined)
|
|
208
297
|
processedArgs.push(arg);
|
|
209
298
|
}
|
|
210
|
-
} else {
|
|
211
|
-
// Primitive value (number, string, bigint, null, undefined)
|
|
212
|
-
processedArgs.push(arg);
|
|
213
299
|
}
|
|
214
|
-
}
|
|
215
300
|
|
|
216
|
-
|
|
217
|
-
|
|
301
|
+
return ffiFunc.call(...processedArgs);
|
|
302
|
+
};
|
|
303
|
+
}
|
|
218
304
|
|
|
219
305
|
// Aggiungi metadata come proprietà non-enumerable per non interferire
|
|
220
306
|
Object.defineProperties(callMethod, {
|
|
@@ -256,11 +342,7 @@ class CDLL {
|
|
|
256
342
|
* @returns {Object} Oggetto callback con proprietà pointer e metodi
|
|
257
343
|
*/
|
|
258
344
|
callback(fn, returnType, argTypes = []) {
|
|
259
|
-
return this._lib.callback(
|
|
260
|
-
_toNativeType(returnType),
|
|
261
|
-
_toNativeTypes(argTypes),
|
|
262
|
-
fn,
|
|
263
|
-
);
|
|
345
|
+
return this._lib.callback(_toNativeType(returnType), _toNativeTypes(argTypes), fn);
|
|
264
346
|
}
|
|
265
347
|
|
|
266
348
|
/**
|
|
@@ -306,11 +388,7 @@ class WinDLL extends CDLL {
|
|
|
306
388
|
* @returns {Object} Oggetto con .pointer (BigInt), .release()
|
|
307
389
|
*/
|
|
308
390
|
function callback(fn, returnType, argTypes = []) {
|
|
309
|
-
const cb = new Callback(
|
|
310
|
-
fn,
|
|
311
|
-
_toNativeType(returnType),
|
|
312
|
-
_toNativeTypes(argTypes),
|
|
313
|
-
);
|
|
391
|
+
const cb = new Callback(fn, _toNativeType(returnType), _toNativeTypes(argTypes));
|
|
314
392
|
|
|
315
393
|
return {
|
|
316
394
|
get pointer() {
|
|
@@ -338,11 +416,7 @@ function callback(fn, returnType, argTypes = []) {
|
|
|
338
416
|
* @returns {Object} Oggetto con .pointer (BigInt), .release()
|
|
339
417
|
*/
|
|
340
418
|
function threadSafeCallback(fn, returnType, argTypes = []) {
|
|
341
|
-
const cb = new ThreadSafeCallback(
|
|
342
|
-
fn,
|
|
343
|
-
_toNativeType(returnType),
|
|
344
|
-
_toNativeTypes(argTypes),
|
|
345
|
-
);
|
|
419
|
+
const cb = new ThreadSafeCallback(fn, _toNativeType(returnType), _toNativeTypes(argTypes));
|
|
346
420
|
|
|
347
421
|
return {
|
|
348
422
|
get pointer() {
|
|
@@ -547,12 +621,7 @@ function sizeof(type) {
|
|
|
547
621
|
}
|
|
548
622
|
|
|
549
623
|
// SimpleCData instance (e.g., sizeof(new c_uint64()))
|
|
550
|
-
if (
|
|
551
|
-
type &&
|
|
552
|
-
type._buffer &&
|
|
553
|
-
type.constructor &&
|
|
554
|
-
type.constructor._isSimpleCData
|
|
555
|
-
) {
|
|
624
|
+
if (type && type._buffer && type.constructor && type.constructor._isSimpleCData) {
|
|
556
625
|
return type.constructor._size;
|
|
557
626
|
}
|
|
558
627
|
|
|
@@ -569,26 +638,16 @@ function sizeof(type) {
|
|
|
569
638
|
}
|
|
570
639
|
|
|
571
640
|
// Struct type
|
|
572
|
-
if (
|
|
573
|
-
typeof type === "object" &&
|
|
574
|
-
type !== null &&
|
|
575
|
-
typeof type.size === "number"
|
|
576
|
-
) {
|
|
641
|
+
if (typeof type === "object" && type !== null && typeof type.size === "number") {
|
|
577
642
|
return type.size;
|
|
578
643
|
}
|
|
579
644
|
|
|
580
645
|
// Array type
|
|
581
|
-
if (
|
|
582
|
-
typeof type === "object" &&
|
|
583
|
-
type !== null &&
|
|
584
|
-
typeof type.getSize === "function"
|
|
585
|
-
) {
|
|
646
|
+
if (typeof type === "object" && type !== null && typeof type.getSize === "function") {
|
|
586
647
|
return type.getSize();
|
|
587
648
|
}
|
|
588
649
|
|
|
589
|
-
throw new TypeError(
|
|
590
|
-
`sizeof: unsupported type. Use SimpleCData classes like c_int32, c_uint64, etc.`,
|
|
591
|
-
);
|
|
650
|
+
throw new TypeError(`sizeof: unsupported type. Use SimpleCData classes like c_int32, c_uint64, etc.`);
|
|
592
651
|
}
|
|
593
652
|
|
|
594
653
|
/**
|
|
@@ -690,8 +749,7 @@ function ptrToBuffer(address, size) {
|
|
|
690
749
|
* @returns {Object} Tipo puntatore
|
|
691
750
|
*/
|
|
692
751
|
function POINTER(baseType) {
|
|
693
|
-
const baseSize =
|
|
694
|
-
typeof baseType === "object" ? baseType.size : sizeof(baseType);
|
|
752
|
+
const baseSize = typeof baseType === "object" ? baseType.size : sizeof(baseType);
|
|
695
753
|
const typeName = typeof baseType === "object" ? "struct" : baseType;
|
|
696
754
|
|
|
697
755
|
return {
|
|
@@ -794,9 +852,7 @@ function union(fields) {
|
|
|
794
852
|
else {
|
|
795
853
|
// Validate type is a SimpleCData class
|
|
796
854
|
if (!(typeof type === "function" && type._isSimpleCData)) {
|
|
797
|
-
throw new TypeError(
|
|
798
|
-
`union field "${name}": type must be a SimpleCData class, struct, union, or array`,
|
|
799
|
-
);
|
|
855
|
+
throw new TypeError(`union field "${name}": type must be a SimpleCData class, struct, union, or array`);
|
|
800
856
|
}
|
|
801
857
|
size = type._size;
|
|
802
858
|
alignment = Math.min(size, native.POINTER_SIZE);
|
|
@@ -854,13 +910,7 @@ function union(fields) {
|
|
|
854
910
|
if (prop === Symbol.iterator) return undefined;
|
|
855
911
|
|
|
856
912
|
// Handle Buffer/TypedArray properties FIRST before field checks
|
|
857
|
-
if (
|
|
858
|
-
prop === "length" ||
|
|
859
|
-
prop === "byteLength" ||
|
|
860
|
-
prop === "byteOffset" ||
|
|
861
|
-
prop === "buffer" ||
|
|
862
|
-
prop === "BYTES_PER_ELEMENT"
|
|
863
|
-
) {
|
|
913
|
+
if (prop === "length" || prop === "byteLength" || prop === "byteOffset" || prop === "buffer" || prop === "BYTES_PER_ELEMENT") {
|
|
864
914
|
return target[prop];
|
|
865
915
|
}
|
|
866
916
|
|
|
@@ -895,10 +945,7 @@ function union(fields) {
|
|
|
895
945
|
return fieldDefs.map((f) => f.name);
|
|
896
946
|
},
|
|
897
947
|
getOwnPropertyDescriptor(target, prop) {
|
|
898
|
-
if (
|
|
899
|
-
typeof prop === "string" &&
|
|
900
|
-
(fieldMap.has(prop) || prop === "_buffer" || prop === "toObject")
|
|
901
|
-
) {
|
|
948
|
+
if (typeof prop === "string" && (fieldMap.has(prop) || prop === "_buffer" || prop === "toObject")) {
|
|
902
949
|
return {
|
|
903
950
|
enumerable: prop !== "_buffer" && prop !== "toObject",
|
|
904
951
|
configurable: true,
|
|
@@ -928,13 +975,7 @@ function union(fields) {
|
|
|
928
975
|
|
|
929
976
|
// Bit field
|
|
930
977
|
if (field.isBitField) {
|
|
931
|
-
return _readBitField(
|
|
932
|
-
buf,
|
|
933
|
-
field.offset,
|
|
934
|
-
field.type,
|
|
935
|
-
field.bitOffset,
|
|
936
|
-
field.bitSize,
|
|
937
|
-
);
|
|
978
|
+
return _readBitField(buf, field.offset, field.type, field.bitOffset, field.bitSize);
|
|
938
979
|
}
|
|
939
980
|
|
|
940
981
|
// Nested struct
|
|
@@ -948,19 +989,11 @@ function union(fields) {
|
|
|
948
989
|
if (prop === Symbol.toStringTag) return "NestedUnionInstance";
|
|
949
990
|
if (prop === Symbol.iterator) return undefined;
|
|
950
991
|
// Handle Buffer/TypedArray properties
|
|
951
|
-
if (
|
|
952
|
-
prop === "length" ||
|
|
953
|
-
prop === "byteLength" ||
|
|
954
|
-
prop === "byteOffset" ||
|
|
955
|
-
prop === "buffer" ||
|
|
956
|
-
prop === "BYTES_PER_ELEMENT"
|
|
957
|
-
) {
|
|
992
|
+
if (prop === "length" || prop === "byteLength" || prop === "byteOffset" || prop === "buffer" || prop === "BYTES_PER_ELEMENT") {
|
|
958
993
|
return target[prop];
|
|
959
994
|
}
|
|
960
995
|
if (typeof prop === "string" && field.type.fields) {
|
|
961
|
-
if (
|
|
962
|
-
field.type.fields.some((f) => f.name === prop && !f.isAnonymous)
|
|
963
|
-
) {
|
|
996
|
+
if (field.type.fields.some((f) => f.name === prop && !f.isAnonymous)) {
|
|
964
997
|
return field.type.get(target, prop);
|
|
965
998
|
}
|
|
966
999
|
}
|
|
@@ -970,9 +1003,7 @@ function union(fields) {
|
|
|
970
1003
|
},
|
|
971
1004
|
set(target, prop, value, receiver) {
|
|
972
1005
|
if (typeof prop === "string" && field.type.fields) {
|
|
973
|
-
if (
|
|
974
|
-
field.type.fields.some((f) => f.name === prop && !f.isAnonymous)
|
|
975
|
-
) {
|
|
1006
|
+
if (field.type.fields.some((f) => f.name === prop && !f.isAnonymous)) {
|
|
976
1007
|
field.type.set(target, prop, value);
|
|
977
1008
|
return true;
|
|
978
1009
|
}
|
|
@@ -987,16 +1018,10 @@ function union(fields) {
|
|
|
987
1018
|
return Reflect.has(target, prop);
|
|
988
1019
|
},
|
|
989
1020
|
ownKeys(target) {
|
|
990
|
-
return (field.type.fields || [])
|
|
991
|
-
.filter((f) => !f.isAnonymous)
|
|
992
|
-
.map((f) => f.name);
|
|
1021
|
+
return (field.type.fields || []).filter((f) => !f.isAnonymous).map((f) => f.name);
|
|
993
1022
|
},
|
|
994
1023
|
getOwnPropertyDescriptor(target, prop) {
|
|
995
|
-
if (
|
|
996
|
-
typeof prop === "string" &&
|
|
997
|
-
field.type.fields &&
|
|
998
|
-
field.type.fields.some((f) => f.name === prop)
|
|
999
|
-
) {
|
|
1024
|
+
if (typeof prop === "string" && field.type.fields && field.type.fields.some((f) => f.name === prop)) {
|
|
1000
1025
|
return {
|
|
1001
1026
|
enumerable: true,
|
|
1002
1027
|
configurable: true,
|
|
@@ -1010,9 +1035,7 @@ function union(fields) {
|
|
|
1010
1035
|
|
|
1011
1036
|
// Array
|
|
1012
1037
|
if (field.isArray) {
|
|
1013
|
-
return field.type.wrap(
|
|
1014
|
-
buf.subarray(field.offset, field.offset + field.size),
|
|
1015
|
-
);
|
|
1038
|
+
return field.type.wrap(buf.subarray(field.offset, field.offset + field.size));
|
|
1016
1039
|
}
|
|
1017
1040
|
|
|
1018
1041
|
// Tipo base
|
|
@@ -1038,14 +1061,7 @@ function union(fields) {
|
|
|
1038
1061
|
|
|
1039
1062
|
// Bit field
|
|
1040
1063
|
if (field.isBitField) {
|
|
1041
|
-
_writeBitField(
|
|
1042
|
-
buf,
|
|
1043
|
-
field.offset,
|
|
1044
|
-
field.type,
|
|
1045
|
-
field.bitOffset,
|
|
1046
|
-
field.bitSize,
|
|
1047
|
-
value,
|
|
1048
|
-
);
|
|
1064
|
+
_writeBitField(buf, field.offset, field.type, field.bitOffset, field.bitSize, value);
|
|
1049
1065
|
return;
|
|
1050
1066
|
}
|
|
1051
1067
|
|
|
@@ -1054,10 +1070,7 @@ function union(fields) {
|
|
|
1054
1070
|
if (Buffer.isBuffer(value)) {
|
|
1055
1071
|
value.copy(buf, field.offset, 0, field.size);
|
|
1056
1072
|
} else if (typeof value === "object") {
|
|
1057
|
-
const nestedBuf = buf.subarray(
|
|
1058
|
-
field.offset,
|
|
1059
|
-
field.offset + field.size,
|
|
1060
|
-
);
|
|
1073
|
+
const nestedBuf = buf.subarray(field.offset, field.offset + field.size);
|
|
1061
1074
|
for (const [k, v] of Object.entries(value)) {
|
|
1062
1075
|
field.type.set(nestedBuf, k, v);
|
|
1063
1076
|
}
|
|
@@ -1070,9 +1083,7 @@ function union(fields) {
|
|
|
1070
1083
|
if (Buffer.isBuffer(value)) {
|
|
1071
1084
|
value.copy(buf, field.offset, 0, field.size);
|
|
1072
1085
|
} else if (Array.isArray(value)) {
|
|
1073
|
-
const wrapped = field.type.wrap(
|
|
1074
|
-
buf.subarray(field.offset, field.offset + field.size),
|
|
1075
|
-
);
|
|
1086
|
+
const wrapped = field.type.wrap(buf.subarray(field.offset, field.offset + field.size));
|
|
1076
1087
|
for (let i = 0; i < Math.min(value.length, field.type.length); i++) {
|
|
1077
1088
|
wrapped[i] = value[i];
|
|
1078
1089
|
}
|
|
@@ -1090,11 +1101,7 @@ function union(fields) {
|
|
|
1090
1101
|
toObject(bufOrObj) {
|
|
1091
1102
|
// Se è già un object (non buffer), ritorna così com'è
|
|
1092
1103
|
if (!Buffer.isBuffer(bufOrObj)) {
|
|
1093
|
-
if (
|
|
1094
|
-
bufOrObj &&
|
|
1095
|
-
bufOrObj._buffer &&
|
|
1096
|
-
bufOrObj._buffer.length === maxSize
|
|
1097
|
-
) {
|
|
1104
|
+
if (bufOrObj && bufOrObj._buffer && bufOrObj._buffer.length === maxSize) {
|
|
1098
1105
|
return bufOrObj; // Già convertito
|
|
1099
1106
|
}
|
|
1100
1107
|
// Se è un plain object, convertilo in union
|
|
@@ -1128,13 +1135,7 @@ function union(fields) {
|
|
|
1128
1135
|
Object.defineProperty(obj, field.name, {
|
|
1129
1136
|
get() {
|
|
1130
1137
|
if (field.isBitField) {
|
|
1131
|
-
return _readBitField(
|
|
1132
|
-
buf,
|
|
1133
|
-
0,
|
|
1134
|
-
field.type,
|
|
1135
|
-
field.bitOffset,
|
|
1136
|
-
field.bitSize,
|
|
1137
|
-
);
|
|
1138
|
+
return _readBitField(buf, 0, field.type, field.bitOffset, field.bitSize);
|
|
1138
1139
|
} else if (field.isNested) {
|
|
1139
1140
|
// Cache nested objects per evitare di ricrearli ogni volta
|
|
1140
1141
|
if (!nestedCache.has(field.name)) {
|
|
@@ -1152,14 +1153,7 @@ function union(fields) {
|
|
|
1152
1153
|
},
|
|
1153
1154
|
set(value) {
|
|
1154
1155
|
if (field.isBitField) {
|
|
1155
|
-
_writeBitField(
|
|
1156
|
-
buf,
|
|
1157
|
-
0,
|
|
1158
|
-
field.type,
|
|
1159
|
-
field.bitOffset,
|
|
1160
|
-
field.bitSize,
|
|
1161
|
-
value,
|
|
1162
|
-
);
|
|
1156
|
+
_writeBitField(buf, 0, field.type, field.bitOffset, field.bitSize, value);
|
|
1163
1157
|
} else {
|
|
1164
1158
|
writeValue(buf, field.type, value, 0);
|
|
1165
1159
|
}
|
|
@@ -1229,12 +1223,7 @@ class Structure {
|
|
|
1229
1223
|
buf.fill(0);
|
|
1230
1224
|
|
|
1231
1225
|
// Support positional args: new Point(10,20)
|
|
1232
|
-
if (
|
|
1233
|
-
args.length === 1 &&
|
|
1234
|
-
typeof args[0] === "object" &&
|
|
1235
|
-
!Array.isArray(args[0]) &&
|
|
1236
|
-
!Buffer.isBuffer(args[0])
|
|
1237
|
-
) {
|
|
1226
|
+
if (args.length === 1 && typeof args[0] === "object" && !Array.isArray(args[0]) && !Buffer.isBuffer(args[0])) {
|
|
1238
1227
|
const initial = args[0];
|
|
1239
1228
|
for (const [k, v] of Object.entries(initial)) {
|
|
1240
1229
|
def.set(buf, k, v);
|
|
@@ -1312,8 +1301,7 @@ class Structure {
|
|
|
1312
1301
|
return Reflect.set(target, prop, value, receiver);
|
|
1313
1302
|
},
|
|
1314
1303
|
has(target, prop) {
|
|
1315
|
-
if (prop === "_buffer" || prop === "_structDef" || prop === "toObject")
|
|
1316
|
-
return true;
|
|
1304
|
+
if (prop === "_buffer" || prop === "_structDef" || prop === "toObject") return true;
|
|
1317
1305
|
if (typeof prop === "string" && fieldMap.has(prop)) return true;
|
|
1318
1306
|
if (typeof prop === "string" && anonFieldNames.has(prop)) return true;
|
|
1319
1307
|
return Reflect.has(target, prop);
|
|
@@ -1332,10 +1320,7 @@ class Structure {
|
|
|
1332
1320
|
return keys;
|
|
1333
1321
|
},
|
|
1334
1322
|
getOwnPropertyDescriptor(target, prop) {
|
|
1335
|
-
if (
|
|
1336
|
-
typeof prop === "string" &&
|
|
1337
|
-
(fieldMap.has(prop) || anonFieldNames.has(prop))
|
|
1338
|
-
) {
|
|
1323
|
+
if (typeof prop === "string" && (fieldMap.has(prop) || anonFieldNames.has(prop))) {
|
|
1339
1324
|
return {
|
|
1340
1325
|
enumerable: true,
|
|
1341
1326
|
configurable: true,
|
|
@@ -1465,19 +1450,11 @@ class Structure {
|
|
|
1465
1450
|
|
|
1466
1451
|
// Direct typed array access for numeric fields (maximum performance)
|
|
1467
1452
|
getInt32Array(offset = 0, length) {
|
|
1468
|
-
return new Int32Array(
|
|
1469
|
-
this.__buffer.buffer,
|
|
1470
|
-
this.__buffer.byteOffset + offset,
|
|
1471
|
-
length,
|
|
1472
|
-
);
|
|
1453
|
+
return new Int32Array(this.__buffer.buffer, this.__buffer.byteOffset + offset, length);
|
|
1473
1454
|
}
|
|
1474
1455
|
|
|
1475
1456
|
getFloat64Array(offset = 0, length) {
|
|
1476
|
-
return new Float64Array(
|
|
1477
|
-
this.__buffer.buffer,
|
|
1478
|
-
this.__buffer.byteOffset + offset,
|
|
1479
|
-
length,
|
|
1480
|
-
);
|
|
1457
|
+
return new Float64Array(this.__buffer.buffer, this.__buffer.byteOffset + offset, length);
|
|
1481
1458
|
}
|
|
1482
1459
|
|
|
1483
1460
|
// Get raw buffer slice for external operations
|
|
@@ -1545,9 +1522,7 @@ class Union extends Structure {
|
|
|
1545
1522
|
function array(elementType, count) {
|
|
1546
1523
|
// Validate elementType is a SimpleCData class
|
|
1547
1524
|
if (!(typeof elementType === "function" && elementType._isSimpleCData)) {
|
|
1548
|
-
throw new TypeError(
|
|
1549
|
-
"array elementType must be a SimpleCData class (e.g., c_int32, c_uint8)",
|
|
1550
|
-
);
|
|
1525
|
+
throw new TypeError("array elementType must be a SimpleCData class (e.g., c_int32, c_uint8)");
|
|
1551
1526
|
}
|
|
1552
1527
|
|
|
1553
1528
|
const elementSize = elementType._size;
|
|
@@ -1666,12 +1641,7 @@ function array(elementType, count) {
|
|
|
1666
1641
|
}
|
|
1667
1642
|
} else if (typeof values === "string") {
|
|
1668
1643
|
for (let i = 0; i < Math.min(values.length, count); i++) {
|
|
1669
|
-
writeValue(
|
|
1670
|
-
buffer,
|
|
1671
|
-
elementType,
|
|
1672
|
-
values.charCodeAt(i),
|
|
1673
|
-
i * sizeof(elementType),
|
|
1674
|
-
);
|
|
1644
|
+
writeValue(buffer, elementType, values.charCodeAt(i), i * sizeof(elementType));
|
|
1675
1645
|
}
|
|
1676
1646
|
}
|
|
1677
1647
|
return wrap(buffer);
|
|
@@ -1786,15 +1756,7 @@ function _initWinError() {
|
|
|
1786
1756
|
_win_error_funcs = {
|
|
1787
1757
|
GetLastError: kernel32.func("GetLastError", c_uint32, []),
|
|
1788
1758
|
SetLastError: kernel32.func("SetLastError", c_void, [c_uint32]),
|
|
1789
|
-
FormatMessageW: kernel32.func("FormatMessageW", c_uint32, [
|
|
1790
|
-
c_uint32,
|
|
1791
|
-
c_void_p,
|
|
1792
|
-
c_uint32,
|
|
1793
|
-
c_uint32,
|
|
1794
|
-
c_void_p,
|
|
1795
|
-
c_uint32,
|
|
1796
|
-
c_void_p,
|
|
1797
|
-
]),
|
|
1759
|
+
FormatMessageW: kernel32.func("FormatMessageW", c_uint32, [c_uint32, c_void_p, c_uint32, c_uint32, c_void_p, c_uint32, c_void_p]),
|
|
1798
1760
|
_lib: kernel32,
|
|
1799
1761
|
};
|
|
1800
1762
|
} catch (e) {
|
|
@@ -1893,9 +1855,7 @@ function bitfield(baseType, bits) {
|
|
|
1893
1855
|
const maxBits = baseSize * 8;
|
|
1894
1856
|
|
|
1895
1857
|
if (bits < 1 || bits > maxBits) {
|
|
1896
|
-
throw new Error(
|
|
1897
|
-
`Bit field size must be between 1 and ${maxBits} for ${baseType}`,
|
|
1898
|
-
);
|
|
1858
|
+
throw new Error(`Bit field size must be between 1 and ${maxBits} for ${baseType}`);
|
|
1899
1859
|
}
|
|
1900
1860
|
|
|
1901
1861
|
return {
|
|
@@ -1910,22 +1870,14 @@ function bitfield(baseType, bits) {
|
|
|
1910
1870
|
* Helper per verificare se un tipo è una struct
|
|
1911
1871
|
*/
|
|
1912
1872
|
function _isStruct(type) {
|
|
1913
|
-
return (
|
|
1914
|
-
typeof type === "object" &&
|
|
1915
|
-
type !== null &&
|
|
1916
|
-
typeof type.size === "number" &&
|
|
1917
|
-
Array.isArray(type.fields) &&
|
|
1918
|
-
typeof type.create === "function"
|
|
1919
|
-
);
|
|
1873
|
+
return typeof type === "object" && type !== null && typeof type.size === "number" && Array.isArray(type.fields) && typeof type.create === "function";
|
|
1920
1874
|
}
|
|
1921
1875
|
|
|
1922
1876
|
/**
|
|
1923
1877
|
* Helper per verificare se un tipo è un array type
|
|
1924
1878
|
*/
|
|
1925
1879
|
function _isArrayType(type) {
|
|
1926
|
-
return
|
|
1927
|
-
typeof type === "object" && type !== null && type._isArrayType === true
|
|
1928
|
-
);
|
|
1880
|
+
return typeof type === "object" && type !== null && type._isArrayType === true;
|
|
1929
1881
|
}
|
|
1930
1882
|
|
|
1931
1883
|
/**
|
|
@@ -2007,8 +1959,7 @@ function _writeBitField(buf, offset, baseType, bitOffset, bitSize, newValue) {
|
|
|
2007
1959
|
if (baseSize === 8) {
|
|
2008
1960
|
const mask = (1n << BigInt(bitSize)) - 1n;
|
|
2009
1961
|
const clearMask = ~(mask << BigInt(bitOffset));
|
|
2010
|
-
value =
|
|
2011
|
-
(value & clearMask) | ((BigInt(newValue) & mask) << BigInt(bitOffset));
|
|
1962
|
+
value = (value & clearMask) | ((BigInt(newValue) & mask) << BigInt(bitOffset));
|
|
2012
1963
|
} else {
|
|
2013
1964
|
const mask = (1 << bitSize) - 1;
|
|
2014
1965
|
const clearMask = ~(mask << bitOffset);
|
|
@@ -2046,12 +1997,7 @@ function struct(fields, options = {}) {
|
|
|
2046
1997
|
let fieldDef;
|
|
2047
1998
|
|
|
2048
1999
|
// Caso 0: Anonymous field - { type: SomeStruct, anonymous: true }
|
|
2049
|
-
if (
|
|
2050
|
-
typeof type === "object" &&
|
|
2051
|
-
type !== null &&
|
|
2052
|
-
type.anonymous === true &&
|
|
2053
|
-
type.type
|
|
2054
|
-
) {
|
|
2000
|
+
if (typeof type === "object" && type !== null && type.anonymous === true && type.type) {
|
|
2055
2001
|
// Reset bit field state
|
|
2056
2002
|
currentBitFieldBase = null;
|
|
2057
2003
|
currentBitOffset = 0;
|
|
@@ -2087,9 +2033,7 @@ function struct(fields, options = {}) {
|
|
|
2087
2033
|
const alignment = packed ? 1 : Math.min(baseSize, native.POINTER_SIZE);
|
|
2088
2034
|
|
|
2089
2035
|
// Verifica se possiamo continuare nel bit field corrente
|
|
2090
|
-
const canContinue =
|
|
2091
|
-
currentBitFieldBase === baseType &&
|
|
2092
|
-
currentBitOffset + bits <= baseSize * 8;
|
|
2036
|
+
const canContinue = currentBitFieldBase === baseType && currentBitOffset + bits <= baseSize * 8;
|
|
2093
2037
|
|
|
2094
2038
|
if (!canContinue) {
|
|
2095
2039
|
// Inizia un nuovo bit field
|
|
@@ -2190,9 +2134,7 @@ function struct(fields, options = {}) {
|
|
|
2190
2134
|
|
|
2191
2135
|
// Validate type is a SimpleCData class
|
|
2192
2136
|
if (!(typeof type === "function" && type._isSimpleCData)) {
|
|
2193
|
-
throw new TypeError(
|
|
2194
|
-
`struct field "${name}": type must be a SimpleCData class, struct, union, or array`,
|
|
2195
|
-
);
|
|
2137
|
+
throw new TypeError(`struct field "${name}": type must be a SimpleCData class, struct, union, or array`);
|
|
2196
2138
|
}
|
|
2197
2139
|
|
|
2198
2140
|
const size = type._size;
|
|
@@ -2252,9 +2194,7 @@ function struct(fields, options = {}) {
|
|
|
2252
2194
|
if (fieldType && fieldType._isSimpleCData) {
|
|
2253
2195
|
const fieldOffset = offset; // Capture offset for closure
|
|
2254
2196
|
fieldReaders.set(name, (buf) => fieldType._reader(buf, fieldOffset));
|
|
2255
|
-
fieldWriters.set(name, (buf, val) =>
|
|
2256
|
-
fieldType._writer(buf, fieldOffset, val),
|
|
2257
|
-
);
|
|
2197
|
+
fieldWriters.set(name, (buf, val) => fieldType._writer(buf, fieldOffset, val));
|
|
2258
2198
|
}
|
|
2259
2199
|
}
|
|
2260
2200
|
|
|
@@ -2303,13 +2243,7 @@ function struct(fields, options = {}) {
|
|
|
2303
2243
|
|
|
2304
2244
|
// Handle Buffer/TypedArray properties FIRST before field checks
|
|
2305
2245
|
// TypedArray methods need direct access to avoid Proxy interference
|
|
2306
|
-
if (
|
|
2307
|
-
prop === "length" ||
|
|
2308
|
-
prop === "byteLength" ||
|
|
2309
|
-
prop === "byteOffset" ||
|
|
2310
|
-
prop === "buffer" ||
|
|
2311
|
-
prop === "BYTES_PER_ELEMENT"
|
|
2312
|
-
) {
|
|
2246
|
+
if (prop === "length" || prop === "byteLength" || prop === "byteOffset" || prop === "buffer" || prop === "BYTES_PER_ELEMENT") {
|
|
2313
2247
|
return target[prop];
|
|
2314
2248
|
}
|
|
2315
2249
|
|
|
@@ -2394,10 +2328,7 @@ function struct(fields, options = {}) {
|
|
|
2394
2328
|
return keys;
|
|
2395
2329
|
},
|
|
2396
2330
|
getOwnPropertyDescriptor(target, prop) {
|
|
2397
|
-
if (
|
|
2398
|
-
typeof prop === "string" &&
|
|
2399
|
-
(fieldMap.has(prop) || prop === "_buffer" || prop === "toObject")
|
|
2400
|
-
) {
|
|
2331
|
+
if (typeof prop === "string" && (fieldMap.has(prop) || prop === "_buffer" || prop === "toObject")) {
|
|
2401
2332
|
return {
|
|
2402
2333
|
enumerable: prop !== "_buffer" && prop !== "toObject",
|
|
2403
2334
|
configurable: true,
|
|
@@ -2469,47 +2400,28 @@ function struct(fields, options = {}) {
|
|
|
2469
2400
|
if (field) {
|
|
2470
2401
|
// Bit field
|
|
2471
2402
|
if (field.isBitField) {
|
|
2472
|
-
return _readBitField(
|
|
2473
|
-
buf,
|
|
2474
|
-
field.offset,
|
|
2475
|
-
field.type,
|
|
2476
|
-
field.bitOffset,
|
|
2477
|
-
field.bitSize,
|
|
2478
|
-
);
|
|
2403
|
+
return _readBitField(buf, field.offset, field.type, field.bitOffset, field.bitSize);
|
|
2479
2404
|
}
|
|
2480
2405
|
|
|
2481
2406
|
// Nested struct (senza dot = ritorna intero oggetto)
|
|
2482
2407
|
if (field.isNested) {
|
|
2483
|
-
const nestedBuf = buf.subarray(
|
|
2484
|
-
field.offset,
|
|
2485
|
-
field.offset + field.size,
|
|
2486
|
-
);
|
|
2408
|
+
const nestedBuf = buf.subarray(field.offset, field.offset + field.size);
|
|
2487
2409
|
// Proxy-based nested instance
|
|
2488
2410
|
return field.type.create
|
|
2489
2411
|
? // Se ha create(), usa quello per creare il proxy
|
|
2490
2412
|
new Proxy(nestedBuf, {
|
|
2491
2413
|
get(target, prop, receiver) {
|
|
2492
2414
|
if (prop === "_buffer") return target;
|
|
2493
|
-
if (prop === "toObject")
|
|
2494
|
-
|
|
2495
|
-
if (prop === Symbol.toStringTag)
|
|
2496
|
-
return "NestedStructInstance";
|
|
2415
|
+
if (prop === "toObject") return () => field.type.toObject(target);
|
|
2416
|
+
if (prop === Symbol.toStringTag) return "NestedStructInstance";
|
|
2497
2417
|
if (prop === Symbol.iterator) return undefined;
|
|
2498
2418
|
// Handle Buffer/TypedArray properties
|
|
2499
|
-
if (
|
|
2500
|
-
prop === "length" ||
|
|
2501
|
-
prop === "byteLength" ||
|
|
2502
|
-
prop === "byteOffset" ||
|
|
2503
|
-
prop === "buffer" ||
|
|
2504
|
-
prop === "BYTES_PER_ELEMENT"
|
|
2505
|
-
) {
|
|
2419
|
+
if (prop === "length" || prop === "byteLength" || prop === "byteOffset" || prop === "buffer" || prop === "BYTES_PER_ELEMENT") {
|
|
2506
2420
|
return target[prop];
|
|
2507
2421
|
}
|
|
2508
2422
|
if (typeof prop === "string") {
|
|
2509
2423
|
// Check direct fields
|
|
2510
|
-
const nestedFieldMap = field.type.fields
|
|
2511
|
-
? new Map(field.type.fields.map((f) => [f.name, f]))
|
|
2512
|
-
: new Map();
|
|
2424
|
+
const nestedFieldMap = field.type.fields ? new Map(field.type.fields.map((f) => [f.name, f])) : new Map();
|
|
2513
2425
|
if (nestedFieldMap.has(prop)) {
|
|
2514
2426
|
return field.type.get(target, prop);
|
|
2515
2427
|
}
|
|
@@ -2528,9 +2440,7 @@ function struct(fields, options = {}) {
|
|
|
2528
2440
|
},
|
|
2529
2441
|
set(target, prop, value, receiver) {
|
|
2530
2442
|
if (typeof prop === "string") {
|
|
2531
|
-
const nestedFieldMap = field.type.fields
|
|
2532
|
-
? new Map(field.type.fields.map((f) => [f.name, f]))
|
|
2533
|
-
: new Map();
|
|
2443
|
+
const nestedFieldMap = field.type.fields ? new Map(field.type.fields.map((f) => [f.name, f])) : new Map();
|
|
2534
2444
|
if (nestedFieldMap.has(prop)) {
|
|
2535
2445
|
field.type.set(target, prop, value);
|
|
2536
2446
|
return true;
|
|
@@ -2550,8 +2460,7 @@ function struct(fields, options = {}) {
|
|
|
2550
2460
|
has(target, prop) {
|
|
2551
2461
|
if (prop === "_buffer" || prop === "toObject") return true;
|
|
2552
2462
|
if (typeof prop === "string" && field.type.fields) {
|
|
2553
|
-
if (field.type.fields.some((f) => f.name === prop))
|
|
2554
|
-
return true;
|
|
2463
|
+
if (field.type.fields.some((f) => f.name === prop)) return true;
|
|
2555
2464
|
}
|
|
2556
2465
|
return Reflect.has(target, prop);
|
|
2557
2466
|
},
|
|
@@ -2559,11 +2468,7 @@ function struct(fields, options = {}) {
|
|
|
2559
2468
|
return (field.type.fields || []).map((f) => f.name);
|
|
2560
2469
|
},
|
|
2561
2470
|
getOwnPropertyDescriptor(target, prop) {
|
|
2562
|
-
if (
|
|
2563
|
-
typeof prop === "string" &&
|
|
2564
|
-
field.type.fields &&
|
|
2565
|
-
field.type.fields.some((f) => f.name === prop)
|
|
2566
|
-
) {
|
|
2471
|
+
if (typeof prop === "string" && field.type.fields && field.type.fields.some((f) => f.name === prop)) {
|
|
2567
2472
|
return {
|
|
2568
2473
|
enumerable: true,
|
|
2569
2474
|
configurable: true,
|
|
@@ -2578,10 +2483,7 @@ function struct(fields, options = {}) {
|
|
|
2578
2483
|
|
|
2579
2484
|
// Array field
|
|
2580
2485
|
if (field.isArray) {
|
|
2581
|
-
const arrayBuf = buf.subarray(
|
|
2582
|
-
field.offset,
|
|
2583
|
-
field.offset + field.size,
|
|
2584
|
-
);
|
|
2486
|
+
const arrayBuf = buf.subarray(field.offset, field.offset + field.size);
|
|
2585
2487
|
return field.type.wrap(arrayBuf);
|
|
2586
2488
|
}
|
|
2587
2489
|
|
|
@@ -2599,9 +2501,7 @@ function struct(fields, options = {}) {
|
|
|
2599
2501
|
if (!field) {
|
|
2600
2502
|
for (const f of fieldDefs) {
|
|
2601
2503
|
if (f.isAnonymous && f.type && f.type.fields) {
|
|
2602
|
-
const hasField = f.type.fields.some(
|
|
2603
|
-
(subField) => subField.name === firstPart,
|
|
2604
|
-
);
|
|
2504
|
+
const hasField = f.type.fields.some((subField) => subField.name === firstPart);
|
|
2605
2505
|
if (hasField) {
|
|
2606
2506
|
const nestedBuf = buf.subarray(f.offset, f.offset + f.size);
|
|
2607
2507
|
return f.type.get(nestedBuf, fieldName);
|
|
@@ -2650,14 +2550,7 @@ function struct(fields, options = {}) {
|
|
|
2650
2550
|
if (field) {
|
|
2651
2551
|
// Bit field
|
|
2652
2552
|
if (field.isBitField) {
|
|
2653
|
-
_writeBitField(
|
|
2654
|
-
buf,
|
|
2655
|
-
field.offset,
|
|
2656
|
-
field.type,
|
|
2657
|
-
field.bitOffset,
|
|
2658
|
-
field.bitSize,
|
|
2659
|
-
value,
|
|
2660
|
-
);
|
|
2553
|
+
_writeBitField(buf, field.offset, field.type, field.bitOffset, field.bitSize, value);
|
|
2661
2554
|
return;
|
|
2662
2555
|
}
|
|
2663
2556
|
|
|
@@ -2666,10 +2559,7 @@ function struct(fields, options = {}) {
|
|
|
2666
2559
|
if (Buffer.isBuffer(value)) {
|
|
2667
2560
|
value.copy(buf, field.offset, 0, field.size);
|
|
2668
2561
|
} else if (typeof value === "object") {
|
|
2669
|
-
const nestedBuf = buf.subarray(
|
|
2670
|
-
field.offset,
|
|
2671
|
-
field.offset + field.size,
|
|
2672
|
-
);
|
|
2562
|
+
const nestedBuf = buf.subarray(field.offset, field.offset + field.size);
|
|
2673
2563
|
for (const [k, v] of Object.entries(value)) {
|
|
2674
2564
|
field.type.set(nestedBuf, k, v);
|
|
2675
2565
|
}
|
|
@@ -2682,16 +2572,9 @@ function struct(fields, options = {}) {
|
|
|
2682
2572
|
if (Buffer.isBuffer(value)) {
|
|
2683
2573
|
value.copy(buf, field.offset, 0, field.size);
|
|
2684
2574
|
} else if (Array.isArray(value)) {
|
|
2685
|
-
const arrayBuf = buf.subarray(
|
|
2686
|
-
field.offset,
|
|
2687
|
-
field.offset + field.size,
|
|
2688
|
-
);
|
|
2575
|
+
const arrayBuf = buf.subarray(field.offset, field.offset + field.size);
|
|
2689
2576
|
const wrapped = field.type.wrap(arrayBuf);
|
|
2690
|
-
for (
|
|
2691
|
-
let i = 0;
|
|
2692
|
-
i < Math.min(value.length, field.type.length);
|
|
2693
|
-
i++
|
|
2694
|
-
) {
|
|
2577
|
+
for (let i = 0; i < Math.min(value.length, field.type.length); i++) {
|
|
2695
2578
|
wrapped[i] = value[i];
|
|
2696
2579
|
}
|
|
2697
2580
|
}
|
|
@@ -2714,9 +2597,7 @@ function struct(fields, options = {}) {
|
|
|
2714
2597
|
for (const f of fieldDefs) {
|
|
2715
2598
|
if (f.isAnonymous && f.type && f.type.fields) {
|
|
2716
2599
|
// Verifica se il campo esiste nel tipo anonimo
|
|
2717
|
-
const hasField = f.type.fields.some(
|
|
2718
|
-
(subField) => subField.name === firstPart,
|
|
2719
|
-
);
|
|
2600
|
+
const hasField = f.type.fields.some((subField) => subField.name === firstPart);
|
|
2720
2601
|
if (hasField) {
|
|
2721
2602
|
// Scrive nel campo dell'anonymous field
|
|
2722
2603
|
const nestedBuf = buf.subarray(f.offset, f.offset + f.size);
|
|
@@ -2730,14 +2611,7 @@ function struct(fields, options = {}) {
|
|
|
2730
2611
|
|
|
2731
2612
|
// Bit field
|
|
2732
2613
|
if (field.isBitField) {
|
|
2733
|
-
_writeBitField(
|
|
2734
|
-
buf,
|
|
2735
|
-
field.offset,
|
|
2736
|
-
field.type,
|
|
2737
|
-
field.bitOffset,
|
|
2738
|
-
field.bitSize,
|
|
2739
|
-
value,
|
|
2740
|
-
);
|
|
2614
|
+
_writeBitField(buf, field.offset, field.type, field.bitOffset, field.bitSize, value);
|
|
2741
2615
|
return;
|
|
2742
2616
|
}
|
|
2743
2617
|
|
|
@@ -2745,20 +2619,14 @@ function struct(fields, options = {}) {
|
|
|
2745
2619
|
if (field.isNested) {
|
|
2746
2620
|
if (parts.length > 1) {
|
|
2747
2621
|
// Accesso a campo annidato singolo
|
|
2748
|
-
const nestedBuf = buf.subarray(
|
|
2749
|
-
field.offset,
|
|
2750
|
-
field.offset + field.size,
|
|
2751
|
-
);
|
|
2622
|
+
const nestedBuf = buf.subarray(field.offset, field.offset + field.size);
|
|
2752
2623
|
field.type.set(nestedBuf, parts.slice(1).join("."), value);
|
|
2753
2624
|
} else if (Buffer.isBuffer(value)) {
|
|
2754
2625
|
// Copia buffer
|
|
2755
2626
|
value.copy(buf, field.offset, 0, field.size);
|
|
2756
2627
|
} else if (typeof value === "object") {
|
|
2757
2628
|
// Imposta campi da oggetto
|
|
2758
|
-
const nestedBuf = buf.subarray(
|
|
2759
|
-
field.offset,
|
|
2760
|
-
field.offset + field.size,
|
|
2761
|
-
);
|
|
2629
|
+
const nestedBuf = buf.subarray(field.offset, field.offset + field.size);
|
|
2762
2630
|
for (const [k, v] of Object.entries(value)) {
|
|
2763
2631
|
field.type.set(nestedBuf, k, v);
|
|
2764
2632
|
}
|
|
@@ -2773,10 +2641,7 @@ function struct(fields, options = {}) {
|
|
|
2773
2641
|
value.copy(buf, field.offset, 0, field.size);
|
|
2774
2642
|
} else if (Array.isArray(value)) {
|
|
2775
2643
|
// Inizializza da array JavaScript
|
|
2776
|
-
const arrayBuf = buf.subarray(
|
|
2777
|
-
field.offset,
|
|
2778
|
-
field.offset + field.size,
|
|
2779
|
-
);
|
|
2644
|
+
const arrayBuf = buf.subarray(field.offset, field.offset + field.size);
|
|
2780
2645
|
const wrapped = field.type.wrap(arrayBuf);
|
|
2781
2646
|
for (let i = 0; i < Math.min(value.length, field.type.length); i++) {
|
|
2782
2647
|
wrapped[i] = value[i];
|
|
@@ -2819,18 +2684,9 @@ function struct(fields, options = {}) {
|
|
|
2819
2684
|
// Leggi tutti i campi in una volta (eager approach)
|
|
2820
2685
|
for (const field of fieldDefs) {
|
|
2821
2686
|
if (field.isBitField) {
|
|
2822
|
-
result[field.name] = _readBitField(
|
|
2823
|
-
buf,
|
|
2824
|
-
field.offset,
|
|
2825
|
-
field.type,
|
|
2826
|
-
field.bitOffset,
|
|
2827
|
-
field.bitSize,
|
|
2828
|
-
);
|
|
2687
|
+
result[field.name] = _readBitField(buf, field.offset, field.type, field.bitOffset, field.bitSize);
|
|
2829
2688
|
} else if (field.isNested) {
|
|
2830
|
-
const nestedBuf = buf.subarray(
|
|
2831
|
-
field.offset,
|
|
2832
|
-
field.offset + field.size,
|
|
2833
|
-
);
|
|
2689
|
+
const nestedBuf = buf.subarray(field.offset, field.offset + field.size);
|
|
2834
2690
|
const nestedObj = field.type.toObject(nestedBuf);
|
|
2835
2691
|
if (field.isAnonymous) {
|
|
2836
2692
|
// Anonymous fields: promote their fields to parent level
|
|
@@ -2839,10 +2695,7 @@ function struct(fields, options = {}) {
|
|
|
2839
2695
|
result[field.name] = nestedObj;
|
|
2840
2696
|
}
|
|
2841
2697
|
} else if (field.isArray) {
|
|
2842
|
-
const arrayBuf = buf.subarray(
|
|
2843
|
-
field.offset,
|
|
2844
|
-
field.offset + field.size,
|
|
2845
|
-
);
|
|
2698
|
+
const arrayBuf = buf.subarray(field.offset, field.offset + field.size);
|
|
2846
2699
|
result[field.name] = field.type.wrap(arrayBuf);
|
|
2847
2700
|
} else {
|
|
2848
2701
|
// Tipo base - lettura diretta
|
|
@@ -2863,8 +2716,7 @@ function struct(fields, options = {}) {
|
|
|
2863
2716
|
// O(1) lookup con Map
|
|
2864
2717
|
const field = fieldMap.get(fieldName);
|
|
2865
2718
|
if (!field) throw new Error(`Unknown field: ${fieldName}`);
|
|
2866
|
-
if (!field.isNested)
|
|
2867
|
-
throw new Error(`Field ${fieldName} is not a nested struct`);
|
|
2719
|
+
if (!field.isNested) throw new Error(`Field ${fieldName} is not a nested struct`);
|
|
2868
2720
|
return buf.subarray(field.offset, field.offset + field.size);
|
|
2869
2721
|
},
|
|
2870
2722
|
};
|
|
@@ -2876,10 +2728,7 @@ function struct(fields, options = {}) {
|
|
|
2876
2728
|
structDef._cppStructType = cppStructType;
|
|
2877
2729
|
} catch (e) {
|
|
2878
2730
|
// Se fallisce, continua senza C++ (fallback a JS)
|
|
2879
|
-
console.warn(
|
|
2880
|
-
"Failed to create C++ StructType, using JavaScript fallback:",
|
|
2881
|
-
e.message,
|
|
2882
|
-
);
|
|
2731
|
+
console.warn("Failed to create C++ StructType, using JavaScript fallback:", e.message);
|
|
2883
2732
|
}
|
|
2884
2733
|
|
|
2885
2734
|
// fromObject: write plain object values into buffer
|
|
@@ -3140,10 +2989,7 @@ class c_wchar extends SimpleCData {
|
|
|
3140
2989
|
class c_void_p extends SimpleCData {
|
|
3141
2990
|
static _size = native.POINTER_SIZE;
|
|
3142
2991
|
static _type = "pointer";
|
|
3143
|
-
static _reader = (buf, off) =>
|
|
3144
|
-
native.POINTER_SIZE === 8
|
|
3145
|
-
? buf.readBigUInt64LE(off)
|
|
3146
|
-
: BigInt(buf.readUInt32LE(off));
|
|
2992
|
+
static _reader = (buf, off) => (native.POINTER_SIZE === 8 ? buf.readBigUInt64LE(off) : BigInt(buf.readUInt32LE(off)));
|
|
3147
2993
|
static _writer = (buf, off, val) => {
|
|
3148
2994
|
// Accept Buffers (pointer to memory) and struct proxies with _buffer
|
|
3149
2995
|
if (Buffer.isBuffer(val)) {
|
|
@@ -3153,12 +2999,7 @@ class c_void_p extends SimpleCData {
|
|
|
3153
2999
|
else buf.writeUInt32LE(Number(v), off);
|
|
3154
3000
|
return;
|
|
3155
3001
|
}
|
|
3156
|
-
if (
|
|
3157
|
-
val &&
|
|
3158
|
-
typeof val === "object" &&
|
|
3159
|
-
val._buffer &&
|
|
3160
|
-
Buffer.isBuffer(val._buffer)
|
|
3161
|
-
) {
|
|
3002
|
+
if (val && typeof val === "object" && val._buffer && Buffer.isBuffer(val._buffer)) {
|
|
3162
3003
|
const addr = addressOf(val._buffer);
|
|
3163
3004
|
const v = typeof addr === "bigint" ? addr : BigInt(addr || 0);
|
|
3164
3005
|
if (native.POINTER_SIZE === 8) buf.writeBigUInt64LE(v, off);
|
|
@@ -3179,10 +3020,7 @@ class c_void_p extends SimpleCData {
|
|
|
3179
3020
|
class c_size_t extends SimpleCData {
|
|
3180
3021
|
static _size = native.POINTER_SIZE;
|
|
3181
3022
|
static _type = "size_t";
|
|
3182
|
-
static _reader = (buf, off) =>
|
|
3183
|
-
native.POINTER_SIZE === 8
|
|
3184
|
-
? buf.readBigUInt64LE(off)
|
|
3185
|
-
: BigInt(buf.readUInt32LE(off));
|
|
3023
|
+
static _reader = (buf, off) => (native.POINTER_SIZE === 8 ? buf.readBigUInt64LE(off) : BigInt(buf.readUInt32LE(off)));
|
|
3186
3024
|
static _writer = (buf, off, val) => {
|
|
3187
3025
|
const v = typeof val === "bigint" ? val : BigInt(val || 0);
|
|
3188
3026
|
if (native.POINTER_SIZE === 8) {
|
|
@@ -3202,27 +3040,15 @@ const _longSize = native.sizeof ? native.sizeof("long") : 4;
|
|
|
3202
3040
|
class c_long extends SimpleCData {
|
|
3203
3041
|
static _size = _longSize;
|
|
3204
3042
|
static _type = "long";
|
|
3205
|
-
static _reader =
|
|
3206
|
-
|
|
3207
|
-
? (buf, off) => buf.readBigInt64LE(off)
|
|
3208
|
-
: (buf, off) => buf.readInt32LE(off);
|
|
3209
|
-
static _writer =
|
|
3210
|
-
_longSize === 8
|
|
3211
|
-
? (buf, off, val) => buf.writeBigInt64LE(BigInt(val), off)
|
|
3212
|
-
: (buf, off, val) => buf.writeInt32LE(val, off);
|
|
3043
|
+
static _reader = _longSize === 8 ? (buf, off) => buf.readBigInt64LE(off) : (buf, off) => buf.readInt32LE(off);
|
|
3044
|
+
static _writer = _longSize === 8 ? (buf, off, val) => buf.writeBigInt64LE(BigInt(val), off) : (buf, off, val) => buf.writeInt32LE(val, off);
|
|
3213
3045
|
}
|
|
3214
3046
|
|
|
3215
3047
|
class c_ulong extends SimpleCData {
|
|
3216
3048
|
static _size = _longSize;
|
|
3217
3049
|
static _type = "ulong";
|
|
3218
|
-
static _reader =
|
|
3219
|
-
|
|
3220
|
-
? (buf, off) => buf.readBigUInt64LE(off)
|
|
3221
|
-
: (buf, off) => buf.readUInt32LE(off);
|
|
3222
|
-
static _writer =
|
|
3223
|
-
_longSize === 8
|
|
3224
|
-
? (buf, off, val) => buf.writeBigUInt64LE(BigInt(val), off)
|
|
3225
|
-
: (buf, off, val) => buf.writeUInt32LE(val, off);
|
|
3050
|
+
static _reader = _longSize === 8 ? (buf, off) => buf.readBigUInt64LE(off) : (buf, off) => buf.readUInt32LE(off);
|
|
3051
|
+
static _writer = _longSize === 8 ? (buf, off, val) => buf.writeBigUInt64LE(BigInt(val), off) : (buf, off, val) => buf.writeUInt32LE(val, off);
|
|
3226
3052
|
}
|
|
3227
3053
|
|
|
3228
3054
|
// ============================================================================
|
|
@@ -3232,10 +3058,7 @@ class c_ulong extends SimpleCData {
|
|
|
3232
3058
|
class c_char_p extends SimpleCData {
|
|
3233
3059
|
static _size = native.POINTER_SIZE;
|
|
3234
3060
|
static _type = "char_p";
|
|
3235
|
-
static _reader = (buf, off) =>
|
|
3236
|
-
native.POINTER_SIZE === 8
|
|
3237
|
-
? buf.readBigUInt64LE(off)
|
|
3238
|
-
: BigInt(buf.readUInt32LE(off));
|
|
3061
|
+
static _reader = (buf, off) => (native.POINTER_SIZE === 8 ? buf.readBigUInt64LE(off) : BigInt(buf.readUInt32LE(off)));
|
|
3239
3062
|
static _writer = (buf, off, val) => {
|
|
3240
3063
|
if (Buffer.isBuffer(val)) {
|
|
3241
3064
|
const addr = addressOf(val);
|
|
@@ -3259,10 +3082,7 @@ class c_char_p extends SimpleCData {
|
|
|
3259
3082
|
class c_wchar_p extends SimpleCData {
|
|
3260
3083
|
static _size = native.POINTER_SIZE;
|
|
3261
3084
|
static _type = "wchar_p";
|
|
3262
|
-
static _reader = (buf, off) =>
|
|
3263
|
-
native.POINTER_SIZE === 8
|
|
3264
|
-
? buf.readBigUInt64LE(off)
|
|
3265
|
-
: BigInt(buf.readUInt32LE(off));
|
|
3085
|
+
static _reader = (buf, off) => (native.POINTER_SIZE === 8 ? buf.readBigUInt64LE(off) : BigInt(buf.readUInt32LE(off)));
|
|
3266
3086
|
static _writer = (buf, off, val) => {
|
|
3267
3087
|
if (Buffer.isBuffer(val)) {
|
|
3268
3088
|
const addr = addressOf(val);
|
|
@@ -3319,9 +3139,7 @@ function create_string_buffer(init) {
|
|
|
3319
3139
|
buf[init.length] = 0; // null terminator
|
|
3320
3140
|
return buf;
|
|
3321
3141
|
}
|
|
3322
|
-
throw new TypeError(
|
|
3323
|
-
"create_string_buffer requires number, string, or Buffer",
|
|
3324
|
-
);
|
|
3142
|
+
throw new TypeError("create_string_buffer requires number, string, or Buffer");
|
|
3325
3143
|
}
|
|
3326
3144
|
|
|
3327
3145
|
/**
|