🚚 Merge Bencode parser

This commit is contained in:
C-3PO 2018-06-22 12:49:15 +02:00
parent 908c4871ed
commit 1a623aa42d
Signed by: c3po
GPG key ID: 62993C4BB4D86F24

75
src/ssn/bencodeParser.ts Normal file
View file

@ -0,0 +1,75 @@
/**
* A parser for .torrent files encoded with Bencode <https://en.wikipedia.org/wiki/Bencode>.
*/
import { TextDecoder } from 'util';
const Decoder = new TextDecoder('utf-8');
/** Takes a Bencoded-encoded file, parses it at the given starting position and returns a JSON object, or rejects on error. */
export default function bpParse(dv: DataView, posIn: number, reject: (reason?: any) => void): { obj: any, pos: number } {
let pos = posIn;
let obj;
const header = dv.getUint8(pos++);
switch (header) {
case 0x64: { //'d' - dictionary (key-value object)
obj = [];
do {
//read key
const out1 = bpParse(dv, pos, reject);
pos = out1.pos;
//read value
const out2 = bpParse(dv, pos, reject);
pos = out2.pos;
obj[out1.obj] = out2.obj;
} while (dv.getUint8(pos) !== 0x65); //'e' - end
pos++;
break;
}
case 0x6C: { //'l' - list (array)
obj = [];
do {
//read entry
const out = bpParse(dv, pos, reject);
pos = out.pos;
obj.push(out.obj);
} while (dv.getUint8(pos) !== 0x65); //'e' - end
pos++;
break;
}
case 0x69: { //'i' - integer
let curChar = dv.getUint8(pos++);
let curNumber = 0;
while (curChar !== 0x65) { //'e' - end
if (curChar < 0x30 || curChar > 0x39) {
reject('Unexpected int char during bencode parsing');
return { obj: null, pos };
}
curNumber *= 10;
curNumber += curChar - 0x30;
curChar = dv.getUint8(pos++);
}
obj = curNumber;
break;
}
case 0x30: case 0x31: case 0x32: case 0x33: case 0x34:
case 0x35: case 0x36: case 0x37: case 0x38: case 0x39: { //string prefixed by length
//read string length
let curChar: number = header;
let strLen = 0;
while (curChar !== 0x3A) { //':' - integer delimiter, beginning of string
strLen *= 10;
strLen += curChar - 0x30;
curChar = dv.getUint8(pos++);
}
//read string
obj = Decoder.decode(new DataView(dv.buffer, pos, strLen));
pos += strLen;
break;
}
default:
reject('Unexpected leading char during bencode parsing.');
return { obj: null, pos };
}
return { obj, pos };
}