Skip to content

Commit

Permalink
Add support for byte strings as object key index
Browse files Browse the repository at this point in the history
Closes #2.
  • Loading branch information
Chocobo1 committed Sep 30, 2020
1 parent a2b4543 commit c33a02f
Show file tree
Hide file tree
Showing 4 changed files with 127 additions and 28 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "bencode_online",
"version": "1.0.0",
"version": "2.0.0",
"description": "Bencode & bdecode in your browser",
"repository": {
"type": "git",
Expand Down
4 changes: 2 additions & 2 deletions src/bencode/decode.js
Original file line number Diff line number Diff line change
Expand Up @@ -121,10 +121,10 @@ decode.find = function (chr) {
decode.dictionary = function () {
decode.position++

var dict = {}
var dict = new Map()

while (decode.data[decode.position] !== END_OF_TYPE) {
dict[decode.buffer()] = decode.next()
dict.set(decode.buffer(), decode.next())
}

decode.position++
Expand Down
20 changes: 20 additions & 0 deletions src/bencode/encode.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ encode.getType = function (value) {
if (value instanceof Number) return 'number'
if (value instanceof Boolean) return 'boolean'
if (value instanceof ArrayBuffer) return 'arraybuffer'
if (value instanceof Map) return 'map'
return typeof value
}

Expand All @@ -47,6 +48,7 @@ encode._encode = function (buffers, data) {
case 'boolean': encode.number(buffers, data); break
case 'arraybufferview': encode.buffer(buffers, Buffer.from(data.buffer, data.byteOffset, data.byteLength)); break
case 'arraybuffer': encode.buffer(buffers, Buffer.from(data)); break
case 'map': encode._map(buffers, data); break
}
}

Expand Down Expand Up @@ -99,6 +101,24 @@ encode.dict = function (buffers, data) {
buffers.push(buffE)
}

encode._map = function (buffers, data) {
buffers.push(buffD)

// fix for issue #13 - sorted dicts
const keys = []
let iter = data.keys();
while (key = iter.next().value)
keys.push(key)
keys.sort(Buffer.compare)

for (const key of keys) {
encode.buffer(buffers, key)
encode._encode(buffers, data.get(key))
}

buffers.push(buffE)
}

encode.list = function (buffers, data) {
var i = 0
var c = data.length
Expand Down
129 changes: 104 additions & 25 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ function loadFile(blob: Blob): Promise<ArrayBuffer>
});
}

function decodeString(data: ArrayBuffer): string
function tryEncodeHexstring(data: ArrayBuffer): string
{
const isStringValid = (str: string): boolean =>
{
Expand Down Expand Up @@ -50,34 +50,71 @@ function decodeString(data: ArrayBuffer): string
return bufferToHexstring(Buffer.from(data));
}

function bytearrayToString(obj: Record<string, any>): object
function encodeToArray(data: Array<any>): Array<any>
{
// traverse through obj
for (const key in obj)
const ret = [];

for (const val of data)
{
const val = obj[key];
if (typeof val === "number")
{
ret.push(val);
}
else if (val instanceof Uint8Array)
{
ret.push(tryEncodeHexstring(val));
}
else if (val instanceof Array)
{
ret.push(encodeToArray(val));
}
else if (val instanceof Map)
{
ret.push(encodeToObject(val));
}
else
{
//throw new Error("Type unhandled: " + typeof val + "\nValue: " + val);
}
}

return ret;
}

function encodeToObject(data: Map<Buffer, any>): Record<string, any>
{
const ret: Record<string, any> = {};

for (const [key, val] of data)
{
const keyString = tryEncodeHexstring(key);

if (val instanceof Number)
if (typeof val === "number")
{
ret[keyString] = val;
}
else if (val instanceof Uint8Array)
{
obj[key] = decodeString(val);
ret[keyString] = tryEncodeHexstring(val);
}
else if (val instanceof Array)
{
bytearrayToString(val);
ret[keyString] = encodeToArray(val);
}
else if (val instanceof Object)
else if (val instanceof Map)
{
ret[keyString] = encodeToObject(val);
}
else
{
bytearrayToString(val);
//throw new Error("Type unhandled: " + typeof val + "\nValue: " + val);
}
}

return obj;
return ret;
}

function stringToBytearray(obj: Record<string, any>): object
function tryDecodeHexstring(str: string): Buffer
{
const isHexArray = (str: string): boolean =>
{
Expand All @@ -91,31 +128,73 @@ function stringToBytearray(obj: Record<string, any>): object
return Buffer.from(str, 'hex');
}

for (const key in obj)
return isHexArray(str)
? hexstringToBuffer(str)
: Buffer.from(str);
}

function decodeToArray(data: Array<any>): Array<any>
{
const ret = [];

for (const val of data)
{
if (typeof val === "number")
{
ret.push(val);
}
else if (isString(val))
{
ret.push(tryDecodeHexstring(val));
}
else if (val instanceof Array)
{
ret.push(decodeToArray(val));
}
else if (val instanceof Object)
{
ret.push(decodeToMap(val));
}
else
{
//throw new Error("Type unhandled: " + typeof val + "\nValue: " + val);
}
}

return ret;
}

function decodeToMap(data: Record<string, any>): Map<Buffer, any>
{
const ret = new Map();

for (const [key, val] of Object.entries(data))
{
const val = obj[key];
const keyString = tryDecodeHexstring(key);

if (val instanceof Number)
if (typeof val === "number")
{
ret.set(keyString, val);
}
else if (isString(val))
{
if (isHexArray(val))
obj[key] = hexstringToBuffer(val);
else
obj[key] = Buffer.from(val);
ret.set(keyString, tryDecodeHexstring(val));
}
else if (val instanceof Array)
{
stringToBytearray(val);
ret.set(keyString, decodeToArray(val));
}
else if (val instanceof Object)
{
stringToBytearray(val);
ret.set(keyString, decodeToMap(val));
}
else
{
//throw new Error("Type unhandled: " + typeof val + "\nValue: " + val);
}
}

return obj;
return ret;
}

/// End of helper functions
Expand All @@ -135,7 +214,7 @@ function main(): void

const loadData = (fileName: string, data: Buffer): void =>
{
let decoded = "";
let decoded;
try
{
decoded = bencode.decode(data);
Expand All @@ -148,7 +227,7 @@ function main(): void
return;
}

const result = bytearrayToString(Object.assign({}, decoded));
const result = encodeToObject(decoded);
editor.setValue(JSON.stringify(result, null, 3) + "\n");
editor.gotoLine(0, 0, undefined!);
editor.scrollToLine(0, undefined!, undefined!, undefined!);
Expand Down Expand Up @@ -194,7 +273,7 @@ function main(): void
try
{
const obj = JSON.parse(text);
const obj2 = stringToBytearray(obj);
const obj2 = decodeToMap(obj);
data = bencode.encode(obj2);
}
catch(e)
Expand Down

0 comments on commit c33a02f

Please sign in to comment.