[wip] start making vanillae js library
It compiles but there's some NYI functions This is going to have all the common functions that we need all over the place - base64 encode/decode - base58 encode/decode - rlp encode/decode - transaction types - transaction formation - reading stuff from the transaction - safe type - (maybe) AWCP This commit contains a refactored version of my prior base64 implementation, which is more imperativey and less "trying to fit Erlang into TS".
This commit is contained in:
@@ -0,0 +1 @@
|
||||
dist
|
||||
@@ -0,0 +1,5 @@
|
||||
{type, library}.
|
||||
{realm, local}.
|
||||
{name, vanillae}.
|
||||
{version, "0.1.0"}.
|
||||
{deps, []}.
|
||||
@@ -0,0 +1,304 @@
|
||||
/**
|
||||
* Base64 Utility Functions in TypeScript
|
||||
*/
|
||||
|
||||
export {
|
||||
encode
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Encode an array of bytes as a Uint8Array in base64 notation.
|
||||
*/
|
||||
function
|
||||
encode(bytes: Uint8Array): string {
|
||||
// slice the array
|
||||
// length of head is a multiple of 3
|
||||
// treat the tail as a special case
|
||||
let {head, tail, tail_len} = slice3k(bytes);
|
||||
let head_str : string = encode_head(head);
|
||||
let tail_str : string = encode_tail(tail, tail_len);
|
||||
return head_str + tail_str;
|
||||
}
|
||||
|
||||
|
||||
|
||||
type slice3k = {head : Uint8Array,
|
||||
tail : Uint8Array,
|
||||
tail_len : number};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Take a Uint8Array, take the first 3k (k >= 0) bytes, put them in head, and
|
||||
* the remaining 0,1, or 2 bytes, put them in tail
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
function
|
||||
slice3k(bytes: Uint8Array): slice3k {
|
||||
let len : number = bytes.length;
|
||||
// too lazy to look up how to do integer division in js so this will do
|
||||
let tail_len : number = len % 3;
|
||||
let head_len : number = len - tail_len;
|
||||
// for slice:
|
||||
// first argument is the 0-index of the start
|
||||
// second - first is the length of the slice
|
||||
let head : Uint8Array = bytes.slice(0, head_len);
|
||||
// empty second argument means go to the end
|
||||
let tail : Uint8Array = bytes.slice(head_len);
|
||||
return {head : head,
|
||||
tail : tail,
|
||||
tail_len : tail_len};
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Encode a Uint8Array whose length is known to be a multiple of 3
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
function
|
||||
encode_head(head_bytes: Uint8Array): string {
|
||||
// can assume length of bytes is a multiple of 3
|
||||
// start index at 0
|
||||
// increment by 3
|
||||
let head_bytes_len : number = head_bytes.length;
|
||||
let max_idx0 : number = head_bytes_len - 1;
|
||||
|
||||
let head_str_acc : string = '';
|
||||
for(let this_3slice_start_idx0 = 0;
|
||||
this_3slice_start_idx0 <= max_idx0;
|
||||
this_3slice_start_idx0 += 3)
|
||||
{
|
||||
let this_3slice_bytes : Uint8Array = head_bytes.slice(this_3slice_start_idx0, this_3slice_start_idx0 + 3);
|
||||
let this_3slice_str : string = encode3(this_3slice_bytes);
|
||||
head_str_acc += this_3slice_str;
|
||||
}
|
||||
|
||||
return head_str_acc;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Encode a 3 bytes into base64 notation
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
function
|
||||
encode3(bytes: Uint8Array) {
|
||||
let b0 : number = bytes[0];
|
||||
let b1 : number = bytes[1];
|
||||
let b2 : number = bytes[2];
|
||||
|
||||
// ABCDEFGH 12345678 ABCDEFGH
|
||||
// b0 b1 b2
|
||||
// ABCDEF GH1234 5678AB CDEFGH
|
||||
// n0 n1 n2 n3
|
||||
let n0 : number = b0 >> 2;
|
||||
// n1 = 00GH1234
|
||||
// b0 = ABCDEFGH
|
||||
// 4 = 00000100
|
||||
// b0 % 4 = 000000GH
|
||||
// (b0 % 4) << 4 = 00GH0000
|
||||
// b1 = 12345678
|
||||
// b1 >> 4 = 00001234
|
||||
let n1 : number = ((b0 % 4) << 4) + (b1 >> 4);
|
||||
// n2 = 005678AB
|
||||
// b1 = 12345678
|
||||
// 16 = 00010000
|
||||
// b1 % 16 = 00005678
|
||||
// (b1 % 16) << 2 = 00567800
|
||||
// b1 = ABCDEFGH
|
||||
// b1 >> 6 = 000000AB
|
||||
let n2 : number = ((b1 % 16) << 2) + (b1 >> 6);
|
||||
// n3 = 00CDEFGH
|
||||
// 64 = 01000000
|
||||
// b2 = ABCDEFGH
|
||||
let n3 : number = b2 % 64;
|
||||
|
||||
// convert to chars
|
||||
let s0 : string = int2char(n0);
|
||||
let s1 : string = int2char(n1);
|
||||
let s2 : string = int2char(n2);
|
||||
let s3 : string = int2char(n3);
|
||||
|
||||
// retrvn
|
||||
return s0 + s1 + s2 + s3;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Encode the final 0, 1, or 2 bytes
|
||||
*
|
||||
* FIXME: nyi
|
||||
*/
|
||||
function
|
||||
encode_tail(tail_bytes : Uint8Array,
|
||||
tail_len : number)
|
||||
: string
|
||||
{
|
||||
throw new Error('nyi');
|
||||
}
|
||||
|
||||
/**
|
||||
* Conversion table for base64 encode
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
function
|
||||
int2char(n: number): string
|
||||
{
|
||||
switch(n) {
|
||||
case 0: return 'A';
|
||||
case 1: return 'B';
|
||||
case 2: return 'C';
|
||||
case 3: return 'D';
|
||||
case 4: return 'E';
|
||||
case 5: return 'F';
|
||||
case 6: return 'G';
|
||||
case 7: return 'H';
|
||||
case 8: return 'I';
|
||||
case 9: return 'J';
|
||||
case 10: return 'K';
|
||||
case 11: return 'L';
|
||||
case 12: return 'M';
|
||||
case 13: return 'N';
|
||||
case 14: return 'O';
|
||||
case 15: return 'P';
|
||||
case 16: return 'Q';
|
||||
case 17: return 'R';
|
||||
case 18: return 'S';
|
||||
case 19: return 'T';
|
||||
case 20: return 'U';
|
||||
case 21: return 'V';
|
||||
case 22: return 'W';
|
||||
case 23: return 'X';
|
||||
case 24: return 'Y';
|
||||
case 25: return 'Z';
|
||||
case 26: return 'a';
|
||||
case 27: return 'b';
|
||||
case 28: return 'c';
|
||||
case 29: return 'd';
|
||||
case 30: return 'e';
|
||||
case 31: return 'f';
|
||||
case 32: return 'g';
|
||||
case 33: return 'h';
|
||||
case 34: return 'i';
|
||||
case 35: return 'j';
|
||||
case 36: return 'k';
|
||||
case 37: return 'l';
|
||||
case 38: return 'm';
|
||||
case 39: return 'n';
|
||||
case 40: return 'o';
|
||||
case 41: return 'p';
|
||||
case 42: return 'q';
|
||||
case 43: return 'r';
|
||||
case 44: return 's';
|
||||
case 45: return 't';
|
||||
case 46: return 'u';
|
||||
case 47: return 'v';
|
||||
case 48: return 'w';
|
||||
case 49: return 'x';
|
||||
case 50: return 'y';
|
||||
case 51: return 'z';
|
||||
case 52: return '0';
|
||||
case 53: return '1';
|
||||
case 54: return '2';
|
||||
case 55: return '3';
|
||||
case 56: return '4';
|
||||
case 57: return '5';
|
||||
case 58: return '6';
|
||||
case 59: return '7';
|
||||
case 60: return '8';
|
||||
case 61: return '9';
|
||||
case 62: return '+';
|
||||
case 63: return '/';
|
||||
default: throw new Error("invalid base64 encode byte: " + n);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Conversion table for base64 decode
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
function
|
||||
char2int(s: string): number
|
||||
{
|
||||
switch(s) {
|
||||
case 'A': return 0;
|
||||
case 'B': return 1;
|
||||
case 'C': return 2;
|
||||
case 'D': return 3;
|
||||
case 'E': return 4;
|
||||
case 'F': return 5;
|
||||
case 'G': return 6;
|
||||
case 'H': return 7;
|
||||
case 'I': return 8;
|
||||
case 'J': return 9;
|
||||
case 'K': return 10;
|
||||
case 'L': return 11;
|
||||
case 'M': return 12;
|
||||
case 'N': return 13;
|
||||
case 'O': return 14;
|
||||
case 'P': return 15;
|
||||
case 'Q': return 16;
|
||||
case 'R': return 17;
|
||||
case 'S': return 18;
|
||||
case 'T': return 19;
|
||||
case 'U': return 20;
|
||||
case 'V': return 21;
|
||||
case 'W': return 22;
|
||||
case 'X': return 23;
|
||||
case 'Y': return 24;
|
||||
case 'Z': return 25;
|
||||
case 'a': return 26;
|
||||
case 'b': return 27;
|
||||
case 'c': return 28;
|
||||
case 'd': return 29;
|
||||
case 'e': return 30;
|
||||
case 'f': return 31;
|
||||
case 'g': return 32;
|
||||
case 'h': return 33;
|
||||
case 'i': return 34;
|
||||
case 'j': return 35;
|
||||
case 'k': return 36;
|
||||
case 'l': return 37;
|
||||
case 'm': return 38;
|
||||
case 'n': return 39;
|
||||
case 'o': return 40;
|
||||
case 'p': return 41;
|
||||
case 'q': return 42;
|
||||
case 'r': return 43;
|
||||
case 's': return 44;
|
||||
case 't': return 45;
|
||||
case 'u': return 46;
|
||||
case 'v': return 47;
|
||||
case 'w': return 48;
|
||||
case 'x': return 49;
|
||||
case 'y': return 50;
|
||||
case 'z': return 51;
|
||||
case '0': return 52;
|
||||
case '1': return 53;
|
||||
case '2': return 54;
|
||||
case '3': return 55;
|
||||
case '4': return 56;
|
||||
case '5': return 57;
|
||||
case '6': return 58;
|
||||
case '7': return 59;
|
||||
case '8': return 60;
|
||||
case '9': return 61;
|
||||
case '+': return 62;
|
||||
case '/': return 63;
|
||||
default: throw new Error("invalid base64 character: " + s);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
{"compilerOptions" : {"target" : "es2022",
|
||||
"strict" : true,
|
||||
"esModuleInterop" : true,
|
||||
"skipLibCheck" : true,
|
||||
"forceConsistentCasingInFileNames" : true,
|
||||
"noImplicitAny" : true,
|
||||
"strictNullChecks" : true,
|
||||
"strictPropertyInitialization" : true,
|
||||
"sourceMap" : true,
|
||||
"outDir" : "dist",
|
||||
"declaration" : true},
|
||||
"$schema" : "https://json.schemastore.org/tsconfig",
|
||||
"display" : "Recommended",
|
||||
"include" : ["src/**/*"],
|
||||
"exclude" : ["src/jex_include"],
|
||||
"composite" : true}
|
||||
Reference in New Issue
Block a user