UNPKG

@oaklean/profiler-core

Version:

Part of the @oaklean suite. It provides all basic functions to work with the `.oak` file format. It allows parsing the `.oak` file format as well as tools for analyzing the measurement values. It also provides all necessary capabilities required for prec

281 lines 27 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.BufferHelper = exports.PRIMITIVE_BUFFER_TYPES_BYTE_SIZES = void 0; const zlib_1 = __importDefault(require("zlib")); // Types const types_1 = require("../types"); exports.PRIMITIVE_BUFFER_TYPES_BYTE_SIZES = { [types_1.PrimitiveBufferTypes.UInt]: 4, [types_1.PrimitiveBufferTypes.Double]: 8, [types_1.PrimitiveBufferTypes.String2L]: 2 ** 16 - 1, [types_1.PrimitiveBufferTypes.String4L]: 2 ** 32 - 1, [types_1.PrimitiveBufferTypes.Boolean]: 1, [types_1.PrimitiveBufferTypes.UInt8]: 1, }; const VALUE_MAP_HEADER_SIZE = 2; // in bytes class BufferHelper { static numberMapToBuffer(typeMap, values, keyOffset) { // first segmentSize * 8 - 1 bits are used to mark wether a value is present // the (segmentSize * 8)th bit marks wether there comes a valueMap behind const valueIsPresent_Buffer = Buffer.alloc(VALUE_MAP_HEADER_SIZE); const keys = Array.from(Object.keys(typeMap)); const valueBuffers = []; const valueLen = Math.min(VALUE_MAP_HEADER_SIZE * 8 - 1, keys.length - (keyOffset || 0)); for (let i = 0; i < valueLen; i++) { const key = keys[i + (keyOffset || 0)]; const byteSize = typeMap[key]; if (values[key] !== undefined && values[key] !== 0) { switch (byteSize) { case types_1.PrimitiveBufferTypes.UInt: valueBuffers.push(BufferHelper.UIntToBuffer(values[key], key)); break; case types_1.PrimitiveBufferTypes.Double: valueBuffers.push(BufferHelper.DoubleToBuffer(values[key])); break; default: throw new Error('BufferHelper.valueMap: unexpected byte size'); } BufferHelper.setBit(valueIsPresent_Buffer, i, 1); } } if (keys.length - (keyOffset || 0) > VALUE_MAP_HEADER_SIZE * 8 - 1) { const nextBuffer = BufferHelper.numberMapToBuffer(typeMap, values, (keyOffset || 0) + valueLen); if (nextBuffer.subarray(0, VALUE_MAP_HEADER_SIZE).toString('hex') === '00'.repeat(VALUE_MAP_HEADER_SIZE)) { return Buffer.concat([valueIsPresent_Buffer, ...valueBuffers]); } BufferHelper.setBit(valueIsPresent_Buffer, VALUE_MAP_HEADER_SIZE * 8 - 1, 1); // still values to store return Buffer.concat([valueIsPresent_Buffer, ...valueBuffers, nextBuffer]); } return Buffer.concat([valueIsPresent_Buffer, ...valueBuffers]); } static numberMapFromBuffer(typeMap, buffer) { const { result: numberArray, remainingBuffer } = BufferHelper.numberArrayFromBuffer(buffer, typeMap); const result = {}; const keys = Array.from(Object.keys(typeMap)); for (let i = 0; i < keys.length; i++) { result[keys[i]] = numberArray[i] || 0; } return { instance: result, remainingBuffer }; } static numberArrayFromBuffer(buffer, typeMap, keyOffset) { if (buffer.byteLength < 2) { throw new Error('BufferHelper.valueMapFromBuffer: not enough bytes remaining'); } const valueIsPresent_Buffer = buffer.subarray(0, 2); let remainingBuffer = buffer.subarray(2); const keys = Array.from(Object.keys(typeMap)); const data = []; for (let i = 0; i < VALUE_MAP_HEADER_SIZE * 8 - 1; i++) { const key = keys[i + (keyOffset || 0)]; if (BufferHelper.readBit(valueIsPresent_Buffer, i) === 1) { switch (typeMap[key]) { case types_1.PrimitiveBufferTypes.UInt: { const { instance, remainingBuffer: newRemainingBuffer } = BufferHelper.UIntFromBuffer(remainingBuffer); remainingBuffer = newRemainingBuffer; data.push(instance); } break; case types_1.PrimitiveBufferTypes.Double: { const { instance, remainingBuffer: newRemainingBuffer } = BufferHelper.DoubleFromBuffer(remainingBuffer); remainingBuffer = newRemainingBuffer; data.push(instance); } break; default: throw new Error('SensorValues.toBuffer: unexpected primitive buffer type'); } } else { data.push(0); } } if (keys.length - (keyOffset || 0) > VALUE_MAP_HEADER_SIZE * 8 - 1 && BufferHelper.readBit(valueIsPresent_Buffer, VALUE_MAP_HEADER_SIZE * 8 - 1) === 1) { // still values to read const { result, remainingBuffer: remainingBuffer_childCall } = BufferHelper.numberArrayFromBuffer(remainingBuffer, typeMap, (keyOffset || 0) + VALUE_MAP_HEADER_SIZE * 8 - 1); return { result: [...data, ...result], remainingBuffer: remainingBuffer_childCall }; } return { result: data, remainingBuffer: remainingBuffer }; } static UInt8ToBuffer(tinyInt) { if (tinyInt < 0 || tinyInt > 2 ** (exports.PRIMITIVE_BUFFER_TYPES_BYTE_SIZES[types_1.PrimitiveBufferTypes.UInt8] * 8) - 1) { throw new Error(`BufferHelper.TIntToBuffer: value out of domain: ${tinyInt}`); } const result = Buffer.alloc(exports.PRIMITIVE_BUFFER_TYPES_BYTE_SIZES[types_1.PrimitiveBufferTypes.UInt8]); result.writeUInt8(tinyInt); return result; } static UInt8FromBuffer(buffer) { if (buffer.byteLength < exports.PRIMITIVE_BUFFER_TYPES_BYTE_SIZES[types_1.PrimitiveBufferTypes.UInt8]) { throw new Error('BufferHelper.TIntFromBuffer: not enough bytes remaining'); } const instance = buffer.readUInt8(); return { instance: instance, remainingBuffer: buffer.subarray(exports.PRIMITIVE_BUFFER_TYPES_BYTE_SIZES[types_1.PrimitiveBufferTypes.UInt8]) }; } static BooleanToBuffer(bool) { const result = Buffer.alloc(exports.PRIMITIVE_BUFFER_TYPES_BYTE_SIZES[types_1.PrimitiveBufferTypes.Boolean]); result.writeInt8(bool ? 1 : 0); return result; } static BooleanFromBuffer(buffer) { if (buffer.byteLength < exports.PRIMITIVE_BUFFER_TYPES_BYTE_SIZES[types_1.PrimitiveBufferTypes.Boolean]) { throw new Error('BufferHelper.BooleanFromBuffer: not enough bytes remaining'); } const instance = buffer.readInt8(); return { instance: instance === 0 ? false : true, remainingBuffer: buffer.subarray(exports.PRIMITIVE_BUFFER_TYPES_BYTE_SIZES[types_1.PrimitiveBufferTypes.Boolean]) }; } static UIntToBuffer(int, message) { if (int < 0 || int > 2 ** (exports.PRIMITIVE_BUFFER_TYPES_BYTE_SIZES[types_1.PrimitiveBufferTypes.UInt] * 8) - 1) { throw new Error(`BufferHelper.UIntToBuffer: value out of domain: ${int} : ${message}`); } const result = Buffer.alloc(exports.PRIMITIVE_BUFFER_TYPES_BYTE_SIZES[types_1.PrimitiveBufferTypes.UInt]); result.writeUInt32LE(int); return result; } static UIntFromBuffer(buffer) { if (buffer.byteLength < exports.PRIMITIVE_BUFFER_TYPES_BYTE_SIZES[types_1.PrimitiveBufferTypes.UInt]) { throw new Error('BufferHelper.UIntFromBuffer: not enough bytes remaining'); } const instance = buffer.readUInt32LE(); return { instance, remainingBuffer: buffer.subarray(exports.PRIMITIVE_BUFFER_TYPES_BYTE_SIZES[types_1.PrimitiveBufferTypes.UInt]) }; } static DoubleToBuffer(double) { const result = Buffer.alloc(exports.PRIMITIVE_BUFFER_TYPES_BYTE_SIZES[types_1.PrimitiveBufferTypes.Double]); result.writeDoubleLE(double); return result; } static DoubleFromBuffer(buffer) { if (buffer.byteLength < exports.PRIMITIVE_BUFFER_TYPES_BYTE_SIZES[types_1.PrimitiveBufferTypes.Double]) { throw new Error('BufferHelper.DoubleFromBuffer: not enough bytes remaining'); } const instance = buffer.readDoubleLE(); return { instance, remainingBuffer: buffer.subarray(exports.PRIMITIVE_BUFFER_TYPES_BYTE_SIZES[types_1.PrimitiveBufferTypes.Double]) }; } static String2LToBuffer(string) { if (string.length > exports.PRIMITIVE_BUFFER_TYPES_BYTE_SIZES[types_1.PrimitiveBufferTypes.String2L]) { throw new Error('BufferHelper.String2LToBuffer: only supports string smaller than 2^16 - 1 characters'); } const string_Buffer = Buffer.from(string); const length_Buffer = Buffer.alloc(2); length_Buffer.writeUInt16LE(string_Buffer.byteLength); return Buffer.concat([length_Buffer, string_Buffer]); } static String2LFromBuffer(buffer) { if (buffer.byteLength < 2) { throw new Error('BufferHelper.String2LFromBuffer: not enough bytes remaining'); } const length = buffer.readUInt16LE(); if (buffer.byteLength - 2 - length < 0) { throw new Error('BufferHelper.String2LFromBuffer: not enough bytes remaining'); } const string = buffer.subarray(2, 2 + length).toString('utf-8'); return { instance: string, remainingBuffer: buffer.subarray(2 + length) }; } static String4LToBuffer(string) { if (string.length > exports.PRIMITIVE_BUFFER_TYPES_BYTE_SIZES[types_1.PrimitiveBufferTypes.String4L]) { throw new Error('BufferHelper.String4LToBuffer: only supports string smaller than 2^32 - 1 characters'); } const string_Buffer = Buffer.from(string); const length_Buffer = Buffer.alloc(4); length_Buffer.writeUInt32LE(string_Buffer.byteLength); return Buffer.concat([length_Buffer, string_Buffer]); } static String4LFromBuffer(buffer) { if (buffer.byteLength < 4) { throw new Error('BufferHelper.String4LFromBuffer: not enough bytes remaining'); } const length = buffer.readUInt32LE(); if (buffer.byteLength - 4 - length < 0) { throw new Error('BufferHelper.String4LFromBuffer: not enough bytes remaining'); } const string = buffer.subarray(4, 4 + length).toString('utf-8'); return { instance: string, remainingBuffer: buffer.subarray(4 + length) }; } static readBit(buffer, bit) { const i = Math.floor(bit / 8); return (buffer[i] >> (bit % 8)) % 2; } static setBit(buffer, bit, value) { const i = Math.floor(bit / 8); if (value === 0) { buffer[i] &= ~(1 << (bit % 8)); } else { buffer[i] |= (1 << (bit % 8)); } } static compressBuffer(buffer) { return __awaiter(this, void 0, void 0, function* () { return new Promise((resolve, reject) => { zlib_1.default.deflate(buffer, (error, result) => { if (error === null) { resolve(result); } else { reject(error); } }); }); }); } static decompressBuffer(buffer, maxOutputLength = 100 * 1024 * 1024) { return __awaiter(this, void 0, void 0, function* () { return new Promise((resolve, reject) => { zlib_1.default.inflate(buffer, { maxOutputLength // protect against zip bombs }, (error, result) => { if (error === null) { resolve(result); } else { reject(error); } }); }); }); } } exports.BufferHelper = BufferHelper; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiQnVmZmVySGVscGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL2hlbHBlci9CdWZmZXJIZWxwZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7O0FBQUEsZ0RBQXVCO0FBRXZCLFFBQVE7QUFDUixvQ0FJaUI7QUFFSixRQUFBLGlDQUFpQyxHQUFzQztJQUNuRixDQUFDLDRCQUFvQixDQUFDLElBQUksQ0FBQyxFQUFFLENBQUM7SUFDOUIsQ0FBQyw0QkFBb0IsQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDO0lBQ2hDLENBQUMsNEJBQW9CLENBQUMsUUFBUSxDQUFDLEVBQUUsQ0FBQyxJQUFJLEVBQUUsR0FBRyxDQUFDO0lBQzVDLENBQUMsNEJBQW9CLENBQUMsUUFBUSxDQUFDLEVBQUUsQ0FBQyxJQUFJLEVBQUUsR0FBRyxDQUFDO0lBQzVDLENBQUMsNEJBQW9CLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQztJQUNqQyxDQUFDLDRCQUFvQixDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUM7Q0FDL0IsQ0FBQTtBQUVELE1BQU0scUJBQXFCLEdBQUcsQ0FBQyxDQUFBLENBQUMsV0FBVztBQUUzQyxNQUFhLFlBQVk7SUFDeEIsTUFBTSxDQUFDLGlCQUFpQixDQUN2QixPQUFzRCxFQUN0RCxNQUE4QixFQUM5QixTQUFrQjtRQUVsQiw0RUFBNEU7UUFDNUUseUVBQXlFO1FBQ3pFLE1BQU0scUJBQXFCLEdBQUcsTUFBTSxDQUFDLEtBQUssQ0FBQyxxQkFBcUIsQ0FBQyxDQUFBO1FBQ2pFLE1BQU0sSUFBSSxHQUFHLEtBQUssQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFBO1FBQzdDLE1BQU0sWUFBWSxHQUFhLEVBQUUsQ0FBQTtRQUVqQyxNQUFNLFFBQVEsR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLHFCQUFxQixHQUFHLENBQUMsR0FBRyxDQUFDLEVBQUUsSUFB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