Skip to content

Instantly share code, notes, and snippets.

@z-------------
Last active July 5, 2020 07:09
Show Gist options
  • Save z-------------/b14c008d9e45a90169b6b87de7eb63f5 to your computer and use it in GitHub Desktop.
Save z-------------/b14c008d9e45a90169b6b87de7eb63f5 to your computer and use it in GitHub Desktop.
Seems to work... Not nearly as fast as node-bencode
const MODE_NONE = 0,
MODE_BYTESTRING = 1,
MODE_INT = 2,
MODE_LIST = 3,
MODE_DICT = 4;
function getInt(buf) {
let n = 0;
for (let i = 0; i < buf.length; ++i) {
n += (buf[buf.length - 1 - i] - 48) * 10 ** i;
}
return n;
}
function _decode(data) {
const items = [];
let buf = [];
const l = data.length;
let i = 0;
let mode = MODE_NONE;
let bytesLength = 0;
let bytesRead = 0;
let bytesBuf;
while (i < l) {
const byte = data[i];
if (mode === MODE_NONE) {
if (byte === 101) { // e
i += 1;
break;
} else if (byte === 105) { // i
mode = MODE_INT;
} else if (byte === 108) { // l
mode = MODE_LIST;
const [listItems, listSize] = _decode(data.slice(i + 1));
items.push(listItems);
i += listSize + 1;
mode = MODE_NONE;
continue;
} else if (byte === 100) { // d
mode = MODE_DICT;
const [dictItems, dictSize] = _decode(data.slice(i + 1));
const dict = {};
for (let j = 0; j < dictItems.length; j += 2) {
dict[dictItems[j]] = dictItems[j + 1];
}
items.push(dict);
i += dictSize + 1;
mode = MODE_NONE;
continue;
} else if (byte >= 48 && byte <= 57) { // 0-9
bytesLength *= 10;
bytesLength += byte - 48;
} else if (byte === 58) { // :
mode = MODE_BYTESTRING;
bytesBuf = Buffer.allocUnsafe(bytesLength);
}
} else if (mode === MODE_INT && byte === 101) { // e
const int = getInt(buf);
items.push(int);
mode = MODE_NONE;
buf = [];
} else if (mode === MODE_BYTESTRING) {
bytesBuf[bytesRead++] = byte;
if (bytesRead === bytesLength) {
items.push(bytesBuf);
bytesRead = 0;
bytesLength = 0;
mode = MODE_NONE;
}
} else {
buf.push(byte);
}
++i;
}
return [items, i];
}
module.exports = function decode(data) {
return _decode(data)[0];
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment