Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 | 191x 191x 191x 191x 595x 595x 191x 181x 181x 181x 3307020x 181x 181x 181x 1x 180x 180x 180x 45x 23x 22x 9x 13x 6x 11x 11x 30x 11x | /**
* Convert a TypedArray to a base64 string for JSON serialization.
* @param {ArrayBufferView} typedArray
* @returns {string} base64-encoded string
*/
export function typedArrayToBase64(typedArray) {
const bytes = new Uint8Array(typedArray.buffer, typedArray.byteOffset, typedArray.byteLength);
// Build binary string in chunks to avoid excessive string concatenation
const chunkSize = 8192;
const parts = [];
for (let i = 0; i < bytes.length; i += chunkSize) {
const end = Math.min(i + chunkSize, bytes.length);
parts.push(String.fromCharCode(...bytes.subarray(i, end)));
}
return btoa(parts.join(""));
}
/**
* Convert a base64 string back to a TypedArray.
* @param {string} base64 base64-encoded string
* @param {function} TypedArrayConstructor constructor for the desired type (e.g., Uint8Array)
* @returns {ArrayBufferView} the decoded typed array
*/
export function base64ToTypedArray(base64, TypedArrayConstructor) {
const binary = atob(base64);
const bytes = new Uint8Array(binary.length);
for (let i = 0; i < binary.length; i++) {
bytes[i] = binary.charCodeAt(i);
}
// Create a properly aligned typed array from the raw bytes
const elementSize = TypedArrayConstructor.BYTES_PER_ELEMENT;
const length = bytes.length / elementSize;
if (!Number.isInteger(length)) {
throw new Error(
`Base64 data length (${bytes.length} bytes) is not a multiple of ${TypedArrayConstructor.name} element size (${elementSize})`,
);
}
const result = new TypedArrayConstructor(length);
new Uint8Array(result.buffer).set(bytes);
return result;
}
/**
* Deep copy a snapshot object, cloning any TypedArrays found within.
* This ensures rewind buffer snapshots are fully isolated from live state.
* @param {object} obj snapshot object to copy
* @returns {object} a deep copy with all TypedArrays cloned
*/
export function deepCopySnapshot(obj) {
if (obj === null || typeof obj !== "object") {
return obj;
}
if (ArrayBuffer.isView(obj)) {
return obj.slice();
}
if (Array.isArray(obj)) {
return obj.map((item) => deepCopySnapshot(item));
}
const copy = {};
for (const key of Object.keys(obj)) {
copy[key] = deepCopySnapshot(obj[key]);
}
return copy;
}
|