@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
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"));
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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