mirror of
https://github.com/wukko/cobalt.git
synced 2025-05-29 13:00:12 +02:00
web/storage: add memory storage and init() function
This commit is contained in:
parent
be4e7e2d7d
commit
ce4ded64a2
15
web/src/lib/storage/index.ts
Normal file
15
web/src/lib/storage/index.ts
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
import type { AbstractStorage } from "./storage";
|
||||||
|
import { MemoryStorage } from "./memory";
|
||||||
|
import { OPFSStorage } from "./opfs";
|
||||||
|
|
||||||
|
export function init(expectedSize?: number): Promise<AbstractStorage> {
|
||||||
|
if (OPFSStorage.isAvailable()) {
|
||||||
|
return OPFSStorage.init();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (MemoryStorage.isAvailable()) {
|
||||||
|
return MemoryStorage.init(expectedSize || 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw "no storage method is available";
|
||||||
|
}
|
91
web/src/lib/storage/memory.ts
Normal file
91
web/src/lib/storage/memory.ts
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
import { AbstractStorage } from "./storage";
|
||||||
|
|
||||||
|
export class MemoryStorage extends AbstractStorage {
|
||||||
|
#chunkSize: number;
|
||||||
|
#actualSize: number = 0;
|
||||||
|
#chunks: Uint8Array[] = [];
|
||||||
|
|
||||||
|
constructor(chunkSize: number) {
|
||||||
|
super();
|
||||||
|
this.#chunkSize = chunkSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
static async init(expectedSize: number) {
|
||||||
|
const MB = 1024 * 1024;
|
||||||
|
const chunkSize = Math.min(512 * MB, expectedSize);
|
||||||
|
|
||||||
|
const storage = new this(chunkSize);
|
||||||
|
|
||||||
|
// since we expect the output file to be roughly the same size
|
||||||
|
// as inputs, preallocate its size for the output
|
||||||
|
for (
|
||||||
|
let toAllocate = expectedSize;
|
||||||
|
toAllocate > 0;
|
||||||
|
toAllocate -= chunkSize
|
||||||
|
) {
|
||||||
|
storage.#chunks.push(new Uint8Array(chunkSize));
|
||||||
|
}
|
||||||
|
|
||||||
|
return storage;
|
||||||
|
}
|
||||||
|
|
||||||
|
async res() {
|
||||||
|
// if we didn't need as much space as we allocated for some reason,
|
||||||
|
// shrink the buffers so that we don't inflate the file with zeroes
|
||||||
|
const outputView: Uint8Array[] = [];
|
||||||
|
|
||||||
|
for (let i = 0; i < this.#chunks.length; ++i) {
|
||||||
|
outputView.push(
|
||||||
|
this.#chunks[i].subarray(
|
||||||
|
0,
|
||||||
|
Math.min(this.#chunkSize, this.#actualSize),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
this.#actualSize -= this.#chunkSize;
|
||||||
|
if (this.#actualSize <= 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Blob(outputView);
|
||||||
|
}
|
||||||
|
|
||||||
|
#expand(size: number) {
|
||||||
|
while (size > this.#chunkSize * this.#chunks.length) {
|
||||||
|
this.#chunks.push(new Uint8Array(this.#chunkSize));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async write(data: Uint8Array | Int8Array, pos: number) {
|
||||||
|
const writeEnd = pos + data.length;
|
||||||
|
this.#expand(writeEnd);
|
||||||
|
|
||||||
|
const chunkIndex = pos / this.#chunkSize | 0;
|
||||||
|
const offset = pos - (this.#chunkSize * chunkIndex);
|
||||||
|
|
||||||
|
if (offset + data.length > this.#chunkSize) {
|
||||||
|
this.#chunks[chunkIndex].set(
|
||||||
|
data.subarray(0, this.#chunkSize - offset),
|
||||||
|
offset,
|
||||||
|
);
|
||||||
|
this.#chunks[chunkIndex + 1].set(
|
||||||
|
data.subarray(this.#chunkSize - offset),
|
||||||
|
0,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
this.#chunks[chunkIndex].set(data, offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.#actualSize = Math.max(writeEnd, this.#actualSize);
|
||||||
|
return data.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
async destroy() {
|
||||||
|
this.#chunks = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
static isAvailable() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,5 @@
|
|||||||
export abstract class AbstractStorage {
|
export abstract class AbstractStorage {
|
||||||
static init(): Promise<AbstractStorage> {
|
static init(_expected_size: number): Promise<AbstractStorage> {
|
||||||
throw "init() call on abstract implementation";
|
throw "init() call on abstract implementation";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user