Files
ffjavascript/src/utils_native.js
2021-12-01 10:25:47 +01:00

182 lines
5.0 KiB
JavaScript

/* global BigInt */
import * as Scalar from "./scalar.js";
export function stringifyBigInts(o) {
if ((typeof(o) == "bigint") || o.eq !== undefined) {
return o.toString(10);
} else if (o instanceof Uint8Array) {
return Scalar.fromRprLE(o, 0);
} else if (Array.isArray(o)) {
return o.map(stringifyBigInts);
} else if (typeof o == "object") {
const res = {};
const keys = Object.keys(o);
keys.forEach( (k) => {
res[k] = stringifyBigInts(o[k]);
});
return res;
} else {
return o;
}
}
export function unstringifyBigInts(o) {
if ((typeof(o) == "string") && (/^[0-9]+$/.test(o) )) {
return BigInt(o);
} else if ((typeof(o) == "string") && (/^0x[0-9a-fA-F]+$/.test(o) )) {
return BigInt(o);
} else if (Array.isArray(o)) {
return o.map(unstringifyBigInts);
} else if (typeof o == "object") {
if (o===null) return null;
const res = {};
const keys = Object.keys(o);
keys.forEach( (k) => {
res[k] = unstringifyBigInts(o[k]);
});
return res;
} else {
return o;
}
}
export function beBuff2int(buff) {
let res = BigInt(0);
let i = buff.length;
let offset = 0;
const buffV = new DataView(buff.buffer, buff.byteOffset, buff.byteLength);
while (i>0) {
if (i >= 4) {
i -= 4;
res += BigInt(buffV.getUint32(i)) << BigInt(offset*8);
offset += 4;
} else if (i >= 2) {
i -= 2;
res += BigInt(buffV.getUint16(i)) << BigInt(offset*8);
offset += 2;
} else {
i -= 1;
res += BigInt(buffV.getUint8(i)) << BigInt(offset*8);
offset += 1;
}
}
return res;
}
export function beInt2Buff(n, len) {
let r = n;
const buff = new Uint8Array(len);
const buffV = new DataView(buff.buffer);
let o = len;
while (o > 0) {
if (o-4 >= 0) {
o -= 4;
buffV.setUint32(o, Number(r & BigInt(0xFFFFFFFF)));
r = r >> BigInt(32);
} else if (o-2 >= 0) {
o -= 2;
buffV.setUint16(o, Number(r & BigInt(0xFFFF)));
r = r >> BigInt(16);
} else {
o -= 1;
buffV.setUint8(o, Number(r & BigInt(0xFF)));
r = r >> BigInt(8);
}
}
if (r) {
throw new Error("Number does not fit in this length");
}
return buff;
}
export function leBuff2int(buff) {
let res = BigInt(0);
let i = 0;
const buffV = new DataView(buff.buffer, buff.byteOffset, buff.byteLength);
while (i<buff.length) {
if (i + 4 <= buff.length) {
res += BigInt(buffV.getUint32(i, true)) << BigInt( i*8);
i += 4;
} else if (i + 4 <= buff.length) {
res += BigInt(buffV.getUint16(i, true)) << BigInt( i*8);
i += 2;
} else {
res += BigInt(buffV.getUint8(i, true)) << BigInt( i*8);
i += 1;
}
}
return res;
}
export function leInt2Buff(n, len) {
let r = n;
if (typeof len === "undefined") {
len = Math.floor((Scalar.bitLength(n) - 1) / 8) +1;
if (len==0) len = 1;
}
const buff = new Uint8Array(len);
const buffV = new DataView(buff.buffer);
let o = 0;
while (o < len) {
if (o+4 <= len) {
buffV.setUint32(o, Number(r & BigInt(0xFFFFFFFF)), true );
o += 4;
r = r >> BigInt(32);
} else if (o+2 <= len) {
buffV.setUint16(Number(o, r & BigInt(0xFFFF)), true );
o += 2;
r = r >> BigInt(16);
} else {
buffV.setUint8(Number(o, r & BigInt(0xFF)), true );
o += 1;
r = r >> BigInt(8);
}
}
if (r) {
throw new Error("Number does not fit in this length");
}
return buff;
}
export function stringifyFElements(F, o) {
if ((typeof(o) == "bigint") || o.eq !== undefined) {
return o.toString(10);
} else if (o instanceof Uint8Array) {
return F.toString(F.e(o));
} else if (Array.isArray(o)) {
return o.map(stringifyFElements.bind(this,F));
} else if (typeof o == "object") {
const res = {};
const keys = Object.keys(o);
keys.forEach( (k) => {
res[k] = stringifyFElements(F, o[k]);
});
return res;
} else {
return o;
}
}
export function unstringifyFElements(F, o) {
if ((typeof(o) == "string") && (/^[0-9]+$/.test(o) )) {
return F.e(o);
} else if ((typeof(o) == "string") && (/^0x[0-9a-fA-F]+$/.test(o) )) {
return F.e(o);
} else if (Array.isArray(o)) {
return o.map(unstringifyFElements.bind(this,F));
} else if (typeof o == "object") {
if (o===null) return null;
const res = {};
const keys = Object.keys(o);
keys.forEach( (k) => {
res[k] = unstringifyFElements(F, o[k]);
});
return res;
} else {
return o;
}
}