my ts rlp decoder seems to work

i feel like i would have more confidence in my code if i didn't test it
This commit is contained in:
2022-10-23 06:41:19 -06:00
parent 2254c82f77
commit 7751e71982
6 changed files with 12856 additions and 10 deletions
+99
View File
@@ -0,0 +1,99 @@
export {
decoded_data,
decode_result,
decode
}
type decoded_data
= Uint8Array
| Array<decoded_data>;
type decode_result
= {decoded_data : decoded_data,
remainder : Uint8Array};
function
decode(bytes: Uint8Array): decode_result {
// check the first byte
let first_byte: number = bytes[0];
let rest : Uint8Array = bytes.slice(1);
// if the first byte is between 0 and 127, that is the data
if
(first_byte <= 127) {
return dr(new Uint8Array([first_byte]), rest);
}
// if the first byte is between 128 and 183 = 128 + 55, it is a bytestring
// and the length is Byte - 128
else if
(first_byte <= 183) {
let payload_byte_length : number = first_byte - 128;
let payload : Uint8Array = rest.slice(0, payload_byte_length);
let rest2 : Uint8Array = rest.slice(payload_byte_length);
return dr(payload, rest2);
}
// if the first byte is between 184 = 183 + 1 and 191 = 183 + 8, it is a
// bytestring. the byte length of bytestring is FirstByte - 183. Then pull
// out the actual data
else if
(first_byte <= 191) {
let byte_length_of_byte_length : number = first_byte - 183;
let bytes_of_byte_length : Uint8Array = rest.slice(0, byte_length_of_byte_length);
let byte_length : number = bytes_to_number(bytes_of_byte_length);
let bytes : Uint8Array = rest.slice(byte_length_of_byte_length,
byte_length + byte_length_of_byte_length);
let rest2 : Uint8Array = rest.slice(byte_length + byte_length_of_byte_length);
return dr(bytes, rest2);
}
// If the first byte is between 192 and 247 = 192 + 55, it is a list. The
// byte length of the list-payload is FirstByte - 192. Then the list
// payload, which needs to be decoded on its own.
else if
(first_byte <= 247) {
let byte_length_of_list : number = first_byte - 192;
let list_payload : Uint8Array = rest.slice(0, byte_length_of_list);
let list : Array<decoded_data> = decode_list(list_payload);
let rest2 : Uint8Array = rest.slice(byte_length_of_list);
return dr(list, rest2);
}
// If the first byte is between 248 = 247 + 1 and 255 = 247 + 8, it is a
// list. The byte length of the byte length of the list-payload is
// FirstByte - 247. Then the byte length of the list. Then the list
// payload, which needs to be decoded on its own.
else {
let byte_length_of_byte_length : number = first_byte - 247;
let bytes_of_byte_length : Uint8Array = rest.slice(0, byte_length_of_byte_length);
let byte_length : number = bytes_to_number(bytes_of_byte_length);
let list_bytes : Uint8Array = rest.slice(byte_length_of_byte_length,
byte_length + byte_length_of_byte_length);
let list : Array<decoded_data> = decode_list(list_bytes);
let rest2 : Uint8Array = rest.slice(byte_length + byte_length_of_byte_length);
return dr(list, rest2);
}
}
function decode_list(bytes: Uint8Array): Array<decoded_data> {
let arr : Array<decoded_data> = [];
while (bytes.length > 0) {
// grab an item off the bytes
let {decoded_data, remainder} = decode(bytes);
// push it
arr.push(decoded_data);
// update bytes
bytes = remainder;
}
return arr;
}
// convert bytestring to number
function bytes_to_number(bytes: Uint8Array) {
let n : number = 0;
for (let b of bytes) {
n <<= 8;
n += b;
}
return n;
}
function dr(x : decoded_data, y : Uint8Array) {
return {decoded_data: x, remainder: y};
}