@foxglove/ulog
Version:
PX4 ULog file reader
108 lines • 4.04 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.parseMessage = parseMessage;
exports.parseFieldValue = parseFieldValue;
exports.parseBasicFieldValue = parseBasicFieldValue;
exports.messageSize = messageSize;
exports.fieldSize = fieldSize;
const BASIC_PARSERS = {
bool: (view, offset) => view.getUint8(offset) !== 0,
int8_t: (view, offset) => view.getInt8(offset),
uint8_t: (view, offset) => view.getUint8(offset),
int16_t: (view, offset) => view.getInt16(offset, true),
uint16_t: (view, offset) => view.getUint16(offset, true),
int32_t: (view, offset) => view.getInt32(offset, true),
uint32_t: (view, offset) => view.getUint32(offset, true),
int64_t: (view, offset) => view.getBigInt64(offset, true),
uint64_t: (view, offset) => view.getBigUint64(offset, true),
float: (view, offset) => view.getFloat32(offset, true),
double: (view, offset) => view.getFloat64(offset, true),
char: (view, offset) => String.fromCharCode(view.getUint8(offset)),
};
const BASIC_SIZES = {
bool: 1,
int8_t: 1,
uint8_t: 1,
int16_t: 2,
uint16_t: 2,
int32_t: 4,
uint32_t: 4,
int64_t: 8,
uint64_t: 8,
float: 4,
double: 8,
char: 1,
};
const textDecoder = new TextDecoder();
function parseMessage(definition, definitions, view, offset = 0) {
const output = {};
let curOffset = offset;
for (const field of definition.fields) {
if (field.name.startsWith("_")) {
continue;
}
output[field.name] = parseFieldValue(field, definitions, view, curOffset);
curOffset += fieldSize(field, definitions) * (field.arrayLength ?? 1);
}
if (typeof output.timestamp !== "bigint") {
throw new Error(`Message "${definition.name}" is missing a timestamp field`);
}
return output;
}
function parseFieldValue(field, definitions, view, offset = 0) {
if (field.isComplex) {
const definition = definitions.get(field.type);
if (!definition) {
throw new Error(`Unknown type ${field.type}, searched ${definitions.size} definitions`);
}
if (field.arrayLength != undefined) {
const size = fieldSize(field, definitions);
const output = new Array(field.arrayLength);
for (let i = 0; i < field.arrayLength; i++) {
output[i] = parseMessage(definition, definitions, view, offset + i * size);
}
return output;
}
return parseMessage(definition, definitions, view, offset);
}
return parseBasicFieldValue(field, view, offset);
}
function parseBasicFieldValue(field, view, offset = 0) {
const basicType = field.type;
const parser = BASIC_PARSERS[basicType];
if (field.arrayLength != undefined) {
// String handling
if (field.type === "char") {
const len = Math.min(field.arrayLength, view.byteLength - offset);
const byteOffset = view.byteOffset + offset;
return textDecoder.decode(new Uint8Array(view.buffer, byteOffset, len));
}
const basicSize = BASIC_SIZES[basicType];
const output = new Array(field.arrayLength);
for (let i = 0; i < field.arrayLength; i++) {
output[i] = parser(view, offset + i * basicSize);
}
return output;
}
return parser(view, offset);
}
function messageSize(definition, definitions) {
return definition.fields.reduce((size, f) => size + fieldSize(f, definitions), 0);
}
function fieldSize(field, definitions) {
if (field.size != undefined) {
return field.size;
}
if (field.isComplex) {
const definition = definitions.get(field.type);
if (!definition) {
throw new Error(`Unknown type ${field.type}, searched ${definitions.size} definitions`);
}
field.size = messageSize(definition, definitions);
}
else {
field.size = BASIC_SIZES[field.type];
}
return field.size;
}
//# sourceMappingURL=parse.js.map