1
0
Fork 0
mirror of https://github.com/demostf/demo.js synced 2026-06-04 00:54:14 +02:00

encoder for parser generator definitions

This commit is contained in:
Robin Appelman 2017-08-12 15:00:36 +02:00
commit 1e21b24763
3 changed files with 88 additions and 4 deletions

View file

@ -3,7 +3,7 @@ import {Match} from '../../Data/Match';
import {Packet} from '../../Data/Packet'; import {Packet} from '../../Data/Packet';
export type Parser = (stream: BitStream, match?: Match, skip?: boolean) => Packet; export type Parser = (stream: BitStream, match?: Match, skip?: boolean) => Packet;
export type Encoder = (packet: Packet, match: Match, stream: BitStream) => void; export type Encoder = (packet: Packet, stream: BitStream, match?: Match) => void;
export interface PacketHandler { export interface PacketHandler {
parser: Parser, parser: Parser,

View file

@ -1,5 +1,5 @@
import {Packet} from '../../Data/Packet'; import {Packet} from '../../Data/Packet';
import {PacketHandler, voidEncoder} from './Parser'; import {PacketHandler} from './Parser';
export function make(name: string, definition: string): PacketHandler { export function make(name: string, definition: string): PacketHandler {
const parts = definition.split('}'); const parts = definition.split('}');
@ -23,7 +23,11 @@ export function make(name: string, definition: string): PacketHandler {
} }
return result as Packet; return result as Packet;
}, },
encoder: voidEncoder encoder: (packet, stream) => {
for (const group of items) {
writeItem(stream, group[1], packet, packet[group[0]]);
}
}
}; };
} }
@ -49,3 +53,26 @@ function readItem(stream, description, data) {
return stream.readBits(parseInt(description, 10), true); return stream.readBits(parseInt(description, 10), true);
} }
} }
function writeItem(stream, description, data, value) {
if (description[0] === 'b') {
return stream.writeBoolean(value);
} else if (description[0] === 's') {
if (description.length === 1) {
return stream.writeUTF8String(value);
} else {
const length = parseInt(description.substr(1), 10);
return stream.writeUTF8String(value, length);
}
} else if (description === 'f32') {
return stream.writeFloat32(value);
} else if (description[0] === 'u') {
const length = parseInt(description.substr(1), 10);
return stream.writeBits(value, length);
} else if (description[0] === '$') {
const variable = description.substr(1);
return stream.writeBits(value, data[variable]);
} else {
return stream.writeBits(value, parseInt(description, 10), true);
}
}

View file

@ -1,18 +1,39 @@
import * as assert from 'assert'; import * as assert from 'assert';
import {make} from '../../../../Parser/Packet/ParserGenerator'; import {make} from '../../../../Parser/Packet/ParserGenerator';
import {BitStream} from 'bit-buffer'; import {BitStream} from 'bit-buffer';
import {Packet} from '../../../../Data/Packet';
function getStream(data: string) { function getStream(data: string) {
const buffer = new Buffer(data); const buffer = new Buffer(data);
return new BitStream(buffer); return new BitStream(buffer);
} }
function assertEncoder(definition: string, data: any, length: number = 0) {
const stream = new BitStream(new ArrayBuffer(64));
const {parser, encoder} = make('packetName', definition);
data.packetType = 'packetName';
encoder(data as Packet, stream);
const pos = stream.index;
if (length) {
assert.equal(stream.index, length, 'Unexpected number of bits used for encoding');
}
stream.index = 0;
const result = parser(stream);
assert.deepEqual(data, result);
assert.equal(pos, stream.index, 'Number of bits used for encoding and parsing not equal');
}
function assertParser(definition: string, stream: BitStream, expected: any, length: number) { function assertParser(definition: string, stream: BitStream, expected: any, length: number) {
const {parser} = make('packetName', definition); const {parser} = make('packetName', definition);
expected.packetType = 'packetName'; expected.packetType = 'packetName';
const start = stream.index; const start = stream.index;
assert.deepEqual(expected, parser(stream)); assert.deepEqual(expected, parser(stream));
assert.equal(length, stream.index - start, 'Unexpected number of bits consumed from stream'); assert.equal(stream.index - start, length, 'Unexpected number of bits consumed from stream');
} }
suite('Parser generator', () => { suite('Parser generator', () => {
@ -83,4 +104,40 @@ suite('Parser generator', () => {
assertParser('foo{f32}', stream, {foo: 12.234233856201172}, 32); assertParser('foo{f32}', stream, {foo: 12.234233856201172}, 32);
}); });
test('Encode fixed string', () => {
assertEncoder('foo{s3}', {
foo: 'bar'
}, 3 * 8);
});
test('Encode null terminated string', () => {
assertEncoder('foo{s}', {
foo: 'bar'
}, 4 * 8);
});
test('Encode booleans', () => {
assertEncoder('foo{b}bar{b}', {
foo: 1,
bar: 0
}, 2);
});
test('Encode integers', () => {
assertEncoder('foo{u2}bar{12}', {
foo: 3,
bar: 7
}, 2 + 12);
});
test('Encode variable length', () => {
assertEncoder('foo{u2}bar{$foo}', {
foo: 3,
bar: 4
}, 2 + 3);
});
test('Encode float', () => {
assertEncoder('foo{f32}', {
foo: 3.5
}, 32);
});
}); });