react-native-binfileutils
Version:
Utils to work with iden3 binary files.
188 lines (151 loc) • 6.25 kB
JavaScript
;
Object.defineProperty(exports, '__esModule', { value: true });
var reactNativeFfjavascript = require('react-native-ffjavascript');
var fastFile = require('fastfile');
function _interopNamespace(e) {
if (e && e.__esModule) return e;
var n = Object.create(null);
if (e) {
Object.keys(e).forEach(function (k) {
if (k !== 'default') {
var d = Object.getOwnPropertyDescriptor(e, k);
Object.defineProperty(n, k, d.get ? d : {
enumerable: true,
get: function () { return e[k]; }
});
}
});
}
n["default"] = e;
return Object.freeze(n);
}
var fastFile__namespace = /*#__PURE__*/_interopNamespace(fastFile);
async function readBinFile(fileName, type, maxVersion, cacheSize, pageSize) {
const fd = await fastFile__namespace.readExisting(fileName, cacheSize, pageSize);
const b = await fd.read(4);
let readedType = "";
for (let i=0; i<4; i++) readedType += String.fromCharCode(b[i]);
if (readedType != type) throw new Error(fileName + ": Invalid File format");
let v = await fd.readULE32();
if (v>maxVersion) throw new Error("Version not supported");
const nSections = await fd.readULE32();
// Scan sections
let sections = [];
for (let i=0; i<nSections; i++) {
let ht = await fd.readULE32();
let hl = await fd.readULE64();
if (typeof sections[ht] == "undefined") sections[ht] = [];
sections[ht].push({
p: fd.pos,
size: hl
});
fd.pos += hl;
}
return {fd, sections};
}
async function createBinFile(fileName, type, version, nSections, cacheSize, pageSize) {
const fd = await fastFile__namespace.createOverride(fileName, cacheSize, pageSize);
const buff = new Uint8Array(4);
for (let i=0; i<4; i++) buff[i] = type.charCodeAt(i);
await fd.write(buff, 0); // Magic "r1cs"
await fd.writeULE32(version); // Version
await fd.writeULE32(nSections); // Number of Sections
return fd;
}
async function startWriteSection(fd, idSection) {
if (typeof fd.writingSection !== "undefined") throw new Error("Already writing a section");
await fd.writeULE32(idSection); // Header type
fd.writingSection = {
pSectionSize: fd.pos
};
await fd.writeULE64(0); // Temporally set to 0 length
}
async function endWriteSection(fd) {
if (typeof fd.writingSection === "undefined") throw new Error("Not writing a section");
const sectionSize = fd.pos - fd.writingSection.pSectionSize - 8;
const oldPos = fd.pos;
fd.pos = fd.writingSection.pSectionSize;
await fd.writeULE64(sectionSize);
fd.pos = oldPos;
delete fd.writingSection;
}
async function startReadUniqueSection(fd, sections, idSection) {
if (typeof fd.readingSection !== "undefined") throw new Error("Already reading a section");
if (!sections[idSection]) throw new Error(fd.fileName + ": Missing section "+ idSection );
if (sections[idSection].length>1) throw new Error(fd.fileName +": Section Duplicated " +idSection);
fd.pos = sections[idSection][0].p;
fd.readingSection = sections[idSection][0];
}
async function endReadSection(fd, noCheck) {
if (typeof fd.readingSection === "undefined") throw new Error("Not reading a section");
if (!noCheck) {
if (fd.pos-fd.readingSection.p != fd.readingSection.size) throw new Error("Invalid section size reading");
}
delete fd.readingSection;
}
async function writeBigInt(fd, n, n8, pos) {
const buff = new Uint8Array(n8);
reactNativeFfjavascript.Scalar.toRprLE(buff, 0, n, n8);
await fd.write(buff, pos);
}
async function readBigInt(fd, n8, pos) {
const buff = await fd.read(n8, pos);
return reactNativeFfjavascript.Scalar.fromRprLE(buff, 0, n8);
}
async function copySection(fdFrom, sections, fdTo, sectionId, size) {
if (typeof size === "undefined") {
size = sections[sectionId][0].size;
}
const chunkSize = fdFrom.pageSize;
await startReadUniqueSection(fdFrom, sections, sectionId);
await startWriteSection(fdTo, sectionId);
for (let p=0; p<size; p+=chunkSize) {
const l = Math.min(size -p, chunkSize);
const buff = await fdFrom.read(l);
await fdTo.write(buff);
}
await endWriteSection(fdTo);
await endReadSection(fdFrom, size != sections[sectionId][0].size);
}
async function readSection(fd, sections, idSection, offset, length) {
offset = (typeof offset === "undefined") ? 0 : offset;
length = (typeof length === "undefined") ? sections[idSection][0].size - offset : length;
if (offset + length > sections[idSection][0].size) {
throw new Error("Reading out of the range of the section");
}
let buff;
if (length < (1 << 30) ) {
buff = new Uint8Array(length);
} else {
buff = new reactNativeFfjavascript.BigBuffer(length);
}
await fd.readToBuffer(buff, 0, length, sections[idSection][0].p + offset);
return buff;
}
async function sectionIsEqual(fd1, sections1, fd2, sections2, idSection) {
const MAX_BUFF_SIZE = fd1.pageSize * 16;
await startReadUniqueSection(fd1, sections1, idSection);
await startReadUniqueSection(fd2, sections2, idSection);
if (sections1[idSection][0].size != sections2[idSection][0].size) return false;
const totalBytes=sections1[idSection][0].size;
for (let i=0; i<totalBytes; i+= MAX_BUFF_SIZE) {
const n = Math.min(totalBytes-i, MAX_BUFF_SIZE);
const buff1 = await fd1.read(n);
const buff2 = await fd2.read(n);
for (let j=0; j<n; j++) if (buff1[j] != buff2[j]) return false;
}
await endReadSection(fd1);
await endReadSection(fd2);
return true;
}
exports.copySection = copySection;
exports.createBinFile = createBinFile;
exports.endReadSection = endReadSection;
exports.endWriteSection = endWriteSection;
exports.readBigInt = readBigInt;
exports.readBinFile = readBinFile;
exports.readSection = readSection;
exports.sectionIsEqual = sectionIsEqual;
exports.startReadUniqueSection = startReadUniqueSection;
exports.startWriteSection = startWriteSection;
exports.writeBigInt = writeBigInt;