73 lines
2.2 KiB
JavaScript
73 lines
2.2 KiB
JavaScript
// The RLP format
|
|
// Serialization and deserialization for the BytesTree type, under the following grammar:
|
|
// | First byte | Meaning |
|
|
// | ---------- | -------------------------------------------------------------------------- |
|
|
// | 0 to 127 | HEX(leaf) |
|
|
// | 128 to 183 | HEX(length_of_leaf + 128) + HEX(leaf) |
|
|
// | 184 to 191 | HEX(length_of_length_of_leaf + 128 + 55) + HEX(length_of_leaf) + HEX(leaf) |
|
|
// | 192 to 247 | HEX(length_of_node + 192) + HEX(node) |
|
|
// | 248 to 255 | HEX(length_of_length_of_node + 128 + 55) + HEX(length_of_node) + HEX(node) |
|
|
|
|
const encode = tree => {
|
|
const padEven = str =>
|
|
str.length % 2 === 0 ? str : "0" + str;
|
|
|
|
const uint = num =>
|
|
padEven(num.toString(16))
|
|
|
|
const length = (len, add) =>
|
|
len < 56 ? uint(add + len) : uint(add + uint(len).length / 2 + 55) + uint(len);
|
|
|
|
const dataTree = tree => {
|
|
if (typeof tree === "string") {
|
|
const hex = tree.slice(2);
|
|
const pre = hex.length != 2 || hex >= "80" ? length(hex.length / 2, 128) : "";
|
|
return pre + hex;
|
|
} else {
|
|
const hex = tree.map(dataTree).join("");
|
|
const pre = length(hex.length / 2, 192)
|
|
return pre + hex;
|
|
}
|
|
}
|
|
|
|
return "0x" + dataTree(tree);
|
|
};
|
|
|
|
const decode = hex => {
|
|
let i = 2;
|
|
|
|
const parseTree = () => {
|
|
if (i >= hex.length) throw "";
|
|
const head = hex.slice(i,i+2);
|
|
return head < "80" ? (i+=2, "0x" + head)
|
|
: head < "c0" ? parseHex()
|
|
: parseList();
|
|
}
|
|
|
|
const parseLength = () => {
|
|
const len = parseInt(hex.slice(i,i+=2), 16) % 64;
|
|
return len < 56 ? len : parseInt(hex.slice(i, i += (len - 55) * 2), 16);
|
|
}
|
|
|
|
const parseHex = () => {
|
|
const len = parseLength();
|
|
return "0x" + hex.slice(i, i += len * 2);
|
|
}
|
|
|
|
const parseList = () => {
|
|
const lim = parseLength() * 2 + i;
|
|
let list = [];
|
|
while (i < lim)
|
|
list.push(parseTree());
|
|
return list;
|
|
}
|
|
|
|
try {
|
|
return parseTree();
|
|
} catch (e) {
|
|
return [];
|
|
}
|
|
};
|
|
|
|
module.exports = {encode, decode};
|