mirror of
https://github.com/CryptKeeperZK/ffjavascript.git
synced 2026-05-03 03:00:11 -04:00
182 lines
5.0 KiB
JavaScript
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;
|
|
}
|
|
}
|