ox
Version:
173 lines • 5.73 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
exports.toBytes = toBytes;
exports.toHex = toHex;
exports.to = to;
exports.decodeRlpCursor = decodeRlpCursor;
exports.readLength = readLength;
exports.readList = readList;
exports.from = from;
exports.fromBytes = fromBytes;
exports.fromHex = fromHex;
const Bytes = require("./Bytes.js");
const Errors = require("./Errors.js");
const Hex = require("./Hex.js");
const Cursor = require("./internal/cursor.js");
function toBytes(value) {
return to(value, 'Bytes');
}
function toHex(value) {
return to(value, 'Hex');
}
function to(value, to) {
const to_ = to ?? (typeof value === 'string' ? 'Hex' : 'Bytes');
const bytes = (() => {
if (typeof value === 'string') {
if (value.length > 3 && value.length % 2 !== 0)
throw new Hex.InvalidLengthError(value);
return Bytes.fromHex(value);
}
return value;
})();
const cursor = Cursor.create(bytes, {
recursiveReadLimit: Number.POSITIVE_INFINITY,
});
const result = decodeRlpCursor(cursor, to_);
return result;
}
function decodeRlpCursor(cursor, to = 'Hex') {
if (cursor.bytes.length === 0)
return (to === 'Hex' ? Hex.fromBytes(cursor.bytes) : cursor.bytes);
const prefix = cursor.readByte();
if (prefix < 0x80)
cursor.decrementPosition(1);
if (prefix < 0xc0) {
const length = readLength(cursor, prefix, 0x80);
const bytes = cursor.readBytes(length);
return (to === 'Hex' ? Hex.fromBytes(bytes) : bytes);
}
const length = readLength(cursor, prefix, 0xc0);
return readList(cursor, length, to);
}
function readLength(cursor, prefix, offset) {
if (offset === 0x80 && prefix < 0x80)
return 1;
if (prefix <= offset + 55)
return prefix - offset;
if (prefix === offset + 55 + 1)
return cursor.readUint8();
if (prefix === offset + 55 + 2)
return cursor.readUint16();
if (prefix === offset + 55 + 3)
return cursor.readUint24();
if (prefix === offset + 55 + 4)
return cursor.readUint32();
throw new Errors.BaseError('Invalid RLP prefix');
}
function readList(cursor, length, to) {
const position = cursor.position;
const value = [];
while (cursor.position - position < length)
value.push(decodeRlpCursor(cursor, to));
return value;
}
function from(value, options) {
const { as } = options;
const encodable = getEncodable(value);
const cursor = Cursor.create(new Uint8Array(encodable.length));
encodable.encode(cursor);
if (as === 'Hex')
return Hex.fromBytes(cursor.bytes);
return cursor.bytes;
}
function fromBytes(bytes, options = {}) {
const { as = 'Bytes' } = options;
return from(bytes, { as });
}
function fromHex(hex, options = {}) {
const { as = 'Hex' } = options;
return from(hex, { as });
}
function getEncodable(bytes) {
if (Array.isArray(bytes))
return getEncodableList(bytes.map((x) => getEncodable(x)));
return getEncodableBytes(bytes);
}
function getEncodableList(list) {
const bodyLength = list.reduce((acc, x) => acc + x.length, 0);
const sizeOfBodyLength = getSizeOfLength(bodyLength);
const length = (() => {
if (bodyLength <= 55)
return 1 + bodyLength;
return 1 + sizeOfBodyLength + bodyLength;
})();
return {
length,
encode(cursor) {
if (bodyLength <= 55) {
cursor.pushByte(0xc0 + bodyLength);
}
else {
cursor.pushByte(0xc0 + 55 + sizeOfBodyLength);
if (sizeOfBodyLength === 1)
cursor.pushUint8(bodyLength);
else if (sizeOfBodyLength === 2)
cursor.pushUint16(bodyLength);
else if (sizeOfBodyLength === 3)
cursor.pushUint24(bodyLength);
else
cursor.pushUint32(bodyLength);
}
for (const { encode } of list) {
encode(cursor);
}
},
};
}
function getEncodableBytes(bytesOrHex) {
const bytes = typeof bytesOrHex === 'string' ? Bytes.fromHex(bytesOrHex) : bytesOrHex;
const sizeOfBytesLength = getSizeOfLength(bytes.length);
const length = (() => {
if (bytes.length === 1 && bytes[0] < 0x80)
return 1;
if (bytes.length <= 55)
return 1 + bytes.length;
return 1 + sizeOfBytesLength + bytes.length;
})();
return {
length,
encode(cursor) {
if (bytes.length === 1 && bytes[0] < 0x80) {
cursor.pushBytes(bytes);
}
else if (bytes.length <= 55) {
cursor.pushByte(0x80 + bytes.length);
cursor.pushBytes(bytes);
}
else {
cursor.pushByte(0x80 + 55 + sizeOfBytesLength);
if (sizeOfBytesLength === 1)
cursor.pushUint8(bytes.length);
else if (sizeOfBytesLength === 2)
cursor.pushUint16(bytes.length);
else if (sizeOfBytesLength === 3)
cursor.pushUint24(bytes.length);
else
cursor.pushUint32(bytes.length);
cursor.pushBytes(bytes);
}
},
};
}
function getSizeOfLength(length) {
if (length <= 0xff)
return 1;
if (length <= 0xff_ff)
return 2;
if (length <= 0xff_ff_ff)
return 3;
if (length <= 0xff_ff_ff_ff)
return 4;
throw new Errors.BaseError('Length is too large.');
}
//# sourceMappingURL=Rlp.js.map
;