mirror of
https://github.com/demostf/demo.js
synced 2026-06-04 00:54:14 +02:00
encoder for createStringTable
This commit is contained in:
parent
79cd277fed
commit
89b9c3b25c
10 changed files with 276 additions and 77 deletions
|
|
@ -4,7 +4,7 @@ import {handleGameEvent} from '../PacketHandler/GameEvent';
|
||||||
import {handleGameEventList} from '../PacketHandler/GameEventList';
|
import {handleGameEventList} from '../PacketHandler/GameEventList';
|
||||||
import {handlePacketEntities} from '../PacketHandler/PacketEntities';
|
import {handlePacketEntities} from '../PacketHandler/PacketEntities';
|
||||||
import {handleSayText2} from '../PacketHandler/SayText2';
|
import {handleSayText2} from '../PacketHandler/SayText2';
|
||||||
import {handleStringTable} from '../PacketHandler/StringTable';
|
import {handleStringTable, handleStringTables} from '../PacketHandler/StringTable';
|
||||||
import {Building} from './Building';
|
import {Building} from './Building';
|
||||||
import {Death} from './Death';
|
import {Death} from './Death';
|
||||||
import {GameEventDefinitionMap} from './GameEvent';
|
import {GameEventDefinitionMap} from './GameEvent';
|
||||||
|
|
@ -146,6 +146,10 @@ export class Match {
|
||||||
handleDataTable(packet, this);
|
handleDataTable(packet, this);
|
||||||
break;
|
break;
|
||||||
case 'stringTable':
|
case 'stringTable':
|
||||||
|
handleStringTables(packet, this);
|
||||||
|
break;
|
||||||
|
case 'createStringTable':
|
||||||
|
case 'updateStringTable':
|
||||||
handleStringTable(packet, this);
|
handleStringTable(packet, this);
|
||||||
break;
|
break;
|
||||||
case 'gameEventList':
|
case 'gameEventList':
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,16 @@ export interface StringTablePacket {
|
||||||
tables: StringTable[];
|
tables: StringTable[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface CreateStringTablePacket {
|
||||||
|
packetType: 'createStringTable';
|
||||||
|
table: StringTable;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface UpdateStringTablePacket {
|
||||||
|
packetType: 'updateStringTable';
|
||||||
|
table: StringTable;
|
||||||
|
}
|
||||||
|
|
||||||
export interface ConsoleCmdPacket {
|
export interface ConsoleCmdPacket {
|
||||||
packetType: 'consoleCmd';
|
packetType: 'consoleCmd';
|
||||||
command: string;
|
command: string;
|
||||||
|
|
@ -81,7 +91,7 @@ export interface ParseSoundsPacket {
|
||||||
|
|
||||||
export interface SetConVarPacket {
|
export interface SetConVarPacket {
|
||||||
packetType: 'setConVar';
|
packetType: 'setConVar';
|
||||||
vars: {[key: string]: string};
|
vars: { [key: string]: string };
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface TempEntitiesPacket {
|
export interface TempEntitiesPacket {
|
||||||
|
|
@ -142,6 +152,8 @@ export type UserMessagePacket = SayText2Packet | TextMessagePacket | UnknownUser
|
||||||
|
|
||||||
export type Packet = BSPDecalPacket |
|
export type Packet = BSPDecalPacket |
|
||||||
StringTablePacket |
|
StringTablePacket |
|
||||||
|
CreateStringTablePacket |
|
||||||
|
UpdateStringTablePacket |
|
||||||
DataTablePacket |
|
DataTablePacket |
|
||||||
ClassInfoPacket |
|
ClassInfoPacket |
|
||||||
EntityMessagePacket |
|
EntityMessagePacket |
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,18 @@
|
||||||
import {Match} from '../Data/Match';
|
import {Match} from '../Data/Match';
|
||||||
import {StringTablePacket} from '../Data/Packet';
|
import {CreateStringTablePacket, StringTablePacket, UpdateStringTablePacket} from '../Data/Packet';
|
||||||
import {StringTableEntry} from '../Data/StringTable';
|
import {StringTable, StringTableEntry} from '../Data/StringTable';
|
||||||
|
|
||||||
export function handleStringTable(packet: StringTablePacket, match: Match) {
|
export function handleStringTable(packet: CreateStringTablePacket | UpdateStringTablePacket, match: Match) {
|
||||||
|
handleTable(packet.table, match);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function handleStringTables(packet: StringTablePacket, match: Match) {
|
||||||
for (const table of packet.tables) {
|
for (const table of packet.tables) {
|
||||||
|
handleTable(table, match);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleTable(table: StringTable, match: Match) {
|
||||||
if (!match.getStringTable(table.name)) {
|
if (!match.getStringTable(table.name)) {
|
||||||
match.stringTables.push(table);
|
match.stringTables.push(table);
|
||||||
}
|
}
|
||||||
|
|
@ -31,7 +40,6 @@ export function handleStringTable(packet: StringTablePacket, match: Match) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function saveInstanceBaseLine(entry: StringTableEntry, match: Match) {
|
function saveInstanceBaseLine(entry: StringTableEntry, match: Match) {
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ import {make} from '../Packet/ParserGenerator';
|
||||||
import {ParseBSPDecal} from '../Packet/BSPDecal';
|
import {ParseBSPDecal} from '../Packet/BSPDecal';
|
||||||
import {EncodeClassInfo, ParseClassInfo} from '../Packet/ClassInfo';
|
import {EncodeClassInfo, ParseClassInfo} from '../Packet/ClassInfo';
|
||||||
import {ParseCmdKeyValues} from '../Packet/CmdKeyValues';
|
import {ParseCmdKeyValues} from '../Packet/CmdKeyValues';
|
||||||
import {ParseCreateStringTable} from '../Packet/CreateStringTable';
|
import {EncodeCreateStringTable, ParseCreateStringTable} from '../Packet/CreateStringTable';
|
||||||
import {ParseEntityMessage} from '../Packet/EntityMessage';
|
import {ParseEntityMessage} from '../Packet/EntityMessage';
|
||||||
import {ParseGameEvent} from '../Packet/GameEvent';
|
import {ParseGameEvent} from '../Packet/GameEvent';
|
||||||
import {ParseGameEventList} from '../Packet/GameEventList';
|
import {ParseGameEventList} from '../Packet/GameEventList';
|
||||||
|
|
@ -41,7 +41,7 @@ export class Packet extends Parser {
|
||||||
'game{s}map{s}skybox{s}serverName{s}replay{b}'),
|
'game{s}map{s}skybox{s}serverName{s}replay{b}'),
|
||||||
10: {parser: ParseClassInfo, encoder: EncodeClassInfo},
|
10: {parser: ParseClassInfo, encoder: EncodeClassInfo},
|
||||||
11: make('setPause', 'paused{b}'),
|
11: make('setPause', 'paused{b}'),
|
||||||
12: {parser: ParseCreateStringTable, encoder: voidEncoder},
|
12: {parser: ParseCreateStringTable, encoder: EncodeCreateStringTable},
|
||||||
13: {parser: ParseUpdateStringTable, encoder: voidEncoder},
|
13: {parser: ParseUpdateStringTable, encoder: voidEncoder},
|
||||||
14: {parser: ParseVoiceInit, encoder: voidEncoder},
|
14: {parser: ParseVoiceInit, encoder: voidEncoder},
|
||||||
15: {parser: ParseVoiceData, encoder: voidEncoder},
|
15: {parser: ParseVoiceData, encoder: voidEncoder},
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,13 @@
|
||||||
import {BitStream} from 'bit-buffer';
|
import {BitStream} from 'bit-buffer';
|
||||||
import {StringTablePacket} from '../../Data/Packet';
|
import {CreateStringTablePacket} from '../../Data/Packet';
|
||||||
import {logBase2} from '../../Math';
|
import {logBase2} from '../../Math';
|
||||||
import {readVarInt} from '../readBitVar';
|
import {readVarInt, writeVarInt} from '../readBitVar';
|
||||||
|
|
||||||
import {uncompress} from 'snappyjs';
|
import {uncompress} from 'snappyjs';
|
||||||
import {Match} from '../../Data/Match';
|
|
||||||
import {StringTable} from '../../Data/StringTable';
|
import {StringTable} from '../../Data/StringTable';
|
||||||
import {parseStringTable} from '../StringTableParser';
|
import {encodeStringTableEntries, guessStringTableEntryLength, parseStringTableEntries} from '../StringTableParser';
|
||||||
|
|
||||||
export function ParseCreateStringTable(stream: BitStream, match: Match): StringTablePacket { // 12: createStringTable
|
export function ParseCreateStringTable(stream: BitStream): CreateStringTablePacket { // 12: createStringTable
|
||||||
const tableName = stream.readASCIIString();
|
const tableName = stream.readASCIIString();
|
||||||
const maxEntries = stream.readUint16();
|
const maxEntries = stream.readUint16();
|
||||||
const encodeBits = logBase2(maxEntries);
|
const encodeBits = logBase2(maxEntries);
|
||||||
|
|
@ -57,10 +56,38 @@ export function ParseCreateStringTable(stream: BitStream, match: Match): StringT
|
||||||
fixedUserDataSizeBits: userDataSizeBits,
|
fixedUserDataSizeBits: userDataSizeBits,
|
||||||
};
|
};
|
||||||
|
|
||||||
parseStringTable(data, table, entityCount, match);
|
table.entries = parseStringTableEntries(data, table, entityCount);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
packetType: 'stringTable',
|
packetType: 'createStringTable',
|
||||||
tables: [table],
|
table: table,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function EncodeCreateStringTable(packet: CreateStringTablePacket, stream: BitStream) {
|
||||||
|
stream.writeASCIIString(packet.table.name);
|
||||||
|
stream.writeUint16(packet.table.maxEntries);
|
||||||
|
const encodeBits = logBase2(packet.table.maxEntries);
|
||||||
|
stream.writeBits(packet.table.entries.length, encodeBits + 1);
|
||||||
|
|
||||||
|
const entryData = new BitStream(new ArrayBuffer(guessStringTableEntryLength(packet.table)));
|
||||||
|
encodeStringTableEntries(entryData, packet.table);
|
||||||
|
|
||||||
|
const entryLength = entryData.index;
|
||||||
|
entryData.index = 0;
|
||||||
|
|
||||||
|
writeVarInt(entryLength, stream);
|
||||||
|
|
||||||
|
if (packet.table.fixedUserDataSize && packet.table.fixedUserDataSizeBits) {
|
||||||
|
stream.writeBoolean(true);
|
||||||
|
stream.writeBits(packet.table.fixedUserDataSize, 12);
|
||||||
|
stream.writeBits(packet.table.fixedUserDataSizeBits, 4);
|
||||||
|
} else {
|
||||||
|
stream.writeBoolean(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// we never compress table data
|
||||||
|
stream.writeBoolean(false);
|
||||||
|
|
||||||
|
stream.writeBitStream(entryData, entryLength);
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
import {BitStream} from 'bit-buffer';
|
import {BitStream} from 'bit-buffer';
|
||||||
import {Match} from '../../Data/Match';
|
import {Match} from '../../Data/Match';
|
||||||
import {StringTablePacket} from '../../Data/Packet';
|
import {UpdateStringTablePacket} from '../../Data/Packet';
|
||||||
import {parseStringTable} from '../StringTableParser';
|
import {parseStringTableEntries} from '../StringTableParser';
|
||||||
|
|
||||||
export function ParseUpdateStringTable(stream: BitStream, match: Match): StringTablePacket { // 12: updateStringTable
|
export function ParseUpdateStringTable(stream: BitStream, match: Match): UpdateStringTablePacket { // 12: updateStringTable
|
||||||
const tableId = stream.readBits(5);
|
const tableId = stream.readBits(5);
|
||||||
|
|
||||||
const multipleChanged = stream.readBoolean();
|
const multipleChanged = stream.readBoolean();
|
||||||
|
|
@ -17,10 +17,16 @@ export function ParseUpdateStringTable(stream: BitStream, match: Match): StringT
|
||||||
}
|
}
|
||||||
|
|
||||||
const table = match.stringTables[tableId];
|
const table = match.stringTables[tableId];
|
||||||
parseStringTable(data, table, changedEntries, match);
|
const updatedEntries = parseStringTableEntries(data, table, changedEntries, table.entries);
|
||||||
|
|
||||||
|
for (let i = 0; i < updatedEntries.length; i++) {
|
||||||
|
if (updatedEntries[i]) {
|
||||||
|
table.entries[i] = updatedEntries[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
packetType: 'stringTable',
|
packetType: 'updateStringTable',
|
||||||
tables: [table],
|
table: table,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,18 +3,15 @@ import {Match} from '../Data/Match';
|
||||||
import {StringTable, StringTableEntry} from '../Data/StringTable';
|
import {StringTable, StringTableEntry} from '../Data/StringTable';
|
||||||
import {logBase2} from '../Math';
|
import {logBase2} from '../Math';
|
||||||
|
|
||||||
export function parseStringTable(stream: BitStream, table: StringTable, entries: number, match: Match) {
|
export function parseStringTableEntries(stream: BitStream, table: StringTable, entryCount: number, existingEntries: StringTableEntry[] = []): StringTableEntry[] {
|
||||||
const entryBits = logBase2(table.maxEntries);
|
const entryBits = logBase2(table.maxEntries);
|
||||||
|
const entries: StringTableEntry[] = [];
|
||||||
let lastEntry = -1;
|
let lastEntry = -1;
|
||||||
|
|
||||||
const history: StringTableEntry[] = [];
|
const history: StringTableEntry[] = [];
|
||||||
|
|
||||||
for (let i = 0; i < entries; i++) {
|
for (let i = 0; i < entryCount; i++) {
|
||||||
let entryIndex = lastEntry + 1;
|
const entryIndex = (!stream.readBoolean()) ? stream.readBits(entryBits) : lastEntry + 1;
|
||||||
|
|
||||||
if (!stream.readBoolean()) {
|
|
||||||
entryIndex = stream.readBits(entryBits);
|
|
||||||
}
|
|
||||||
|
|
||||||
lastEntry = entryIndex;
|
lastEntry = entryIndex;
|
||||||
|
|
||||||
|
|
@ -43,7 +40,7 @@ export function parseStringTable(stream: BitStream, table: StringTable, entries:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let userData: BitStream|undefined;
|
let userData: BitStream | undefined;
|
||||||
|
|
||||||
if (stream.readBoolean()) {
|
if (stream.readBoolean()) {
|
||||||
if (table.fixedUserDataSize && table.fixedUserDataSizeBits) {
|
if (table.fixedUserDataSize && table.fixedUserDataSizeBits) {
|
||||||
|
|
@ -54,8 +51,8 @@ export function parseStringTable(stream: BitStream, table: StringTable, entries:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (table.entries[entryIndex]) {
|
if (existingEntries[entryIndex]) {
|
||||||
const existingEntry = table.entries[entryIndex];
|
const existingEntry: StringTableEntry = {...existingEntries[entryIndex]};
|
||||||
if (userData) {
|
if (userData) {
|
||||||
existingEntry.extraData = userData;
|
existingEntry.extraData = userData;
|
||||||
}
|
}
|
||||||
|
|
@ -63,16 +60,67 @@ export function parseStringTable(stream: BitStream, table: StringTable, entries:
|
||||||
if (value) {
|
if (value) {
|
||||||
existingEntry.text = value;
|
existingEntry.text = value;
|
||||||
}
|
}
|
||||||
|
entries[entryIndex] = existingEntry;
|
||||||
history.push(existingEntry);
|
history.push(existingEntry);
|
||||||
} else {
|
} else {
|
||||||
table.entries[entryIndex] = {
|
entries[entryIndex] = {
|
||||||
text: value,
|
text: value,
|
||||||
extraData: userData,
|
extraData: userData,
|
||||||
};
|
};
|
||||||
history.push(table.entries[entryIndex]);
|
console.log(entries[entryIndex]);
|
||||||
|
history.push(entries[entryIndex]);
|
||||||
}
|
}
|
||||||
if (history.length > 32) {
|
if (history.length > 32) {
|
||||||
history.shift();
|
history.shift();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return entries;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function guessStringTableEntryLength(table: StringTable): number {
|
||||||
|
// a rough guess of how many bytes are needed to encode the table entries
|
||||||
|
const entryBytes = Math.ceil(logBase2(table.maxEntries) / 8);
|
||||||
|
return table.entries.reduce((length: number, entry: StringTableEntry) => {
|
||||||
|
return length +
|
||||||
|
entryBytes +
|
||||||
|
1 + // misc boolean
|
||||||
|
entry.text.length + 1 + // +1 for null termination
|
||||||
|
(entry.extraData ? Math.ceil(entry.extraData.length / 8) : 0);
|
||||||
|
}, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function encodeStringTableEntries(stream: BitStream, table: StringTable) {
|
||||||
|
const entryBits = logBase2(table.maxEntries);
|
||||||
|
let lastIndex = -1;
|
||||||
|
for (let i = 0; i < table.entries.length; i++) {
|
||||||
|
if (table.entries[i]) {
|
||||||
|
const entry = table.entries[i];
|
||||||
|
if (i !== lastIndex) {
|
||||||
|
stream.writeBoolean(false);
|
||||||
|
stream.writeBits(i, entryBits);
|
||||||
|
} else {
|
||||||
|
stream.writeBoolean(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// we always encode a value
|
||||||
|
stream.writeBoolean(true);
|
||||||
|
// we don't encode substring optimizations
|
||||||
|
stream.writeBoolean(false);
|
||||||
|
|
||||||
|
stream.writeASCIIString(entry.text);
|
||||||
|
|
||||||
|
if (entry.extraData) {
|
||||||
|
stream.writeBoolean(true);
|
||||||
|
|
||||||
|
if (!table.fixedUserDataSizeBits) {
|
||||||
|
stream.writeBits(Math.ceil(entry.extraData.length / 8), 14);
|
||||||
|
}
|
||||||
|
stream.writeBitStream(entry.extraData);
|
||||||
|
entry.extraData.index = 0;
|
||||||
|
} else {
|
||||||
|
stream.writeBoolean(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
94
src/tests/unit/Parser/Packet/CreateStringTableTest.ts
Normal file
94
src/tests/unit/Parser/Packet/CreateStringTableTest.ts
Normal file
|
|
@ -0,0 +1,94 @@
|
||||||
|
import {BitStream} from 'bit-buffer';
|
||||||
|
import {assertEncoder, assertParser, getStream} from './PacketTest';
|
||||||
|
import {EncodeCreateStringTable, ParseCreateStringTable} from '../../../../Parser/Packet/CreateStringTable';
|
||||||
|
|
||||||
|
const exampleData = [
|
||||||
|
100,
|
||||||
|
111,
|
||||||
|
119,
|
||||||
|
110,
|
||||||
|
108,
|
||||||
|
111,
|
||||||
|
97,
|
||||||
|
100,
|
||||||
|
97,
|
||||||
|
98,
|
||||||
|
108,
|
||||||
|
101,
|
||||||
|
115,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
32,
|
||||||
|
1,
|
||||||
|
0,
|
||||||
|
121,
|
||||||
|
0,
|
||||||
|
107,
|
||||||
|
11,
|
||||||
|
131,
|
||||||
|
155,
|
||||||
|
227,
|
||||||
|
130,
|
||||||
|
99,
|
||||||
|
251,
|
||||||
|
18,
|
||||||
|
11,
|
||||||
|
35,
|
||||||
|
187,
|
||||||
|
11,
|
||||||
|
163,
|
||||||
|
43,
|
||||||
|
147,
|
||||||
|
251,
|
||||||
|
130,
|
||||||
|
147,
|
||||||
|
123,
|
||||||
|
251,
|
||||||
|
178,
|
||||||
|
203,
|
||||||
|
113,
|
||||||
|
17,
|
||||||
|
155,
|
||||||
|
131,
|
||||||
|
3,
|
||||||
|
192];
|
||||||
|
|
||||||
|
const examplePacket = {
|
||||||
|
packetType: 'createStringTable',
|
||||||
|
table: {
|
||||||
|
name: 'downloadables',
|
||||||
|
entries: [{text: 'maps\\pl_badwater_pro_v9.bsp', extraData: undefined}],
|
||||||
|
maxEntries: 8192,
|
||||||
|
fixedUserDataSize: 0,
|
||||||
|
fixedUserDataSizeBits: 0
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const examplePacket2 = {
|
||||||
|
packetType: 'createStringTable',
|
||||||
|
table: {
|
||||||
|
name: 'downloadables',
|
||||||
|
entries: [
|
||||||
|
{text: 'maps\\pl_badwater_pro_v9.bsp', extraData: undefined},
|
||||||
|
{text: 'foobar', extraData: undefined},
|
||||||
|
{text: 'assadasdas', extraData: undefined},
|
||||||
|
{text: 'foo', extraData: undefined}
|
||||||
|
],
|
||||||
|
maxEntries: 8192,
|
||||||
|
fixedUserDataSize: 0,
|
||||||
|
fixedUserDataSizeBits: 0
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
suite('CreateStringTable', () => {
|
||||||
|
test('Parse createStringTable', () => {
|
||||||
|
assertParser(ParseCreateStringTable, getStream(exampleData), examplePacket, 388);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Encode createStringTable', () => {
|
||||||
|
// more bits are used for encoding because we don't do a lot of compression tricks
|
||||||
|
assertEncoder(ParseCreateStringTable, EncodeCreateStringTable, examplePacket, 401);
|
||||||
|
assertEncoder(ParseCreateStringTable, EncodeCreateStringTable, examplePacket2, 628);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
@ -15,7 +15,7 @@ export function getStream(data: string | number[]) {
|
||||||
export type Encoder = (data: any, stream: BitStream) => void;
|
export type Encoder = (data: any, stream: BitStream) => void;
|
||||||
|
|
||||||
export function assertEncoder(parser: Parser, encoder: Encoder, data: any, length: number = 0) {
|
export function assertEncoder(parser: Parser, encoder: Encoder, data: any, length: number = 0) {
|
||||||
const stream = new BitStream(new ArrayBuffer(64));
|
const stream = new BitStream(new ArrayBuffer(Math.max(64, length * 8)));
|
||||||
|
|
||||||
encoder(data as Packet, stream);
|
encoder(data as Packet, stream);
|
||||||
|
|
||||||
|
|
@ -28,14 +28,14 @@ export function assertEncoder(parser: Parser, encoder: Encoder, data: any, lengt
|
||||||
stream.index = 0;
|
stream.index = 0;
|
||||||
|
|
||||||
const result = parser(stream);
|
const result = parser(stream);
|
||||||
assert.deepEqual(data, result, 'Re-decoded value not equal to original value');
|
assert.deepEqual(result, data, 'Re-decoded value not equal to original value');
|
||||||
assert.equal(pos, stream.index, 'Number of bits used for encoding and parsing not equal');
|
assert.equal(stream.index, pos, 'Number of bits used for encoding and parsing not equal');
|
||||||
}
|
}
|
||||||
|
|
||||||
export type Parser = (stream: BitStream) => any;
|
export type Parser = (stream: BitStream) => any;
|
||||||
|
|
||||||
export function assertParser(parser: Parser, stream: BitStream, expected: any, length: number) {
|
export function assertParser(parser: Parser, stream: BitStream, expected: any, length: number) {
|
||||||
const start = stream.index;
|
const start = stream.index;
|
||||||
assert.deepEqual(expected, parser(stream));
|
assert.deepEqual(parser(stream), expected);
|
||||||
assert.equal(stream.index - start, length, 'Unexpected number of bits consumed from stream');
|
assert.equal(stream.index - start, length, 'Unexpected number of bits consumed from stream');
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue