@fizzyflow/suisql
Version:
SuiSQL is a library and set of tools for working with decentralized SQL databases on the Sui blockchain and Walrus protocol.
99 lines (80 loc) • 2.33 kB
text/typescript
import { compress, decompress } from './SuiSqlUtils.js';
export default class SuiSqlBinaryPatch {
/**
* Applies a binary patch to an original Uint8Array.
* @param {Uint8Array} original - The original array to be patched.
* @param {Uint8Array} binaryPatch - The binary patch to apply.
* @returns {Uint8Array} - The patched array.
*/
static applyPatch(original: Uint8Array, binaryPatch: Uint8Array) {
const result = new Uint8Array(original);
let offset = 0;
while (offset < binaryPatch.length) {
const start = (
(binaryPatch[offset] << 24) |
(binaryPatch[offset + 1] << 16) |
(binaryPatch[offset + 2] << 8) |
binaryPatch[offset + 3]
);
const length = (binaryPatch[offset + 4] << 8) | binaryPatch[offset + 5];
offset += 6;
const newBytes = binaryPatch.slice(offset, offset + length);
result.set(newBytes, start);
offset += length;
}
return result;
}
static async compressedBinaryDiff(a: Uint8Array, b: Uint8Array) {
return compress(this.binaryDiff(a, b));
}
static binaryDiff(a: Uint8Array, b: Uint8Array) {
return this.encodeFixedLengthPatch(this.diff(a, b));
}
static diff(a: Uint8Array, b: Uint8Array) {
if (a.length !== b.length) {
throw new Error("Arrays must be of equal length");
}
const patch = [];
let i = 0;
while (i < a.length) {
if (a[i] === b[i]) {
i++;
continue;
}
const start = i;
while (i < a.length && a[i] !== b[i]) {
i++;
}
patch.push({
start,
length: i - start,
newBytes: b.slice(start, i),
});
}
return patch;
}
static encodeFixedLengthPatch(patch: any[]) {
const chunks = [];
for (const { start, length, newBytes } of patch) {
const header = new Uint8Array(6);
header[0] = (start >>> 24) & 0xff;
header[1] = (start >>> 16) & 0xff;
header[2] = (start >>> 8) & 0xff;
header[3] = start & 0xff;
header[4] = (length >>> 8) & 0xff;
header[5] = length & 0xff;
chunks.push(header, newBytes);
}
return this.concatUint8Arrays(chunks);
}
static concatUint8Arrays(arrays: Uint8Array[]) {
const totalLength = arrays.reduce((sum, arr) => sum + arr.length, 0);
const result = new Uint8Array(totalLength);
let offset = 0;
for (const arr of arrays) {
result.set(arr, offset);
offset += arr.length;
}
return result;
}
}