redesign type-handler

This commit is contained in:
方而静 2024-02-10 15:29:34 +08:00
parent d1520baa61
commit 023e8e34f9
Signed by: szTom
GPG Key ID: 072D999D60C6473C

View File

@ -1,455 +1,773 @@
import { VirtualMethodNotImplementedError } from '@og/error-utils';
import { UUID } from '@og/uuid';
/**
* Represents the result of deserialization.
* @class
*/
export class DeserializedResult {
/**
* @constructor
* @param {any} value - The deserialized value.
* @param {number} offset - The offset after deserialization.
*/
constructor(value, offset) {
this.value = value;
this.offset = offset;
}
}
/**
* Base class for handling basic data types.
* @abstract
* @class
*/
export class BasicTypeHandler {
/**
* Gets the size of the serialized value in bytes.
* @abstract
* @param {any} value - The value to be serialized.
* @returns {number} - The size of the serialized value in bytes.
*/
sizeof(value) {
throw new VirtualMethodNotImplementedError();
}
/**
* Serializes the value and writes it to the DataView at the specified offset.
* @abstract
* @param {DataView} view - The DataView to write to.
* @param {number} offset - The offset to start writing at.
* @param {any} value - The value to be serialized.
* @returns {number} - The new offset after serialization.
*/
serialize(view, offset, value) {
throw new VirtualMethodNotImplementedError();
}
/**
* Deserializes the value from the DataView at the specified offset.
* @abstract
* @param {DataView} view - The DataView to read from.
* @param {number} offset - The offset to start reading from.
* @returns {DeserializedResult} - The deserialized result.
*/
deserialize(view, offset) {
throw new VirtualMethodNotImplementedError();
}
};
}
/**
* Handles 8-bit signed integers (int8).
* @extends {BasicTypeHandler}
* @class
*/
export class Int8Handler extends BasicTypeHandler {
/**
* Gets the size of the serialized int8 value in bytes (always 1).
* @param {number} _value - The int8 value.
* @returns {number} - The size of the serialized int8 value in bytes.
*/
sizeof(_value) {
return 1;
}
/**
*
* @param {DataView} view
* @param {number} offset
* @param {number} value
* Serializes the int8 value 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 {number} value - The int8 value to be serialized.
* @returns {number} - The new offset after serialization.
*/
serialize(view, offset, value) {
view.setInt8(offset, value);
return offset + 1;
}
/**
*
* @param {DataView} view
* @param {number} offset
* @returns {number}
* Deserializes the int8 value 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 int8 value and a new offset.
*/
deserialize(view, offset) {
return view.getInt8(offset);
return new DeserializedResult(view.getInt8(offset), offset + 1);
}
}
/**
* Handles 16-bit signed integers (int16).
* @extends {BasicTypeHandler}
* @class
*/
export class Int16Handler extends BasicTypeHandler {
/**
* @param {number} _value
* @returns {number}
* Gets the size of the serialized int16 value in bytes (always 2).
* @param {number} _value - The int16 value.
* @returns {number} - The size of the serialized int16 value in bytes.
*/
sizeof(_value) {
return 2;
}
/**
* @param {DataView} view
* @param {number} offset
* @param {number} value
* Serializes the int16 value 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 {number} value - The int16 value to be serialized.
* @returns {number} - The new offset after serialization.
*/
serialize(view, offset, value) {
view.setInt16(offset, value);
return offset + 2;
}
/**
* @param {DataView} view
* @param {number} offset
* @returns {number}
* Deserializes the int16 value 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 int16 value and a new offset.
*/
deserialize(view, offset) {
return view.getInt16(offset);
return new DeserializedResult(view.getInt16(offset), offset + 2);
}
}
/**
* Handles 32-bit signed integers (int32).
* @extends {BasicTypeHandler}
* @class
*/
export class Int32Handler extends BasicTypeHandler {
/**
* @param {number} _value
* @returns {number}
* Gets the size of the serialized int32 value in bytes (always 4).
* @param {number} _value - The int32 value.
* @returns {number} - The size of the serialized int32 value in bytes.
*/
sizeof(_value) {
return 4;
}
/**
* @param {DataView} view
* @param {number} offset
* @param {number} value
* Serializes the int32 value 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 {number} value - The int32 value to be serialized.
* @returns {number} - The new offset after serialization.
*/
serialize(view, offset, value) {
view.setInt32(offset, value);
return offset + 4;
}
/**
* @param {DataView} view
* @param {number} offset
* @returns {number}
* Deserializes the int32 value 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 int32 value and a new offset.
*/
deserialize(view, offset) {
return view.getInt32(offset);
return new DeserializedResult(view.getInt32(offset), offset + 4);
}
}
/**
* Handles 64-bit signed integers (int64).
* @extends {BasicTypeHandler}
* @class
*/
export class Int64Handler extends BasicTypeHandler {
/**
* @param {number} _value
* @returns {number}
* Gets the size of the serialized int64 value in bytes (always 8).
* @param {BigInt} _value - The int64 value.
* @returns {number} - The size of the serialized int64 value in bytes.
*/
sizeof(_value) {
return 8;
}
/**
* @param {DataView} view
* @param {number} offset
* @param {BigInt} value
* Serializes the int64 value 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 {BigInt} value - The int64 value to be serialized.
* @returns {number} - The new offset after serialization.
*/
serialize(view, offset, value) {
view.setBigInt64(offset, value);
return offset + 8;
}
/**
* @param {DataView} view
* @param {number} offset
* @returns {BigInt}
* Deserializes the int64 value 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 int64 value and a new offset.
*/
deserialize(view, offset) {
return view.getBigInt64(offset);
return new DeserializedResult(view.getBigInt64(offset), offset + 8);
}
}
/**
* Handles 8-bit unsigned integers (uint8).
* @extends {BasicTypeHandler}
* @class
*/
export class Uint8Handler extends BasicTypeHandler {
/**
* @param {number} _value
* @returns {number}
* Gets the size of the serialized uint8 value in bytes (always 1).
* @param {number} _value - The uint8 value.
* @returns {number} - The size of the serialized uint8 value in bytes.
*/
sizeof(_value) {
return 1;
}
/**
* @param {DataView} view
* @param {number} offset
* @param {number} value
* Serializes the uint8 value 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 {number} value - The uint8 value to be serialized.
* @returns {number} - The new offset after serialization.
*/
serialize(view, offset, value) {
view.setUint8(offset, value);
return offset + 1;
}
/**
* @param {DataView} view
* @param {number} offset
* @returns {number}
* Deserializes the uint8 value 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 uint8 value and a new offset.
*/
deserialize(view, offset) {
return view.getUint8(offset);
return new DeserializedResult(view.getUint8(offset), offset + 1);
}
}
/**
* Handles 16-bit unsigned integers (uint16).
* @extends {BasicTypeHandler}
* @class
*/
export class Uint16Handler extends BasicTypeHandler {
/**
* @param {number} _value
* @returns {number}
* Gets the size of the serialized uint16 value in bytes (always 2).
* @param {number} _value - The uint16 value.
* @returns {number} - The size of the serialized uint16 value in bytes.
*/
sizeof(_value) {
return 2;
}
/**
* @param {DataView} view
* @param {number} offset
* @param {number} value
* Serializes the uint16 value 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 {number} value - The uint16 value to be serialized.
* @returns {number} - The new offset after serialization.
*/
serialize(view, offset, value) {
view.setUint16(offset, value);
return offset + 2;
}
/**
* @param {DataView} view
* @param {number} offset
* @returns {number}
* Deserializes the uint16 value 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 uint16 value and a new offset.
*/
deserialize(view, offset) {
return view.getUint16(offset);
return new DeserializedResult(view.getUint16(offset), offset + 2);
}
}
/**
* Handles 32-bit unsigned integers (uint32).
* @extends {BasicTypeHandler}
* @class
*/
export class Uint32Handler extends BasicTypeHandler {
/**
* @param {number} _value
* @returns {number}
* Gets the size of the serialized uint32 value in bytes (always 4).
* @param {number} _value - The uint32 value.
* @returns {number} - The size of the serialized uint32 value in bytes.
*/
sizeof(_value) {
return 4;
}
/**
* @param {DataView} view
* @param {number} offset
* @param {number} value
* Serializes the uint32 value 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 {number} value - The uint32 value to be serialized.
* @returns {number} - The new offset after serialization.
*/
serialize(view, offset, value) {
view.setUint32(offset, value);
return offset + 4;
}
/**
* @param {DataView} view
* @param {number} offset
* @returns {number}
* Deserializes the uint32 value 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 uint32 value and a new offset.
*/
deserialize(view, offset) {
return view.getUint32(offset);
return new DeserializedResult(view.getUint32(offset), offset + 4);
}
}
/**
* Handles 64-bit unsigned integers (uint64).
* @extends {BasicTypeHandler}
* @class
*/
export class Uint64Handler extends BasicTypeHandler {
/**
* @param {number} _value
* @returns {number}
* Gets the size of the serialized uint64 value in bytes (always 8).
* @param {BigInt} _value - The uint64 value.
* @returns {number} - The size of the serialized uint64 value in bytes.
*/
sizeof(_value) {
return 8;
}
/**
* @param {DataView} view
* @param {number} offset
* @param {BigInt} value
* Serializes the uint64 value 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 {BigInt} value - The uint64 value to be serialized.
* @returns {number} - The new offset after serialization.
*/
serialize(view, offset, value) {
view.setBigUint64(offset, value);
return offset + 8;
}
/**
* @param {DataView} view
* @param {number} offset
* @returns {BigInt}
* Deserializes the uint64 value 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 uint64 value and a new offset.
*/
deserialize(view, offset) {
return view.getBigUint64(offset);
return new DeserializedResult(view.getBigUint64(offset), offset + 8);
}
}
export class Float32Handler extends BasicTypeHandler {
/**
* @param {number} _value
* @returns {number}
*/
sizeof(_value) {
return 4;
}
/**
* @param {DataView} view
* @param {number} offset
* @param {number} value
* Handles boolean values (bool).
* @extends {BasicTypeHandler}
* @class
*/
serialize(view, offset, value) {
view.setFloat32(offset, value);
}
/**
* @param {DataView} view
* @param {number} offset
* @returns {number}
*/
deserialize(view, offset) {
return view.getFloat32(offset);
}
}
export class Float64Handler extends BasicTypeHandler {
/**
* @param {number} _value
* @returns {number}
*/
sizeof(_value) {
return 8;
}
/**
* @param {DataView} view
* @param {number} offset
* @param {number} value
*/
serialize(view, offset, value) {
view.setFloat64(offset, value);
}
/**
* @param {DataView} view
* @param {number} offset
* @returns {number}
*/
deserialize(view, offset) {
return view.getFloat64(offset);
}
}
export class BoolHandler extends BasicTypeHandler {
/**
* @param {boolean} _value
* @returns {number}
* Gets the size of the serialized bool value in bytes (always 1).
* @param {boolean} _value - The bool value.
* @returns {number} - The size of the serialized bool value in bytes.
*/
sizeof(_value) {
return 1;
}
/**
* @param {DataView} view
* @param {number} offset
* @param {boolean} value
* Serializes the bool value 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 {boolean} value - The bool value to be serialized.
* @returns {number} - The new offset after serialization.
*/
serialize(view, offset, value) {
view.setUint8(offset, value ? 1 : 0);
return offset + 1;
}
/**
* @param {DataView} view
* @param {number} offset
* @returns {boolean}
* Deserializes the bool value 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 bool value and a new offset.
*/
deserialize(view, offset) {
return view.getUint8(offset) !== 0;
return new DeserializedResult(view.getUint8(offset) !== 0, offset + 1);
}
}
/**
* Handles void values (void).
* @extends {BasicTypeHandler}
* @class
*/
export class VoidHandler extends BasicTypeHandler {
/**
* @returns {number}
* Gets the size of the serialized void value in bytes (always 0).
* @param {*} _value - The void value.
* @returns {number} - The size of the serialized void value in bytes (always 0).
*/
sizeof() {
sizeof(_value) {
return 0;
}
/**
* @param {DataView} _view
* @param {number} _offset
* @param {undefined} _value
* Serializes the void value (does nothing).
* @param {DataView} _view - The DataView to write to (not used).
* @param {number} offset - The offset to start writing at (not used).
* @param {*} _value - The void value (not used).
* @returns {number} - The offset unchanged.
*/
serialize(_view, _offset, _value) {
// Do nothing for Void
serialize(_view, offset, _value) {
return offset;
}
/**
* @param {DataView} _view
* @param {number} _offset
* @returns {undefined}
* Deserializes the void value (does nothing).
* @param {DataView} _view - The DataView to read from (not used).
* @param {number} offset - The offset to start reading from (not used).
* @returns {DeserializedResult} - The offset unchanged and undefined as the value.
*/
deserialize(_view, _offset) {
// Do nothing for Void
deserialize(_view, offset) {
return new DeserializedResult(undefined, offset);
}
}
/**
* Handles array of a fixed length with elements of the same type.
* @extends {BasicTypeHandler}
* @class
*/
export class FixedArrayHandler extends BasicTypeHandler {
/**
* Constructor for FixedArrayHandler.
* @param {number} n - The fixed length of the array.
* @param {BasicTypeHandler} element_handler - The handler for individual elements of the array.
*/
constructor(n, element_handler) {
super();
this.n = n;
this.element_handler = element_handler;
}
/**
* Gets the size of the serialized fixed-length array in bytes.
* @param {Array} value - The array to calculate the size for.
* @returns {number} - The size of the serialized fixed-length array in bytes.
*/
sizeof(value) {
let res = 0;
for (let i = 0; i < this.n; i += 1) {
res += this.element_handler.sizeof(value[i]);
}
return res;
}
/**
* Serializes the fixed-length array 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 {Array} value - The fixed-length array to be serialized.
* @returns {number} - The new offset after serialization.
*/
serialize(view, offset, value) {
for (let i = 0; i < this.n; i += 1) {
offset = this.element_handler.serialize(view, offset, value[i]);
}
return offset;
}
/**
* 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) {
let res = new Array(this.n);
for (let i = 0; i < this.n; i += 1) {
const tmp = this.element_handler.deserialize(view, offset);
res[i] = tmp.value;
offset = tmp.offset;
}
return new DeserializedResult(res, offset);
}
}
/**
* Handles dynamic arrays with elements of the same type.
* @extends {BasicTypeHandler}
* @class
*/
export class DynamicArrayHandler extends BasicTypeHandler {
/**
* Constructor for DynamicArrayHandler.
* @param {BasicTypeHandler} element_handler - The handler for individual elements of the array.
*/
constructor(element_handler) {
super();
this.element_handler = element_handler;
}
/**
* Gets the size of the serialized dynamic array in bytes.
* @param {Array} value - The array to calculate the size for.
* @returns {number} - The size of the serialized dynamic array in bytes.
*/
sizeof(value) {
let size = 4; // For storing the length of the array
for (const element of value) {
size += this.element_handler.sizeof(element);
}
return size;
}
/**
* Serializes the dynamic array 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 {Array} value - The dynamic array to be serialized.
* @returns {number} - The new offset after serialization.
*/
serialize(view, offset, value) {
view.setUint32(offset, value.length);
offset += 4;
for (const element of value) {
offset = this.element_handler.serialize(view, offset, element);
}
return offset;
}
/**
* Deserializes the dynamic 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 dynamic array and a new offset.
*/
deserialize(view, offset) {
const length = view.getUint32(offset);
offset += 4;
const res = new Array(length);
for (let i = 0; i < length; i++) {
const tmp = this.element_handler.deserialize(view, offset);
res[i] = tmp.value;
offset = tmp.offset;
}
return new DeserializedResult(res, offset);
}
}
/**
* Handles storage and serialization of UUID objects using a 16-byte buffer.
* @extends {BasicTypeHandler}
* @class
*/
export class UUIDHandler extends BasicTypeHandler {
/**
* @param {UUID} _value
* @returns {number}
*/
sizeof(_value) {
return 16;
}
/**
* @param {DataView} view
* @param {number} offset
* @param {UUID} value
* Serializes the UUID object and writes it to the buffer at the specified offset.
* @param {DataView} view - The DataView to write to.
* @param {number} offset - The offset to start writing at.
* @param {UUID} value - The UUID object to be serialized.
* @returns {number} - The new offset after serialization.
*/
serialize(view, offset, value) {
const buffer = value.buffer;
for (let i = 0; i < buffer.length; i++) {
view.setUint8(offset + i, buffer[i]);
// Convert UUID to binary data (16 bytes)
const binary_data = new Uint8Array(value.buffer);
// Write binary data to the buffer
for (let i = 0; i < binary_data.length; i++) {
view.setUint8(offset + i, binary_data[i]);
}
return offset + 16; // Move offset to the next position after the UUID
}
/**
* Deserializes the UUID from the buffer 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 object.
*/
deserialize(view, offset) {
// Read 16 bytes from the buffer starting at the given offset
const binary_data = new Uint8Array(16);
for (let i = 0; i < 16; i++) {
binary_data[i] = view.getUint8(offset + i);
}
// Create a new UUID object from the binary data
const uuid = new UUID(binary_data.buffer);
return new DeserializedResult(uuid, offset + 16);
}
}
/**
* @param {DataView} view
* @param {number} offset
* @returns {UUID}
* Handles storage and serialization of strings.
* @extends {BasicTypeHandler}
* @class
*/
deserialize(view, offset) {
const buffer = new Uint8Array(16);
for (let i = 0; i < 16; i++) {
buffer[i] = view.getUint8(offset + i);
}
return new UUID(buffer);
}
}
export class StringHandler extends BasicTypeHandler {
/**
* @param {string} _value
* @returns {number}
* Constructs a StringHandler object.
*/
sizeof(_value) {
// Calculate the size of string in bytes including the 4 bytes for length
return 4 + this.utf8ByteLength(_value);
constructor() {
super();
}
/**
* @param {DataView} view
* @param {number} offset
* @param {string} value
* Gets the size of the serialized string in bytes.
* @param {string} value - The string to calculate the size for.
* @returns {number} - The size of the serialized string in bytes.
*/
sizeof(value) {
// Convert the string to UTF-8 encoding and calculate its byte length
const encoder = new TextEncoder();
const encodedString = encoder.encode(value);
// Calculate the size of the string (length of UTF-8 encoding) plus 4 bytes for storing the length
return encodedString.byteLength + 4;
}
/**
* Serializes the string 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 {string} value - The string to be serialized.
* @returns {number} - The new offset after serialization.
*/
serialize(view, offset, value) {
const utf8_bytes = this.encodeUTF8(value);
// Write string length as 4-byte unsigned integer
view.setUint32(offset, utf8_bytes.length, true);
// Write UTF-8 bytes
for (let i = 0; i < utf8_bytes.length; i++) {
view.setUint8(offset + 4 + i, utf8_bytes[i]);
// Convert the string to UTF-8 encoding
const encoder = new TextEncoder();
const encoded_string = encoder.encode(value);
// Write the length of the string as a uint32 at the specified offset
view.setUint32(offset, encoded_string.length);
offset += 4;
// Write the UTF-8 encoded string to the DataView starting at offset + 4 (after the length)
for (let i = 0; i < encoded_string.length; i++) {
view.setUint8(offset + i, encoded_string[i]);
}
// Return the new offset after serialization
return offset + encoded_string.length;
}
/**
* @param {DataView} view
* @param {number} offset
* @returns {string}
* Deserializes the string 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 string and a new offset.
*/
deserialize(view, offset) {
// Read string length as 4-byte unsigned integer
const length = view.getUint32(offset, true);
// Read UTF-8 bytes
const utf8_bytes = new Uint8Array(length);
for (let i = 0; i < length; i++) {
utf8_bytes[i] = view.getUint8(offset + 4 + i);
}
// Decode UTF-8 bytes to string
return this.decodeUTF8(utf8_bytes);
}
// Read the length of the string as a uint32 at the specified offset
const length = view.getUint32(offset);
offset += 4;
/**
* Encodes a string to UTF-8 bytes.
* @param {string} str
* @returns {Uint8Array}
*/
encodeUTF8(str) {
const encoder = new TextEncoder();
return encoder.encode(str);
}
// Read the UTF-8 encoded string from the DataView starting at offset + 4 (after the length)
const encoded_string = new Uint8Array(view.buffer, offset, length);
/**
* Decodes UTF-8 bytes to a string.
* @param {Uint8Array} bytes
* @returns {string}
*/
decodeUTF8(bytes) {
// Convert the UTF-8 encoded string to a JavaScript string
const decoder = new TextDecoder();
return decoder.decode(bytes);
const decodedString = decoder.decode(encoded_string);
// Return the deserialized string and the new offset
return new DeserializedResult(decodedString, offset + length);
}
}
/**
* Calculates the byte length of a string encoded in UTF-8.
* @param {string} str
* @returns {number}
* Handles the serialization and deserialization of a compound type composed of various fields.
* @extends {BasicTypeHandler}
* @class
*/
utf8ByteLength(str) {
return new TextEncoder().encode(str).length;
export class CompoundTypeHandler extends BasicTypeHandler {
/**
* Constructs a CompoundTypeHandler object for the specified type.
* @param {Function} type - The class representing the compound type.
* @example
* // Define a class Point
* class Point {
* constructor(x, y) {
* this.x = x;
* this.y = y;
* }
* }
*
* // Define the type definition for Point
* Point.prototype.typedef = [
* {field: 'x', handler: new Float32Handler()},
* {field: 'y', handler: new Float32Handler()}
* ];
*
* // Create a CompoundTypeHandler for Point
* const pointHandler = new CompoundTypeHandler(Point);
*/
constructor(type) {
super();
/**
* The class representing the compound type.
* @type {Function}
* @private
*/
this.type = type;
/**
* The type definition specifying the fields and their handlers.
* @type {Array<{field: string, handler: BasicTypeHandler}>}
* @private
*/
this.typedef = type.typedef;
}
/**
* Gets the size of the serialized compound type in bytes.
* @param {Object} value - The instance of the compound type to calculate the size for.
* @returns {number} - The size of the serialized compound type in bytes.
*/
sizeof(value) {
let res = 0;
for (let i = 0; i < this.typedef.length; i += 1) {
const field_name = this.typedef[i].field;
const field_handler = this.typedef[i].handler;
res += field_handler.sizeof(value[field_name]);
}
return res;
}
/**
* Serializes the compound type 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 {Object} value - The instance of the compound type to be serialized.
* @returns {number} - The new offset after serialization.
*/
serialize(view, offset, value) {
for (let i = 0; i < this.typedef.length; i += 1) {
const field_name = this.typedef[i].field;
const field_handler = this.typedef[i].handler;
offset = field_handler.serialize(view, offset, value[field_name]);
}
return offset;
}
/**
* Deserializes the compound type 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 compound type and a new offset.
*/
deserialize(view, offset) {
let res = new this.type();
for (let i = 0; i < this.typedef.length; i += 1) {
const field_name = this.typedef[i].field;
const field_handler = this.typedef[i].handler;
const tmp = field_handler.deserialize(view, offset);
res[field_name] = tmp.value;
offset = tmp.offset;
}
return new DeserializedResult(res, offset);
}
}