Skip to content

Commit

Permalink
feat: 🎸 implement writeSync() method
Browse files Browse the repository at this point in the history
  • Loading branch information
streamich committed Jun 20, 2023
1 parent 31383a8 commit 7a2fced
Show file tree
Hide file tree
Showing 7 changed files with 66 additions and 33 deletions.
7 changes: 7 additions & 0 deletions demo/fsa/main.ts
Expand Up @@ -92,6 +92,13 @@ const demo = async (dir: fsa.IFileSystemDirectoryHandle) => {
const bytesRead = fs.readSync(readHandle.fd, buf, 0, 3, 0);
strictEqual(bytesRead, 3);
strictEqual(buf.toString('utf8'), 'wor');

console.log('writeSync() - can write into an open file');
const writeHandle = await fs.promises.open('/cool.txt', 'a');
const bytesWritten = fs.writeSync(writeHandle.fd, Buffer.from('W'), 0, 1, 0);
await writeHandle.close();
strictEqual(bytesWritten, 1);
strictEqual(fs.readFileSync('/cool.txt', 'utf8'), 'Worlds!');
};

const main = async () => {
Expand Down
15 changes: 14 additions & 1 deletion src/fsa-to-node/FsaNodeFs.ts
Expand Up @@ -34,6 +34,7 @@ import {
validateCallback,
validateFd,
isFd,
getWriteSyncArgs,
} from '../node/util';
import { pathToLocation, testDirectoryIsWritable } from './util';
import { ERRSTR, MODE } from '../node/constants';
Expand Down Expand Up @@ -974,8 +975,20 @@ export class FsaNodeFs extends FsaNodeCore implements FsCallbackApi, FsSynchrono
return uint8.length;
};

public readonly writeSync: FsSynchronousApi['writeSync'] = (
fd: number,
a: string | Buffer | ArrayBufferView | DataView,
b?: number,
c?: number | BufferEncoding,
d?: number,
): number => {
const [, buf, offset, length, position] = getWriteSyncArgs(fd, a, b, c, d)
const filename = this.getFileName(fd);
const data = new Uint8Array(buf.buffer, buf.byteOffset + offset, length);
return this.getSyncAdapter().call('write', [filename, data, position || null]);
};

public readonly openSync: FsSynchronousApi['openSync'] = notSupported;
public readonly writeSync: FsSynchronousApi['writeSync'] = notSupported;

public readonly chmodSync: FsSynchronousApi['chmodSync'] = noop;
public readonly chownSync: FsSynchronousApi['chownSync'] = noop;
Expand Down
5 changes: 5 additions & 0 deletions src/fsa-to-node/types.ts
Expand Up @@ -26,6 +26,11 @@ export interface FsaNodeSyncAdapterApi {
position: number,
length: number,
]): Uint8Array;
write(req: [
filename: string,
data: Uint8Array,
position: number | null,
]): number;
}

export interface FsaNodeSyncAdapter {
Expand Down
5 changes: 5 additions & 0 deletions src/fsa-to-node/worker/FsaNodeSyncWorker.ts
Expand Up @@ -183,5 +183,10 @@ export class FsaNodeSyncWorker {
if (bytesRead < length) uint8 = uint8.slice(0, bytesRead);
return uint8;
},
write: async ([filename, data, position]): Promise<number> => {
const handle = await this.fs.promises.open(filename, 'a');
const {bytesWritten} = await handle.write(data, 0, data.length, position || undefined);
return bytesWritten;
},
};
}
4 changes: 0 additions & 4 deletions src/node/constants.ts
Expand Up @@ -34,10 +34,6 @@ const {
O_TRUNC,
O_APPEND,
O_SYNC,
O_DIRECTORY,
F_OK,
COPYFILE_EXCL,
COPYFILE_FICLONE_FORCE,
} = constants;

// List of file `flags` as defined by Node.
Expand Down
33 changes: 33 additions & 0 deletions src/node/util.ts
Expand Up @@ -244,6 +244,39 @@ export const getWriteArgs = (
return [fd, tipa === 'string', buf, offset, length!, position, cb];
};

export const getWriteSyncArgs = (
fd: number,
a: string | Buffer | ArrayBufferView | DataView,
b?: number,
c?: number | BufferEncoding,
d?: number,
): [fd: number, buf: Buffer, offset: number, length?: number, position?: number] => {
validateFd(fd);
let encoding: BufferEncoding | undefined;
let offset: number | undefined;
let length: number | undefined;
let position: number | undefined;
const isBuffer = typeof a !== 'string';
if (isBuffer) {
offset = (b || 0) | 0;
length = c as number;
position = d;
} else {
position = b;
encoding = c as BufferEncoding;
}
const buf: Buffer = dataToBuffer(a, encoding);
if (isBuffer) {
if (typeof length === 'undefined') {
length = buf.length;
}
} else {
offset = 0;
length = buf.length;
}
return [fd, buf, offset || 0, length, position];
};

export function bufferToEncoding(buffer: Buffer, encoding?: TEncodingExtended): misc.TDataOut {
if (!encoding || encoding === 'buffer') return buffer;
else return buffer.toString(encoding);
Expand Down
30 changes: 2 additions & 28 deletions src/volume.ts
Expand Up @@ -48,6 +48,7 @@ import {
dataToBuffer,
getWriteArgs,
bufferToEncoding,
getWriteSyncArgs,
} from './node/util';
import type { PathLike, symlink } from 'fs';
import { WritevCallback } from './node/types/callback';
Expand Down Expand Up @@ -907,34 +908,7 @@ export class Volume {
c?: number | BufferEncoding,
d?: number,
): number {
validateFd(fd);

let encoding: BufferEncoding | undefined;
let offset: number | undefined;
let length: number | undefined;
let position: number | undefined;

const isBuffer = typeof a !== 'string';
if (isBuffer) {
offset = (b || 0) | 0;
length = c as number;
position = d;
} else {
position = b;
encoding = c as BufferEncoding;
}

const buf: Buffer = dataToBuffer(a, encoding);

if (isBuffer) {
if (typeof length === 'undefined') {
length = buf.length;
}
} else {
offset = 0;
length = buf.length;
}

const [, buf, offset, length, position] = getWriteSyncArgs(fd, a, b, c, d)
return this.writeBase(fd, buf, offset, length, position);
}

Expand Down

0 comments on commit 7a2fced

Please sign in to comment.