signal-desktop/ts/services/backups/util/FileStream.ts

55 lines
1.3 KiB
TypeScript
Raw Normal View History

2024-09-03 10:18:15 -07:00
// Copyright 2024 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import { type FileHandle, open } from 'node:fs/promises';
import { Buffer } from 'node:buffer';
import { InputStream } from '@signalapp/libsignal-client/dist/io';
export class FileStream extends InputStream {
#file: FileHandle | undefined;
#position = 0;
#buffer = Buffer.alloc(16 * 1024);
#initPromise: Promise<unknown> | undefined;
2024-09-03 10:18:15 -07:00
constructor(private readonly filePath: string) {
super();
}
public async close(): Promise<void> {
await this.#initPromise;
await this.#file?.close();
2024-09-03 10:18:15 -07:00
}
async read(amount: number): Promise<Buffer> {
const file = await this.#lazyOpen();
if (this.#buffer.length < amount) {
this.#buffer = Buffer.alloc(amount);
2024-09-03 10:18:15 -07:00
}
const { bytesRead } = await file.read(
this.#buffer,
2024-09-03 10:18:15 -07:00
0,
amount,
this.#position
2024-09-03 10:18:15 -07:00
);
this.#position += bytesRead;
return this.#buffer.slice(0, bytesRead);
2024-09-03 10:18:15 -07:00
}
async skip(amount: number): Promise<void> {
this.#position += amount;
2024-09-03 10:18:15 -07:00
}
async #lazyOpen(): Promise<FileHandle> {
await this.#initPromise;
2024-09-03 10:18:15 -07:00
if (this.#file) {
return this.#file;
2024-09-03 10:18:15 -07:00
}
const filePromise = open(this.filePath);
this.#initPromise = filePromise;
this.#file = await filePromise;
return this.#file;
2024-09-03 10:18:15 -07:00
}
}