openreplay/frontend/app/player/MessageDistributor/messages/MFileReader.ts

68 lines
No EOL
1.7 KiB
TypeScript

import type { Message } from './message';
import type { RawMessage } from './raw';
import logger from 'App/logger';
import RawMessageReader from './RawMessageReader';
// TODO: composition instead of inheritance
// needSkipMessage() and next() methods here use buf and p protected properties,
// which should be probably somehow incapsulated
export default class MFileReader extends RawMessageReader {
private pLastMessageID: number = 0;
private currentTime: number = 0;
public error: boolean = false;
constructor(data: Uint8Array, private readonly startTime: number) {
super(data);
}
private needSkipMessage(): boolean {
if (this.p === 0) return false;
for (let i = 7; i >= 0; i--) {
if (this.buf[ this.p + i ] !== this.buf[ this.pLastMessageID + i ]) {
return this.buf[ this.p + i ] - this.buf[ this.pLastMessageID + i ] < 0;
}
}
return true;
}
private readRawMessage(): RawMessage | null {
this.skip(8);
try {
return super.readMessage();
} catch (e) {
this.error = true;
logger.error("Read message error:", e);
return null;
}
}
hasNext():boolean {
return !this.error && this.hasNextByte();
}
next(): [ Message, number] | null {
if (!this.hasNext()) {
return null;
}
while (this.needSkipMessage()) {
this.readRawMessage();
}
this.pLastMessageID = this.p;
const rMsg = this.readRawMessage();
if (!rMsg) {
return null;
}
if (rMsg.tp === "timestamp") {
this.currentTime = rMsg.timestamp - this.startTime;
} else {
const msg = Object.assign(rMsg, {
time: this.currentTime,
_index: this.pLastMessageID,
})
return [msg, this.pLastMessageID];
}
return null;
}
}