Skip to content

Commit

Permalink
feat: 🎸 implement readFileSync() method
Browse files Browse the repository at this point in the history
  • Loading branch information
streamich committed Jun 20, 2023
1 parent accebdb commit 2a07e34
Show file tree
Hide file tree
Showing 8 changed files with 38 additions and 9 deletions.
1 change: 1 addition & 0 deletions demo/fsa/main.ts
Expand Up @@ -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});

Expand Down
2 changes: 1 addition & 1 deletion src/fsa-to-node/FsaNodeCore.ts
Expand Up @@ -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;
}
Expand Down
16 changes: 15 additions & 1 deletion src/fsa-to-node/FsaNodeFs.ts
Expand Up @@ -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;
Expand All @@ -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;
Expand Down
1 change: 1 addition & 0 deletions src/fsa-to-node/FsaNodeFsOpenFile.ts
Expand Up @@ -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);
}
Expand Down
5 changes: 5 additions & 0 deletions 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();
3 changes: 3 additions & 0 deletions 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];

/**
Expand All @@ -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 {
Expand Down
6 changes: 3 additions & 3 deletions 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 {
Expand Down Expand Up @@ -58,10 +58,10 @@ export class FsaNodeSyncAdapterWorker implements FsaNodeSyncAdapter {
payload: Parameters<FsaNodeSyncAdapterApi[K]>[0],
): ReturnType<FsaNodeSyncAdapterApi[K]> {
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<MsgBack>(encodedResponse as any);
const [code, data] = decoder.decode(encodedResponse) as MsgBack;
switch (code) {
case FsaNodeWorkerMessageCode.Response:
return data as any;
Expand Down
13 changes: 9 additions & 4 deletions 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,
Expand Down Expand Up @@ -44,20 +44,20 @@ export class FsaNodeSyncWorker {

protected readonly onRequest: AsyncCallback = async (request: Uint8Array): Promise<Uint8Array> => {
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');
const [, method, payload] = message;
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]);
}
};

Expand Down Expand Up @@ -124,5 +124,10 @@ export class FsaNodeSyncWorker {
access: async ({filename, mode}): Promise<void> => {
await this.fs.promises.access(filename, mode);
},
readFile: async ({filename, opts}): Promise<Uint8Array> => {
const buf = await this.fs.promises.readFile(filename, {...opts, encoding: 'buffer'}) as Buffer;
const uint8 = new Uint8Array(buf, buf.byteOffset, buf.byteLength);
return uint8;
},
};
}

0 comments on commit 2a07e34

Please sign in to comment.