Compare commits
2 Commits
f785493ec2
...
cdd6564b51
Author | SHA1 | Date | |
---|---|---|---|
cdd6564b51 | |||
9bc48fc0c0 |
@ -1,6 +1,6 @@
|
|||||||
import { BaseTypeHandler, CompoundTypeHandler } from './type-handler.mjs';
|
import { BaseTypeHandler, CompoundTypeHandler } from './type-handler.mjs';
|
||||||
|
|
||||||
export { BASIC_TYPES, FixedArrayHandler, DynamicArrayHandler, CompoundTypeHandler } from './type-handler.mjs';
|
export { BASIC_TYPES } from './type-handler.mjs';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Serializes JavaScript value to binary.
|
* Serializes JavaScript value to binary.
|
||||||
|
@ -4,7 +4,8 @@
|
|||||||
"main": "index.mjs",
|
"main": "index.mjs",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@og/error-utils": "file:../error-utils",
|
"@og/error-utils": "file:../error-utils",
|
||||||
|
"@og/utility": "file:../utility",
|
||||||
"@og/uuid": "file:../uuid",
|
"@og/uuid": "file:../uuid",
|
||||||
"@og/utility": "file:../utility"
|
"buffer": "^6.0.3"
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,4 +1,4 @@
|
|||||||
import { BASIC_TYPES, FixedArrayHandler, DynamicArrayHandler, CompoundTypeHandler, serializeToBinary, deserializeFromBinary } from '../index.mjs';
|
import { BASIC_TYPES, serializeToBinary, deserializeFromBinary } from '../index.mjs';
|
||||||
import assert from 'node:assert/strict';
|
import assert from 'node:assert/strict';
|
||||||
import { areArrayBuffersEqual } from '@og/utility';
|
import { areArrayBuffersEqual } from '@og/utility';
|
||||||
import { UUID } from '@og/uuid';
|
import { UUID } from '@og/uuid';
|
||||||
@ -82,13 +82,13 @@ describe('binary-struct', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('type u16[]', () => {
|
it('type u16[]', () => {
|
||||||
let res = serializeToBinary([0x1770, 0x3c3a, 0x9012], new DynamicArrayHandler(BASIC_TYPES.u16));
|
let res = serializeToBinary([0x1770, 0x3c3a, 0x9012], BASIC_TYPES.array(BASIC_TYPES.u16));
|
||||||
let ans = new Uint8Array([0x03, 0x00, 0x00, 0x00, 0x70, 0x17, 0x3a, 0x3c, 0x12, 0x90]);
|
let ans = new Uint8Array([0x03, 0x00, 0x00, 0x00, 0x70, 0x17, 0x3a, 0x3c, 0x12, 0x90]);
|
||||||
assert.ok(areArrayBuffersEqual(res, ans));
|
assert.ok(areArrayBuffersEqual(res, ans));
|
||||||
});
|
});
|
||||||
|
|
||||||
it('type u16[3]', () => {
|
it('type u16[3]', () => {
|
||||||
let res = serializeToBinary([0x1770, 0x3c3a, 0x9012], new FixedArrayHandler(3, BASIC_TYPES.u16));
|
let res = serializeToBinary([0x1770, 0x3c3a, 0x9012], BASIC_TYPES.FixedArray(3, BASIC_TYPES.u16));
|
||||||
let ans = new Uint8Array([0x70, 0x17, 0x3a, 0x3c, 0x12, 0x90]);
|
let ans = new Uint8Array([0x70, 0x17, 0x3a, 0x3c, 0x12, 0x90]);
|
||||||
assert.ok(areArrayBuffersEqual(res, ans));
|
assert.ok(areArrayBuffersEqual(res, ans));
|
||||||
});
|
});
|
||||||
@ -104,6 +104,18 @@ describe('binary-struct', () => {
|
|||||||
let ans = new Uint8Array([0x80, 0x30, 0x18, 0x46, 0, 0, 0, 0]);
|
let ans = new Uint8Array([0x80, 0x30, 0x18, 0x46, 0, 0, 0, 0]);
|
||||||
assert.ok(areArrayBuffersEqual(res, ans));
|
assert.ok(areArrayBuffersEqual(res, ans));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('type Buffer', () => {
|
||||||
|
let ans = new Uint8Array([0x3c, 0x3d, 0x3e, 0x3f]).buffer;
|
||||||
|
let res = serializeToBinary(Buffer.from(ans), BASIC_TYPES.raw(4));
|
||||||
|
assert.ok(areArrayBuffersEqual(res, ans));
|
||||||
|
});
|
||||||
|
|
||||||
|
it('type StringMap', () => {
|
||||||
|
let res = serializeToBinary(new Map([['aa', 'b'], ['hi', 'hello']]), BASIC_TYPES.StringMap);
|
||||||
|
let ans = new Uint8Array([0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x61, 0x61, 0x01, 0x00, 0x00, 0x00, 0x62, 0x02, 0x00, 0x00, 0x00, 0x68, 0x69, 0x05, 0x00, 0x00, 0x00, 0x68, 0x65, 0x6c, 0x6c, 0x6f]).buffer;
|
||||||
|
assert.ok(areArrayBuffersEqual(res, ans));
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('deserializeFromBinary', () => {
|
describe('deserializeFromBinary', () => {
|
||||||
@ -179,14 +191,14 @@ describe('binary-struct', () => {
|
|||||||
|
|
||||||
it('type u16[]', () => {
|
it('type u16[]', () => {
|
||||||
let binary_data = new Uint8Array([0x03, 0x00, 0x00, 0x00, 0x70, 0x17, 0x3a, 0x3c, 0x12, 0x90]).buffer;
|
let binary_data = new Uint8Array([0x03, 0x00, 0x00, 0x00, 0x70, 0x17, 0x3a, 0x3c, 0x12, 0x90]).buffer;
|
||||||
let res = deserializeFromBinary(new DataView(binary_data), new DynamicArrayHandler(BASIC_TYPES.u16));
|
let res = deserializeFromBinary(new DataView(binary_data), BASIC_TYPES.array(BASIC_TYPES.u16));
|
||||||
let ans = [0x1770, 0x3c3a, 0x9012];
|
let ans = [0x1770, 0x3c3a, 0x9012];
|
||||||
assert.deepEqual(res, ans);
|
assert.deepEqual(res, ans);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('type u16[3]', () => {
|
it('type u16[3]', () => {
|
||||||
let binary_data = new Uint8Array([0x70, 0x17, 0x3a, 0x3c, 0x12, 0x90]).buffer;
|
let binary_data = new Uint8Array([0x70, 0x17, 0x3a, 0x3c, 0x12, 0x90]).buffer;
|
||||||
let res = deserializeFromBinary(new DataView(binary_data), new FixedArrayHandler(3, BASIC_TYPES.u16));
|
let res = deserializeFromBinary(new DataView(binary_data), BASIC_TYPES.FixedArray(3, BASIC_TYPES.u16));
|
||||||
let ans = [0x1770, 0x3c3a, 0x9012];
|
let ans = [0x1770, 0x3c3a, 0x9012];
|
||||||
assert.deepEqual(res, ans);
|
assert.deepEqual(res, ans);
|
||||||
});
|
});
|
||||||
@ -206,5 +218,18 @@ describe('binary-struct', () => {
|
|||||||
let ans = new Date("2007-04-08");
|
let ans = new Date("2007-04-08");
|
||||||
assert.equal(ans.toUTCString(), res.toUTCString());
|
assert.equal(ans.toUTCString(), res.toUTCString());
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('type Buffer', () => {
|
||||||
|
let binary_data = new Uint8Array([0x3c, 0x3d, 0x3e, 0x3f]).buffer;
|
||||||
|
let res = deserializeFromBinary(new DataView(binary_data), BASIC_TYPES.raw(4));
|
||||||
|
assert.deepEqual(Buffer.from(binary_data), res);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('type StringMap', () => {
|
||||||
|
let binary_data = new Uint8Array([0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x61, 0x61, 0x01, 0x00, 0x00, 0x00, 0x62, 0x02, 0x00, 0x00, 0x00, 0x68, 0x69, 0x05, 0x00, 0x00, 0x00, 0x68, 0x65, 0x6c, 0x6c, 0x6f]).buffer;
|
||||||
|
let res = deserializeFromBinary(new DataView(binary_data), BASIC_TYPES.StringMap);
|
||||||
|
let ans = new Map([['aa', 'b'], ['hi', 'hello']]);
|
||||||
|
assert.deepEqual(res, ans);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import { VirtualMethodNotImplementedError } from '@og/error-utils';
|
import { VirtualMethodNotImplementedError } from '@og/error-utils';
|
||||||
import { UUID } from '@og/uuid';
|
import { UUID } from '@og/uuid';
|
||||||
|
import { Buffer } from 'buffer';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents the result of deserialization.
|
* Represents the result of deserialization.
|
||||||
@ -551,6 +552,13 @@ export class VoidHandler extends BaseTypeHandler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getHandlerObject(type) {
|
||||||
|
if (type instanceof BaseTypeHandler) {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
return new CompoundTypeHandler(type);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles array of a fixed length with elements of the same type.
|
* Handles array of a fixed length with elements of the same type.
|
||||||
* @extends {BaseTypeHandler}
|
* @extends {BaseTypeHandler}
|
||||||
@ -565,7 +573,7 @@ export class FixedArrayHandler extends BaseTypeHandler {
|
|||||||
constructor(n, element_handler) {
|
constructor(n, element_handler) {
|
||||||
super();
|
super();
|
||||||
this.n = n;
|
this.n = n;
|
||||||
this.element_handler = element_handler;
|
this.element_handler = getHandlerObject(element_handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -612,6 +620,56 @@ export class FixedArrayHandler extends BaseTypeHandler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles raw binary buffer of a fixed length.
|
||||||
|
* @extends {BaseTypeHandler}
|
||||||
|
* @class
|
||||||
|
*/
|
||||||
|
export class RawBufferHandler extends BaseTypeHandler {
|
||||||
|
/**
|
||||||
|
* Constructor for RawBufferHandler.
|
||||||
|
* @param {number} n - The fixed length of the buffer.
|
||||||
|
*/
|
||||||
|
constructor(n) {
|
||||||
|
super();
|
||||||
|
this.n = n;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the size of the serialized fixed-length buffer in bytes.
|
||||||
|
* @param {Buffer} value - The array to calculate the size for.
|
||||||
|
* @returns {number} - The size of the serialized fixed-length array in bytes.
|
||||||
|
*/
|
||||||
|
sizeof(value) {
|
||||||
|
return value.byteLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Serializes the fixed-length buffer and writes it to the DataView at the specified offset.
|
||||||
|
* @param {DataView} view - The DataView to write to.
|
||||||
|
* @param {number} offset - The offset to start writing at.
|
||||||
|
* @param {Buffer} value - The fixed-length buffer to be serialized.
|
||||||
|
* @returns {number} - The new offset after serialization.
|
||||||
|
*/
|
||||||
|
serialize(view, offset, value) {
|
||||||
|
for (let i = 0; i < this.n; i += 1) {
|
||||||
|
view.setUint8(offset + i, value.readUInt8(offset + i));
|
||||||
|
}
|
||||||
|
return offset + this.n;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deserializes the fixed-length array from the DataView at the specified offset.
|
||||||
|
* @param {DataView} view - The DataView to read from.
|
||||||
|
* @param {number} offset - The offset to start reading from.
|
||||||
|
* @returns {DeserializedResult} - The deserialized result containing the fixed-length array and a new offset.
|
||||||
|
*/
|
||||||
|
deserialize(view, offset) {
|
||||||
|
const res = Buffer.from(view.buffer, offset, this.n);
|
||||||
|
return new DeserializedResult(res, offset + this.n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles dynamic arrays with elements of the same type.
|
* Handles dynamic arrays with elements of the same type.
|
||||||
* @extends {BaseTypeHandler}
|
* @extends {BaseTypeHandler}
|
||||||
@ -624,7 +682,7 @@ export class DynamicArrayHandler extends BaseTypeHandler {
|
|||||||
*/
|
*/
|
||||||
constructor(element_handler) {
|
constructor(element_handler) {
|
||||||
super();
|
super();
|
||||||
this.element_handler = element_handler;
|
this.element_handler = getHandlerObject(element_handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -675,6 +733,74 @@ export class DynamicArrayHandler extends BaseTypeHandler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles map with keys and values are of the same type.
|
||||||
|
* @extends {BaseTypeHandler}
|
||||||
|
* @class
|
||||||
|
*/
|
||||||
|
export class MapHandler extends BaseTypeHandler {
|
||||||
|
/**
|
||||||
|
* Constructor for MapHandler.
|
||||||
|
* @param {BaseTypeHandler} key_handler - The handler for keys of the map.
|
||||||
|
* @param {BaseTypeHandler} value_handler - The handler for values of the map.
|
||||||
|
*/
|
||||||
|
constructor(key_handler, value_handler) {
|
||||||
|
super();
|
||||||
|
this.key_handler = getHandlerObject(key_handler);
|
||||||
|
this.value_handler = getHandlerObject(value_handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the size of the serialized map in bytes.
|
||||||
|
* @param {Map} value - The map to calculate the size for.
|
||||||
|
* @returns {number} - The size of the serialized map in bytes.
|
||||||
|
*/
|
||||||
|
sizeof(value) {
|
||||||
|
let res = 4;
|
||||||
|
for (const [k, v] of value) {
|
||||||
|
res += this.key_handler.sizeof(k);
|
||||||
|
res += this.value_handler.sizeof(v);
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Serializes the map and writes it to the DataView at the specified offset.
|
||||||
|
* @param {DataView} view - The DataView to write to.
|
||||||
|
* @param {number} offset - The offset to start writing at.
|
||||||
|
* @param {Map} value - The map to be serialized.
|
||||||
|
* @returns {number} - The new offset after serialization.
|
||||||
|
*/
|
||||||
|
serialize(view, offset, value) {
|
||||||
|
view.setUint32(offset, value.size, true);
|
||||||
|
offset += 4;
|
||||||
|
for (const [k, v] of value) {
|
||||||
|
offset = this.key_handler.serialize(view, offset, k);
|
||||||
|
offset = this.value_handler.serialize(view, offset, v);
|
||||||
|
}
|
||||||
|
return offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deserializes the map from the DataView at the specified offset.
|
||||||
|
* @param {DataView} view - The DataView to read from.
|
||||||
|
* @param {number} offset - The offset to start reading from.
|
||||||
|
* @returns {DeserializedResult} - The deserialized result containing the map and a new offset.
|
||||||
|
*/
|
||||||
|
deserialize(view, offset) {
|
||||||
|
const size = view.getUint32(offset, true);
|
||||||
|
offset += 4;
|
||||||
|
const res = new Map();
|
||||||
|
for (let i = 0; i < size; i += 1) {
|
||||||
|
const resk = this.key_handler.deserialize(view, offset);
|
||||||
|
const resv = this.value_handler.deserialize(view, resk.offset);
|
||||||
|
offset = resv.offset;
|
||||||
|
res.set(resk.value, resv.value);
|
||||||
|
}
|
||||||
|
return new DeserializedResult(res, offset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles storage and serialization of UUID objects using a 16-byte buffer.
|
* Handles storage and serialization of UUID objects using a 16-byte buffer.
|
||||||
* @extends {BaseTypeHandler}
|
* @extends {BaseTypeHandler}
|
||||||
@ -848,7 +974,7 @@ export class CompoundTypeHandler extends BaseTypeHandler {
|
|||||||
let res = 0;
|
let res = 0;
|
||||||
for (let i = 0; i < this.typedef.length; i += 1) {
|
for (let i = 0; i < this.typedef.length; i += 1) {
|
||||||
const field_name = this.typedef[i].field;
|
const field_name = this.typedef[i].field;
|
||||||
const field_handler = this.typedef[i].type;
|
const field_handler = getHandlerObject(this.typedef[i].type);
|
||||||
res += field_handler.sizeof(value[field_name]);
|
res += field_handler.sizeof(value[field_name]);
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
@ -864,7 +990,7 @@ export class CompoundTypeHandler extends BaseTypeHandler {
|
|||||||
serialize(view, offset, value) {
|
serialize(view, offset, value) {
|
||||||
for (let i = 0; i < this.typedef.length; i += 1) {
|
for (let i = 0; i < this.typedef.length; i += 1) {
|
||||||
const field_name = this.typedef[i].field;
|
const field_name = this.typedef[i].field;
|
||||||
const field_handler = this.typedef[i].type;
|
const field_handler = getHandlerObject(this.typedef[i].type);
|
||||||
offset = field_handler.serialize(view, offset, value[field_name]);
|
offset = field_handler.serialize(view, offset, value[field_name]);
|
||||||
}
|
}
|
||||||
return offset;
|
return offset;
|
||||||
@ -880,7 +1006,7 @@ export class CompoundTypeHandler extends BaseTypeHandler {
|
|||||||
let res = new this.type();
|
let res = new this.type();
|
||||||
for (let i = 0; i < this.typedef.length; i += 1) {
|
for (let i = 0; i < this.typedef.length; i += 1) {
|
||||||
const field_name = this.typedef[i].field;
|
const field_name = this.typedef[i].field;
|
||||||
const field_handler = this.typedef[i].type;
|
const field_handler = getHandlerObject(this.typedef[i].type);
|
||||||
const tmp = field_handler.deserialize(view, offset);
|
const tmp = field_handler.deserialize(view, offset);
|
||||||
res[field_name] = tmp.value;
|
res[field_name] = tmp.value;
|
||||||
offset = tmp.offset;
|
offset = tmp.offset;
|
||||||
@ -908,4 +1034,10 @@ export const BASIC_TYPES = {
|
|||||||
uuid: new UUIDHandler(),
|
uuid: new UUIDHandler(),
|
||||||
str: new StringHandler(),
|
str: new StringHandler(),
|
||||||
DateTime: new DateHandler(),
|
DateTime: new DateHandler(),
|
||||||
|
|
||||||
|
array: (type) => new DynamicArrayHandler(type),
|
||||||
|
FixedArray: (n, type) => new FixedArrayHandler(n, type),
|
||||||
|
raw: (n) => new RawBufferHandler(n),
|
||||||
|
map: (k, v) => new MapHandler(k, v),
|
||||||
|
StringMap: new MapHandler(new StringHandler(), new StringHandler()),
|
||||||
};
|
};
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
import { Queue } from './queue.mjs';
|
import { Queue } from './queue.mjs';
|
||||||
|
|
||||||
import { Queue } from './queue.mjs';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents an asynchronous lock for managing access to a shared resource.
|
* Represents an asynchronous lock for managing access to a shared resource.
|
||||||
* @class
|
* @class
|
||||||
|
Loading…
x
Reference in New Issue
Block a user