Files
2026-01-31 03:01:55 +02:00

151 lines
4.4 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
export default class Stream {
private _stream: number[];
private _readPoiner: number = 0;
private _writePointer: number = 0;
constructor(stream : number[] = []) {
this._stream = stream;
}
public getStream(): number[] {
return this._stream;
}
public setStream(stream: number[]) {
this._stream = stream;
}
public writeInt8(value: number) {
const negationBit = value < 0 ? 1 : 0;
const int8Value = Math.abs(value) & 0xFF;
this._stream[this._writePointer >> 3] |= negationBit << (7 - (this._writePointer & 7));
this._writePointer++;
for (let i = 0; i < 8; i++) {
const bit = (int8Value >> (7 - i)) & 1;
this._stream[this._writePointer >> 3] |= bit << (7 - (this._writePointer & 7));
this._writePointer++;
}
}
public readInt8(): number {
let value = 0;
const negationBit = (this._stream[this._readPoiner >> 3] >> (7 - (this._readPoiner & 7))) & 1;
this._readPoiner++;
for (let i = 0; i < 8; i++) {
const bit = (this._stream[this._readPoiner >> 3] >> (7 - (this._readPoiner & 7))) & 1;
value |= bit << (7 - i);
this._readPoiner++;
}
return negationBit ? -value : value;
}
public writeBit(value: number) {
const bit = value & 1;
this._stream[this._writePointer >> 3] |= bit << (7 - (this._writePointer & 7));
this._writePointer++;
}
public readBit(): number {
const bit = (this._stream[this._readPoiner >> 3] >> (7 - (this._readPoiner & 7))) & 1;
this._readPoiner++;
return bit;
}
public writeBoolean(value: boolean) {
this.writeBit(value ? 1 : 0);
}
public readBoolean(): boolean {
return this.readBit() === 1;
}
public writeInt16(value: number) {
this.writeInt8(value >> 8);
this.writeInt8(value & 0xFF);
}
public readInt16(): number {
const value = this.readInt8() << 8;
return value | this.readInt8();
}
public writeInt32(value: number) {
this.writeInt16(value >> 16);
this.writeInt16(value & 0xFFFF);
}
public readInt32(): number {
const value = this.readInt16() << 16;
return value | this.readInt16();
}
public writeInt64(value: number) {
const high = Math.floor(value / 0x100000000);
const low = value >>> 0;
this.writeInt32(high);
this.writeInt32(low);
}
public readInt64(): number {
const high = this.readInt32();
const low = this.readInt32() >>> 0;
return high * 0x100000000 + low;
}
public writeFloat32(value: number) {
const buffer = new ArrayBuffer(4);
new DataView(buffer).setFloat32(0, value, true);
const float32Value = new Uint32Array(buffer)[0];
this.writeInt32(float32Value);
}
public readFloat32(): number {
const float32Value = this.readInt32();
const buffer = new ArrayBuffer(4);
new Uint32Array(buffer)[0] = float32Value;
return new DataView(buffer).getFloat32(0, true);
}
public writeString(value: string) {
let length = value.length;
this.writeInt32(length);
for (let i = 0; i < value.length; i++) {
this.writeInt16(value.charCodeAt(i));
}
}
public readString(): string {
let length = this.readInt32();
/**
* Фикс уязвимости с длинной строки, превышающей
* возможность для чтения _stream
*/
if (length < 0 || length > (this._stream.length - (this._readPoiner >> 3))) {
console.info("Stream readString length invalid", length, this._stream.length, this._readPoiner);
return "";
}
let value = "";
for (let i = 0; i < length; i++) {
value += String.fromCharCode(this.readInt16());
}
return value;
}
public writeBytes(value: number[]) {
this.writeInt32(value.length);
for (let i = 0; i < value.length; i++) {
this.writeInt8(value[i]);
}
}
public readBytes(): number[] {
let length = this.readInt32();
let value : any = [];
for (let i = 0; i < length; i++) {
value.push(this.readInt8());
}
return value;
}
}