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

309 lines 28.3 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")); const LoggerHelper_1 = require("./LoggerHelper"); // 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 outOfDomainError(value, type, error) { if (error) { error(type, value); } throw new Error(`${type}: value out of domain: ${value}`); } static numberMapToBuffer(typeMap, values, keyOffset = 0, tag) { // 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); for (let i = 0; i < valueLen; i++) { const key = keys[i + keyOffset]; const byteSize = typeMap[key]; if (values[key] !== undefined && values[key] !== 0) { switch (byteSize) { case types_1.PrimitiveBufferTypes.UInt: valueBuffers.push(BufferHelper.UIntToBuffer(values[key], (type, value) => { LoggerHelper_1.LoggerHelper.error('NumberMapToBuffer value out of domain: ', { type, value, origin: (tag !== undefined ? tag + '.' : '') + 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 > VALUE_MAP_HEADER_SIZE * 8 - 1) { const nextBuffer = BufferHelper.numberMapToBuffer(typeMap, values, keyOffset + valueLen, tag); 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, error) { if (tinyInt < 0 || tinyInt > 2 ** (exports.PRIMITIVE_BUFFER_TYPES_BYTE_SIZES[types_1.PrimitiveBufferTypes.UInt8] * 8) - 1) { BufferHelper.outOfDomainError(tinyInt, 'BufferHelper.UInt8ToBuffer', error); } 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, error) { if (int < 0 || int > 2 ** (exports.PRIMITIVE_BUFFER_TYPES_BYTE_SIZES[types_1.PrimitiveBufferTypes.UInt] * 8) - 1) { BufferHelper.outOfDomainError(int, 'BufferHelper.UIntToBuffer', error); } 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_1) { return __awaiter(this, arguments, void 0, function* (buffer, maxOutputLength = 100 * 1024 * 1024) { 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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiQnVmZmVySGVscGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL2hlbHBlci9CdWZmZXJIZWxwZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7O0FBQUEsZ0RBQXVCO0FBRXZCLGlEQUE2QztBQUU3QyxRQUFRO0FBQ1Isb0NBSWlCO0FBRUosUUFBQSxpQ0FBaUMsR0FDN0M7SUFDQyxDQUFDLDRCQUFvQixDQUFDLElBQUksQ0FBQyxFQUFFLENBQUM7SUFDOUIsQ0FBQyw0QkFBb0IsQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDO0lBQ2hDLENBQUMsNEJBQW9CLENBQUMsUUFBUSxDQUFDLEVBQUUsQ0FBQyxJQUFJLEVBQUUsR0FBRyxDQUFDO0lBQzVDLENBQUMsNEJBQW9CLENBQUMsUUFBUSxDQUFDLEVBQUUsQ0FBQyxJQUFJLEVBQUUsR0FBRyxDQUFDO0lBQzVDLENBQUMsNEJBQW9CLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQztJQUNqQyxDQUFDLDRCQUFvQixDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUM7Q0FDL0IsQ0FBQTtBQUVGLE1BQU0scUJBQXFCLEdBQUcsQ0FBQyxDQUFBLENBQUMsV0FBVztBQUUzQyxNQUFhLFlBQVk7SUFDeEIsTUFBTSxDQUFDLGdCQUFnQixDQUN0QixLQUFhLEVBQ2IsSUFBWSxFQUNaLEtBQTZDO1FBRTdDLElBQUksS0FBSyxFQUFFLENBQUM7WUFDWCxLQUFLLENBQUMsSUFBSSxFQUFFLEtBQUssQ0FBQyxDQUFBO1FBQ25CLENBQUM7UUFDRCxNQUFNLElBQUksS0FBSyxDQUFDLEdBQUcsSUFBSSwwQkFBMEIsS0FBSyxFQUFFLENBQUMsQ0FBQTtJQUMxRCxDQUFDO0lBRUQsTUFBTSxDQUFDLGlCQUFpQixDQUN2QixPQUFzRCxFQUN0RCxNQUE4QixFQUM5QixTQUFTLEdBQUcsQ0FBQyxFQUNiLEdBQVk7UUFFWiw0RUFBNEU7UUFDNUUseUVBQXlFO1FBQ3pFLE1BQU0scUJB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