Files
suaveplan/packages/networking/drive/drive-plugin-chunks/src/layout/chunk-keys.ts
2026-05-27 23:47:53 +01:00

50 lines
1.7 KiB
TypeScript

import type { DriveStorage } from "@suaveplan/drive";
import type { ChunkLayout } from "../types/chunks.types.js";
export function createChunkKeysLayout(storage: DriveStorage): ChunkLayout {
return {
name: "chunk-keys",
async putChunk(fileId, chunkId, rawBytes) {
const key = chunkKey(fileId, chunkId);
await storage.set(key, rawBytes);
},
async getChunk(fileId, chunkId) {
const key = chunkKey(fileId, chunkId);
return storage.get(key);
},
async hasChunks(fileId) {
const prefix = `chunks/${hex(fileId)}/`;
const result = await storage.list({ prefix });
const maxChunkId = result.keys.reduce(
(max: number, key: string) => {
const id = Number.parseInt(key.slice(prefix.length), 10);
return Math.max(max, id);
},
-1
);
const bits = new Array(maxChunkId + 1).fill(false);
for (const key of result.keys) {
const id = Number.parseInt(key.slice(prefix.length), 10);
bits[id] = true;
}
return bits;
},
async availableChunks(fileId) {
const bits = await this.hasChunks(fileId);
const ids: number[] = [];
for (let i = 0; i < bits.length; i++) {
if (bits[i]) ids.push(i);
}
return ids;
},
};
}
function chunkKey(fileId: Uint8Array, chunkId: number): string {
return `chunks/${hex(fileId)}/${chunkId}`;
}
function hex(bytes: Uint8Array): string {
return Array.from(bytes, (b) => b.toString(16).padStart(2, "0")).join("");
}