From 1a623aa42d04064f72ca70cccd50195501fa041b Mon Sep 17 00:00:00 2001 From: C-3PO Date: Fri, 22 Jun 2018 12:49:15 +0200 Subject: [PATCH] =?UTF-8?q?=F0=9F=9A=9A=20Merge=20Bencode=20parser?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/ssn/bencodeParser.ts | 75 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 src/ssn/bencodeParser.ts diff --git a/src/ssn/bencodeParser.ts b/src/ssn/bencodeParser.ts new file mode 100644 index 0000000..73d6c05 --- /dev/null +++ b/src/ssn/bencodeParser.ts @@ -0,0 +1,75 @@ +/** + * A parser for .torrent files encoded with 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 }; +}