UNPKG

@javelin/net

Version:

Networking protocol and utilities for Javelin ECS.

132 lines 4.11 kB
import * as Core from "@javelin/core"; import * as Pack from "@javelin/pack"; const BYTE_VIEWS = [ Pack.uint8, Pack.uint16, Pack.uint32, Pack.int8, Pack.int16, Pack.int32, Pack.float32, Pack.float64, Pack.string8, Pack.string16, Pack.boolean, ]; const BYTE_VIEWS_LOOKUP = BYTE_VIEWS.reduce((sparse, byteView) => { sparse[byteView[Pack.$byteView]] = byteView; return sparse; }, []); const COLLECTION_MASK = 1 << 6; const SCHEMA_MASK = 1 << 7; function encodeField(byteView, out, offset = 0) { var _a; out.push(byteView[Pack.$byteView]); offset++; if (byteView[Core.$kind] === Core.FieldKind.String) { out.push((_a = byteView.length) !== null && _a !== void 0 ? _a : 0); offset++; } return offset; } function encodeNode(node, out, offset = 0) { if (Core.isField(node)) { if (Core.isPrimitiveField(node)) { offset = encodeField(node, out, offset); } else { out.push(node[Core.$kind] | COLLECTION_MASK); offset++; if ("key" in node) { offset = encodeField(node.key, out, offset); } offset = encodeNode(node.element, out, offset); } } else { const length = node.fields.length; out.push(length | SCHEMA_MASK); offset++; for (let i = 0; i < length; i++) { const key = node.keys[i]; out.push(key.length); offset++; for (let i = 0; i < key.length; i++) { out.push(key.charCodeAt(i)); offset++; } offset = encodeNode(node.fields[i], out, offset); } } return offset; } export function encodeModel(model) { const flat = []; let size = 0; for (const prop in model) { flat.push(+prop); size += encodeNode(model[prop], flat) + 1; } const buffer = new ArrayBuffer(size); const encoded = new Uint8Array(buffer); for (let i = 0; i < flat.length; i++) { encoded[i] = flat[i]; } return buffer; } export function decodeField(encoded, cursor) { const dataTypeId = encoded[cursor.offset++]; let child; if ((dataTypeId & SCHEMA_MASK) !== 0) { let length = dataTypeId & ~SCHEMA_MASK; child = {}; while (length-- > 0) { let keySize = encoded[cursor.offset++]; let key = ""; while (keySize-- > 0) { key += String.fromCharCode(encoded[cursor.offset++]); } child[key] = decodeField(encoded, cursor); } } else if ((dataTypeId & COLLECTION_MASK) !== 0) { const collectionType = dataTypeId & ~COLLECTION_MASK; switch (collectionType) { case Core.FieldKind.Array: child = Core.arrayOf(decodeField(encoded, cursor)); break; case Core.FieldKind.Object: { const key = decodeField(encoded, cursor); child = Core.objectOf(decodeField(encoded, cursor), key); break; } case Core.FieldKind.Set: child = Core.setOf(decodeField(encoded, cursor)); break; case Core.FieldKind.Map: child = Core.mapOf(decodeField(encoded, cursor), decodeField(encoded, cursor)); break; default: child = Core.dynamic(); break; } } else { child = BYTE_VIEWS_LOOKUP[dataTypeId]; if (Pack.isStringView(child)) { child = { ...child, length: encoded[cursor.offset++] }; } } return child; } export function decodeModel(dataView, cursor, length) { const config = new Map(); const encoded = new Uint8Array(dataView.buffer); while (cursor.offset < length) { const schemaId = encoded[cursor.offset++]; const schema = decodeField(encoded, cursor); config.set(schemaId, schema); } return Core.createModel(config); } //# sourceMappingURL=model.js.map