encoding seems to work now

This commit is contained in:
Moon Man 2024-01-28 08:58:59 -05:00
parent f2bd5e4795
commit e41193e489
3 changed files with 79 additions and 72 deletions

6
dist/bert.d.ts vendored
View File

@ -137,13 +137,13 @@ export declare class Bert {
encode: (obj: any, copy?: boolean) => Buffer;
decode: (buffer: Buffer) => any;
encode_string: (obj: string, buffer: Buffer) => Buffer;
encode_boolean: (obj: boolean, buffer: Buffer) => any;
encode_boolean: (obj: boolean, buffer: Buffer) => Buffer;
encode_number: (obj: number, buffer: Buffer) => Buffer;
encode_float: (obj: number, buffer: Buffer) => Buffer;
encode_object: (obj: any, buffer: Buffer) => any;
encode_object: (obj: any, buffer: Buffer) => Buffer;
encode_atom: (obj: any, buffer: Buffer) => Buffer;
encode_binary: (obj: Buffer, buffer: Buffer) => Buffer;
encode_undefined: (_obj: Buffer, buffer: Buffer) => any;
encode_undefined: (_obj: Buffer, buffer: Buffer) => Buffer;
encode_tuple: (obj: Buffer, buffer: Buffer) => Buffer;
encode_array: (obj: any[], buffer: Buffer) => Buffer;
encode_map: (obj: Record<string, any>, buffer: Buffer) => Buffer;

67
dist/bert.js vendored
View File

@ -39,22 +39,23 @@ export class Bert {
toTuple = toTuple;
#encode = (obj, buffer) => this[`encode_${typeof obj}`](obj, buffer);
encode = (obj, copy = true) => {
const tailBuffer = this.#encode(obj, Buffer.from(this.outputBuffer, 1));
const tailBuffer = this.#encode(obj, this.outputBuffer.subarray(1));
process.stderr.write(`tailbuffer length: ${tailBuffer.length}\n`);
if (tailBuffer.length === 0) {
throw new Error("Bert encode a too big term, encoding buffer overflow");
}
else if (copy) {
const ret = Buffer.alloc(tailBuffer.length);
this.outputBuffer.copy(ret, 0, 0, ret.length);
const ret = Buffer.alloc(tailBuffer.length + 1);
this.outputBuffer.copy(ret, 0, 0, ret.length + 1);
return ret;
}
else {
return Buffer.from(this.outputBuffer, 0, tailBuffer.length);
return this.outputBuffer.subarray(0, tailBuffer.length + 1);
}
};
#decode = (buffer) => {
const t = buffer[0];
buffer = Buffer.from(buffer, 1);
buffer = buffer.subarray(1);
switch (t) {
case Types.SMALL_ATOM:
return this.decode_atom(buffer, 1);
@ -102,13 +103,14 @@ export class Bert {
};
encode_string = (obj, buffer) => {
if (this.convention === Lang.ELIXIR) {
process.stderr.write(`encode string as elixir\n`);
return this.encode_binary(Buffer.from(obj), buffer);
}
else {
buffer[0] = Types.STRING;
buffer.writeUInt16BE(Buffer.byteLength(obj, "utf-8"), 1);
const len = buffer.write(obj, 3);
return Buffer.from(buffer, 0, 3 + len);
return buffer.subarray(0, 3 + len);
}
};
encode_boolean = (obj, buffer) => {
@ -129,13 +131,13 @@ export class Bert {
if (isInteger && obj >= 0 && obj < 256) {
buffer[0] = Types.SMALL_INTEGER;
buffer.writeUInt8(obj, 1);
return Buffer.from(buffer, 0, 2);
return buffer.subarray(0, 2);
}
// 4 byte int...
if (isInteger && obj >= -134217728 && obj <= 134217727) {
buffer[0] = Types.INTEGER;
buffer.writeInt32BE(obj, 1);
return Buffer.from(buffer, 0, 5);
return buffer.subarray(0, 5);
}
// Bignum...
const numBuffer = Buffer.alloc(buffer.length);
@ -156,20 +158,20 @@ export class Bert {
buffer[0] = Types.SMALL_BIG;
buffer.writeUInt8(offset - 1, 1);
numBuffer.copy(buffer, 2, 0, offset);
return Buffer.from(buffer, 0, 2 + offset);
return buffer.subarray(0, 2 + offset);
}
else {
buffer[0] = Types.LARGE_BIG;
buffer.writeUInt32BE(offset - 1, 1);
numBuffer.copy(buffer, 5, 0, offset);
return Buffer.from(buffer, 0, 5 + offset);
return buffer.subarray(0, 5 + offset);
}
};
encode_float = (obj, buffer) => {
// float...
buffer[0] = Types.NEW_FLOAT;
buffer.writeDoubleBE(obj, 1);
return Buffer.from(buffer, 0, 9);
return buffer.subarray(0, 9);
};
encode_object = (obj, buffer) => {
// Check if it's an atom, binary, or tuple...
@ -196,13 +198,14 @@ export class Bert {
buffer[0] = Types.ATOM;
buffer.writeUInt16BE(obj.value.length, 1);
const len = buffer.write(obj.value, 3);
return Buffer.from(buffer, 0, 3 + len);
return buffer.subarray(0, 3 + len);
};
encode_binary = (obj, buffer) => {
process.stderr.write(`encode binary\n`);
buffer[0] = Types.BINARY;
buffer.writeUInt32BE(obj.length, 1);
const len = obj.copy(buffer, 5);
return Buffer.from(buffer, 0, 5 + len);
return buffer.subarray(0, 5 + len);
};
encode_undefined = (_obj, buffer) => {
return this.#encode(null, buffer);
@ -211,12 +214,12 @@ export class Bert {
if (obj.length < 256) {
buffer[0] = Types.SMALL_TUPLE;
buffer.writeUInt8(obj.length, 1);
buffer = Buffer.from(buffer, 0, 2);
buffer = buffer.subarray(0, 2);
}
else {
buffer[0] = Types.LARGE_TUPLE;
buffer.writeUInt32BE(obj.length, 1);
buffer = Buffer.from(buffer, 0, 5);
buffer = buffer.subarray(0, 5);
}
for (let i = 0; i < obj.length; ++i) {
buffer = this.#encode(obj[i], buffer);
@ -226,22 +229,22 @@ export class Bert {
encode_array = (obj, buffer) => {
if (obj.length === 0) {
buffer[0] = Types.NIL;
return Buffer.from(buffer, 0, 1);
return buffer.subarray(0, 1);
}
buffer[0] = Types.LIST;
buffer.writeUInt32BE(obj.length, 1);
buffer = Buffer.from(buffer, 0, 5);
buffer = buffer.subarray(0, 5);
for (let i = 0; i < obj.length; ++i) {
buffer = this.#encode(obj[i], buffer);
}
buffer[0] = Types.NIL;
return Buffer.from(buffer, 0, 1);
return buffer.subarray(0, 1);
};
encode_map = (obj, buffer) => {
const keys = Object.keys(obj);
buffer[0] = Types.MAP;
buffer.writeUInt32BE(keys.length, 1);
buffer = Buffer.from(buffer, 0, 5);
buffer = buffer.subarray(0, 5);
for (let i = 0; i < keys.length; ++i) {
const key = this.mapKeyAsAtom ? this.toAtom(keys[i]) : keys[i];
buffer = this.#encode(key, buffer);
@ -274,7 +277,7 @@ export class Bert {
}
return {
value,
rest: Buffer.from(buffer, size),
rest: buffer.subarray(size),
};
};
decode_binary = (buffer) => {
@ -286,21 +289,21 @@ export class Bert {
value: this.convention === Lang.ELIXIR && this.allBinariesAsString
? bin.toString()
: bin,
rest: Buffer.from(buffer, size),
rest: buffer.subarray(size),
};
};
decode_integer = (buffer, count, unsigned = false) => {
return {
value: this.bytesToInt(buffer, count, unsigned),
rest: Buffer.from(buffer, count),
rest: buffer.subarray(count),
};
};
decode_big = (buffer, count) => {
const size = this.bytesToInt(buffer, count, false);
buffer = Buffer.from(buffer, count);
buffer = buffer.subarray(count);
let num = 0;
const isNegative = buffer[0] === 1;
buffer = Buffer.from(buffer, 1);
buffer = buffer.subarray(1);
for (let i = size - 1; i >= 0; --i) {
const n = buffer[i];
if (num === 0) {
@ -315,28 +318,28 @@ export class Bert {
}
return {
value: num,
rest: Buffer.from(buffer, size),
rest: buffer.subarray(size),
};
};
decode_float = (buffer) => {
const size = 31;
return {
value: parseFloat(buffer.toString("utf8", 0, size)),
rest: Buffer.from(buffer, size),
rest: buffer.subarray(size),
};
};
decode_new_float = (buffer) => {
return {
value: buffer.readDoubleBE(0),
rest: Buffer.from(buffer, 8),
rest: buffer.subarray(8),
};
};
decode_string = (buffer) => {
const size = this.bytesToInt(buffer, 2, true);
buffer = Buffer.from(buffer, 2);
buffer = buffer.subarray(2);
return {
value: buffer.toString("utf8", 0, size),
rest: Buffer.from(buffer, size),
rest: buffer.subarray(size),
};
};
decode_list = (buffer) => {
@ -352,7 +355,7 @@ export class Bert {
if (lastChar !== Types.NIL) {
throw new Error("List does not end with NIL");
}
buffer = Buffer.from(buffer, 1);
buffer = buffer.subarray(1);
return {
value: arr,
rest: buffer,
@ -361,7 +364,7 @@ export class Bert {
decode_map = (buffer) => {
const map = {};
const size = this.bytesToInt(buffer, 4, true);
buffer = Buffer.from(buffer, 4);
buffer = buffer.subarray(4);
for (let i = 0; i < size; ++i) {
let el = this.#decode(buffer);
const key = el.value;
@ -378,7 +381,7 @@ export class Bert {
decode_tuple = (buffer, count) => {
const arr = [];
const size = this.bytesToInt(buffer, count, true);
buffer = Buffer.from(buffer, count);
buffer = buffer.subarray(count);
for (let i = 0; i < size; ++i) {
const el = this.#decode(buffer);
arr.push(el.value);

View File

@ -47,32 +47,32 @@ export class Bert {
toAtom = toAtom;
toTuple = toTuple;
#encode = (obj: any, buffer: Buffer) =>
#encode = (obj: any, buffer: Buffer): Buffer =>
(this as any)[`encode_${typeof obj}`](obj, buffer);
encode = (obj: any, copy = true) => {
const tailBuffer = this.#encode(obj, Buffer.from(this.outputBuffer, 1));
const tailBuffer = this.#encode(obj, this.outputBuffer.subarray(1));
process.stderr.write(`tailbuffer length: ${tailBuffer.length}\n`);
if (tailBuffer.length === 0) {
throw new Error("Bert encode a too big term, encoding buffer overflow");
}
else if (copy) {
const ret = Buffer.alloc(tailBuffer.length);
this.outputBuffer.copy(ret, 0, 0, ret.length);
const ret = Buffer.alloc(tailBuffer.length + 1);
this.outputBuffer.copy(ret, 0, 0, ret.length + 1);
return ret;
}
else {
return Buffer.from(
this.outputBuffer,
return this.outputBuffer.subarray(
0,
tailBuffer.length,
tailBuffer.length + 1,
);
}
};
#decode = (buffer: Buffer): any => {
const t = buffer[0];
buffer = Buffer.from(buffer, 1);
buffer = buffer.subarray(1);
switch (t) {
case Types.SMALL_ATOM:
@ -126,20 +126,22 @@ export class Bert {
encode_string = (obj: string, buffer: Buffer) => {
if (this.convention === Lang.ELIXIR) {
process.stderr.write(`encode string as elixir\n`);
return this.encode_binary(Buffer.from(obj), buffer);
}
else {
buffer[0] = Types.STRING;
buffer.writeUInt16BE(Buffer.byteLength(obj, "utf-8"), 1);
const len = buffer.write(obj, 3);
return Buffer.from(buffer, 0, 3 + len);
return buffer.subarray(0, 3 + len);
}
};
encode_boolean = (obj: boolean, buffer: Buffer) => {
if (obj) {
return this.#encode(this.toAtom("true"), buffer);
} else {
}
else {
return this.#encode(this.toAtom("false"), buffer);
}
};
@ -156,14 +158,14 @@ export class Bert {
if (isInteger && obj >= 0 && obj < 256) {
buffer[0] = Types.SMALL_INTEGER;
buffer.writeUInt8(obj, 1);
return Buffer.from(buffer, 0, 2);
return buffer.subarray(0, 2);
}
// 4 byte int...
if (isInteger && obj >= -134217728 && obj <= 134217727) {
buffer[0] = Types.INTEGER;
buffer.writeInt32BE(obj, 1);
return Buffer.from(buffer, 0, 5);
return buffer.subarray(0, 5);
}
// Bignum...
@ -171,7 +173,8 @@ export class Bert {
if (obj < 0) {
obj *= -1;
numBuffer[0] = 1;
} else {
}
else {
numBuffer[0] = 0;
}
@ -186,12 +189,12 @@ export class Bert {
buffer[0] = Types.SMALL_BIG;
buffer.writeUInt8(offset - 1, 1);
numBuffer.copy(buffer, 2, 0, offset);
return Buffer.from(buffer, 0, 2 + offset);
return buffer.subarray(0, 2 + offset);
} else {
buffer[0] = Types.LARGE_BIG;
buffer.writeUInt32BE(offset - 1, 1);
numBuffer.copy(buffer, 5, 0, offset);
return Buffer.from(buffer, 0, 5 + offset);
return buffer.subarray(0, 5 + offset);
}
};
@ -199,7 +202,7 @@ export class Bert {
// float...
buffer[0] = Types.NEW_FLOAT;
buffer.writeDoubleBE(obj, 1);
return Buffer.from(buffer, 0, 9);
return buffer.subarray(0, 9);
};
encode_object = (obj: any, buffer: Buffer) => {
@ -230,14 +233,15 @@ export class Bert {
buffer[0] = Types.ATOM;
buffer.writeUInt16BE(obj.value.length, 1);
const len = buffer.write(obj.value, 3);
return Buffer.from(buffer, 0, 3 + len);
return buffer.subarray(0, 3 + len);
};
encode_binary = (obj: Buffer, buffer: Buffer) => {
process.stderr.write(`encode binary\n`);
buffer[0] = Types.BINARY;
buffer.writeUInt32BE(obj.length, 1);
const len = obj.copy(buffer, 5);
return Buffer.from(buffer, 0, 5 + len);
return buffer.subarray(0, 5 + len);
};
encode_undefined = (_obj: Buffer, buffer: Buffer) => {
@ -248,11 +252,11 @@ export class Bert {
if (obj.length < 256) {
buffer[0] = Types.SMALL_TUPLE;
buffer.writeUInt8(obj.length, 1);
buffer = Buffer.from(buffer, 0, 2);
buffer = buffer.subarray(0, 2);
} else {
buffer[0] = Types.LARGE_TUPLE;
buffer.writeUInt32BE(obj.length, 1);
buffer = Buffer.from(buffer, 0, 5);
buffer = buffer.subarray(0, 5);
}
for (let i = 0; i < obj.length; ++i) {
@ -265,25 +269,25 @@ export class Bert {
encode_array = (obj: any[], buffer: Buffer) => {
if (obj.length === 0) {
buffer[0] = Types.NIL;
return Buffer.from(buffer, 0, 1);
return buffer.subarray(0, 1);
}
buffer[0] = Types.LIST;
buffer.writeUInt32BE(obj.length, 1);
buffer = Buffer.from(buffer, 0, 5);
buffer = buffer.subarray(0, 5);
for (let i = 0; i < obj.length; ++i) {
buffer = this.#encode(obj[i], buffer);
}
buffer[0] = Types.NIL;
return Buffer.from(buffer, 0, 1);
return buffer.subarray(0, 1);
};
encode_map = (obj: Record<string, any>, buffer: Buffer) => {
const keys = Object.keys(obj);
buffer[0] = Types.MAP;
buffer.writeUInt32BE(keys.length, 1);
buffer = Buffer.from(buffer, 0, 5);
buffer = buffer.subarray(0, 5);
for (let i = 0; i < keys.length; ++i) {
const key = this.mapKeyAsAtom ? this.toAtom(keys[i]) : keys[i];
@ -318,7 +322,7 @@ export class Bert {
}
return {
value,
rest: Buffer.from(buffer, size),
rest: buffer.subarray(size),
};
};
@ -332,25 +336,25 @@ export class Bert {
this.convention === Lang.ELIXIR && this.allBinariesAsString
? bin.toString()
: bin,
rest: Buffer.from(buffer, size),
rest: buffer.subarray(size),
};
};
decode_integer = (buffer: Buffer, count: 1 | 2 | 4, unsigned = false) => {
return {
value: this.bytesToInt(buffer, count, unsigned),
rest: Buffer.from(buffer, count),
rest: buffer.subarray(count),
};
};
decode_big = (buffer: Buffer, count: 1 | 2 | 4) => {
const size = this.bytesToInt(buffer, count, false);
buffer = Buffer.from(buffer, count);
buffer = buffer.subarray(count);
let num = 0;
const isNegative = buffer[0] === 1;
buffer = Buffer.from(buffer, 1);
buffer = buffer.subarray(1);
for (let i = size - 1; i >= 0; --i) {
const n = buffer[i];
@ -366,7 +370,7 @@ export class Bert {
return {
value: num,
rest: Buffer.from(buffer, size),
rest: buffer.subarray(size),
};
};
@ -375,25 +379,25 @@ export class Bert {
return {
value: parseFloat(buffer.toString("utf8", 0, size)),
rest: Buffer.from(buffer, size),
rest: buffer.subarray(size),
};
};
decode_new_float = (buffer: Buffer) => {
return {
value: buffer.readDoubleBE(0),
rest: Buffer.from(buffer, 8),
rest: buffer.subarray(8),
};
};
decode_string = (buffer: Buffer) => {
const size = this.bytesToInt(buffer, 2, true);
buffer = Buffer.from(buffer, 2);
buffer = buffer.subarray(2);
return {
value: buffer.toString("utf8", 0, size),
rest: Buffer.from(buffer, size),
rest: buffer.subarray(size),
};
};
@ -414,7 +418,7 @@ export class Bert {
throw new Error("List does not end with NIL");
}
buffer = Buffer.from(buffer, 1);
buffer = buffer.subarray(1);
return {
value: arr,
@ -426,7 +430,7 @@ export class Bert {
const map: Record<string, any> = {};
const size = this.bytesToInt(buffer, 4, true);
buffer = Buffer.from(buffer, 4);
buffer = buffer.subarray(4);
for (let i = 0; i < size; ++i) {
let el = this.#decode(buffer);
@ -445,7 +449,7 @@ export class Bert {
decode_tuple = (buffer: Buffer, count: 1 | 2 | 4) => {
const arr = [];
const size = this.bytesToInt(buffer, count, true);
buffer = Buffer.from(buffer, count);
buffer = buffer.subarray(count);
for (let i = 0; i < size; ++i) {
const el = this.#decode(buffer);
arr.push(el.value);