From 2a07e34edf20c6bc29fe1bb88827d0bace45bf57 Mon Sep 17 00:00:00 2001 From: streamich Date: Sun, 18 Jun 2023 19:45:17 +0200 Subject: [PATCH] =?UTF-8?q?feat:=20=F0=9F=8E=B8=20implement=20readFileSync?= =?UTF-8?q?()=20method?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- demo/fsa/main.ts | 1 + src/fsa-to-node/FsaNodeCore.ts | 2 +- src/fsa-to-node/FsaNodeFs.ts | 16 +++++++++++++++- src/fsa-to-node/FsaNodeFsOpenFile.ts | 1 + src/fsa-to-node/json.ts | 5 +++++ src/fsa-to-node/types.ts | 3 +++ .../worker/FsaNodeSyncAdapterWorker.ts | 6 +++--- src/fsa-to-node/worker/FsaNodeSyncWorker.ts | 13 +++++++++---- 8 files changed, 38 insertions(+), 9 deletions(-) create mode 100644 src/fsa-to-node/json.ts diff --git a/demo/fsa/main.ts b/demo/fsa/main.ts index 7e8e13fdc..8bccf6f41 100644 --- a/demo/fsa/main.ts +++ b/demo/fsa/main.ts @@ -17,6 +17,7 @@ const demo = async (dir: fsa.IFileSystemDirectoryHandle) => { // fs.accessSync('/test.txt', fs.constants.F_OK); console.log('/test.txt', fs.statSync('/test.txt'), fs.statSync('/test.txt').isFile(), fs.statSync('/test.txt').isDirectory()); console.log('/dir', fs.statSync('/dir'), fs.statSync('/dir').isFile(), fs.statSync('/dir').isDirectory()); + console.log('data', fs.readFileSync('/test.txt', 'utf8')); // await fs.promises.mkdir('storage/a/b/c', {recursive: true}); // await fs.promises.rm('storage/a/b', {recursive: true}); diff --git a/src/fsa-to-node/FsaNodeCore.ts b/src/fsa-to-node/FsaNodeCore.ts index 2393ac031..581bd671b 100644 --- a/src/fsa-to-node/FsaNodeCore.ts +++ b/src/fsa-to-node/FsaNodeCore.ts @@ -120,7 +120,7 @@ export class FsaNodeCore { const createIfMissing = !!(flags & FLAG.O_CREAT); const fsaFile = await this.getFile(folder, name, 'open', createIfMissing); const fd = this.newFdNumber(); - const file = new FsaNodeFsOpenFile(fd, mode, flags, fsaFile); + const file = new FsaNodeFsOpenFile(fd, mode, flags, fsaFile, filename); this.fds.set(fd, file); return file; } diff --git a/src/fsa-to-node/FsaNodeFs.ts b/src/fsa-to-node/FsaNodeFs.ts index 5ffe37c7e..f67b613f2 100644 --- a/src/fsa-to-node/FsaNodeFs.ts +++ b/src/fsa-to-node/FsaNodeFs.ts @@ -778,6 +778,21 @@ export class FsaNodeFs extends FsaNodeCore implements FsCallbackApi, FsSynchrono adapter.call('access', {filename, mode}); }; + public readonly readFileSync: FsSynchronousApi['readFileSync'] = (file: misc.TFileId, options?: opts.IReadFileOptions | string): misc.TDataOut => { + const opts = getReadFileOptions(options); + const flagsNum = flagsToNumber(opts.flag); + let filename: string = ''; + if (typeof file === 'number') { + const openFile = this.fds.get(file); + if (!openFile) throw createError('EBADF', 'readFile'); + filename = openFile.filename; + } else filename = pathToFilename(file); + const adapter = this.getSyncAdapter(); + const uint8 = adapter.call('readFile', {filename, opts}); + const buffer = Buffer.from(uint8.buffer, uint8.byteOffset, uint8.byteLength); + return bufferToEncoding(buffer, opts.encoding); + }; + public readonly appendFileSync: FsSynchronousApi['appendFileSync'] = notSupported; public readonly chmodSync: FsSynchronousApi['chmodSync'] = noop; public readonly chownSync: FsSynchronousApi['chownSync'] = noop; @@ -799,7 +814,6 @@ export class FsaNodeFs extends FsaNodeCore implements FsCallbackApi, FsSynchrono public readonly mkdtempSync: FsSynchronousApi['mkdtempSync'] = notSupported; public readonly openSync: FsSynchronousApi['openSync'] = notSupported; public readonly readdirSync: FsSynchronousApi['readdirSync'] = notSupported; - public readonly readFileSync: FsSynchronousApi['readFileSync'] = notSupported; public readonly readlinkSync: FsSynchronousApi['readlinkSync'] = notSupported; public readonly readSync: FsSynchronousApi['readSync'] = notSupported; public readonly realpathSync: FsSynchronousApi['realpathSync'] = notSupported; diff --git a/src/fsa-to-node/FsaNodeFsOpenFile.ts b/src/fsa-to-node/FsaNodeFsOpenFile.ts index f70b340cc..8503b6d82 100644 --- a/src/fsa-to-node/FsaNodeFsOpenFile.ts +++ b/src/fsa-to-node/FsaNodeFsOpenFile.ts @@ -22,6 +22,7 @@ export class FsaNodeFsOpenFile { public readonly createMode: misc.TMode, public readonly flags: number, public readonly file: fsa.IFileSystemFileHandle, + public readonly filename: string, ) { this.keepExistingData = !!(flags & FLAG.O_APPEND); } diff --git a/src/fsa-to-node/json.ts b/src/fsa-to-node/json.ts new file mode 100644 index 000000000..335b4167e --- /dev/null +++ b/src/fsa-to-node/json.ts @@ -0,0 +1,5 @@ +import {CborEncoder} from 'json-joy/es6/json-pack/cbor/CborEncoder'; +import {CborDecoder} from 'json-joy/es6/json-pack/cbor/CborDecoder'; + +export const encoder = new CborEncoder(); +export const decoder = new CborDecoder(); diff --git a/src/fsa-to-node/types.ts b/src/fsa-to-node/types.ts index d17f30a63..52ca0d7fe 100644 --- a/src/fsa-to-node/types.ts +++ b/src/fsa-to-node/types.ts @@ -1,3 +1,5 @@ +import type * as opts from '../node/types/options'; + export type FsLocation = [folder: string[], file: string]; /** @@ -6,6 +8,7 @@ export type FsLocation = [folder: string[], file: string]; export interface FsaNodeSyncAdapterApi { stat(location: FsLocation): FsaNodeSyncAdapterStats; access(req: {filename: string, mode: number}): void; + readFile(req: {filename: string, opts: opts.IReadFileOptions}): Uint8Array; } export interface FsaNodeSyncAdapter { diff --git a/src/fsa-to-node/worker/FsaNodeSyncAdapterWorker.ts b/src/fsa-to-node/worker/FsaNodeSyncAdapterWorker.ts index a5c476ca7..7c8c8c6f1 100644 --- a/src/fsa-to-node/worker/FsaNodeSyncAdapterWorker.ts +++ b/src/fsa-to-node/worker/FsaNodeSyncAdapterWorker.ts @@ -1,7 +1,7 @@ import { Defer } from 'thingies/es6/Defer'; import { FsaNodeWorkerMessageCode } from './constants'; -import { encode, decode } from 'json-joy/es6/json-pack/msgpack/util'; import { SyncMessenger } from './SyncMessenger'; +import {decoder, encoder} from '../json'; import type * as fsa from '../../fsa/types'; import type { FsaNodeSyncAdapter, FsaNodeSyncAdapterApi } from '../types'; import type { @@ -58,10 +58,10 @@ export class FsaNodeSyncAdapterWorker implements FsaNodeSyncAdapter { payload: Parameters[0], ): ReturnType { const request: FsaNodeWorkerMsgRequest = [FsaNodeWorkerMessageCode.Request, method, payload]; - const encoded = encode(request); + const encoded = encoder.encode(request); const encodedResponse = this.messenger.callSync(encoded); type MsgBack = FsaNodeWorkerMsgResponse | FsaNodeWorkerMsgResponseError; - const [code, data] = decode(encodedResponse as any); + const [code, data] = decoder.decode(encodedResponse) as MsgBack; switch (code) { case FsaNodeWorkerMessageCode.Response: return data as any; diff --git a/src/fsa-to-node/worker/FsaNodeSyncWorker.ts b/src/fsa-to-node/worker/FsaNodeSyncWorker.ts index 8f1ce7a73..e89eafcb8 100644 --- a/src/fsa-to-node/worker/FsaNodeSyncWorker.ts +++ b/src/fsa-to-node/worker/FsaNodeSyncWorker.ts @@ -1,7 +1,7 @@ import { AsyncCallback, SyncMessenger } from './SyncMessenger'; -import { encode, decode } from 'json-joy/es6/json-pack/msgpack/util'; import { FsaNodeWorkerMessageCode } from './constants'; import {FsaNodeFs} from '../FsaNodeFs'; +import {decoder, encoder} from '../json'; import type * as fsa from '../../fsa/types'; import type { FsaNodeWorkerError, @@ -44,7 +44,7 @@ export class FsaNodeSyncWorker { protected readonly onRequest: AsyncCallback = async (request: Uint8Array): Promise => { try { - const message = decode(request as any) as FsaNodeWorkerMsgRequest; + const message = decoder.decode(request as any) as FsaNodeWorkerMsgRequest; if (!Array.isArray(message)) throw new Error('Invalid message format'); const code = message[0]; if (code !== FsaNodeWorkerMessageCode.Request) throw new Error('Invalid message code'); @@ -52,12 +52,12 @@ export class FsaNodeSyncWorker { const handler = this.handlers[method]; if (!handler) throw new Error(`Unknown method ${method}`); const response = await handler(payload); - return encode([FsaNodeWorkerMessageCode.Response, response]); + return encoder.encode([FsaNodeWorkerMessageCode.Response, response]); } catch (err) { const message = err && typeof err === 'object' && err.message ? err.message : 'Unknown error'; const error: FsaNodeWorkerError = { message }; if (err && typeof err === 'object' && (err.code || err.name)) error.code = err.code || err.name; - return encode([FsaNodeWorkerMessageCode.ResponseError, error]); + return encoder.encode([FsaNodeWorkerMessageCode.ResponseError, error]); } }; @@ -124,5 +124,10 @@ export class FsaNodeSyncWorker { access: async ({filename, mode}): Promise => { await this.fs.promises.access(filename, mode); }, + readFile: async ({filename, opts}): Promise => { + const buf = await this.fs.promises.readFile(filename, {...opts, encoding: 'buffer'}) as Buffer; + const uint8 = new Uint8Array(buf, buf.byteOffset, buf.byteLength); + return uint8; + }, }; }