@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
JavaScript
;
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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