diff options
Diffstat (limited to 'ext')
-rw-r--r-- | ext/node/lib.rs | 1 | ||||
-rw-r--r-- | ext/node/polyfills/_fs/_fs_readv.ts | 130 | ||||
-rw-r--r-- | ext/node/polyfills/fs.ts | 5 |
3 files changed, 136 insertions, 0 deletions
diff --git a/ext/node/lib.rs b/ext/node/lib.rs index cf63a5785..85abe49e4 100644 --- a/ext/node/lib.rs +++ b/ext/node/lib.rs @@ -371,6 +371,7 @@ deno_core::extension!(deno_node, "_fs/_fs_readdir.ts", "_fs/_fs_readFile.ts", "_fs/_fs_readlink.ts", + "_fs/_fs_readv.ts", "_fs/_fs_realpath.ts", "_fs/_fs_rename.ts", "_fs/_fs_rm.ts", diff --git a/ext/node/polyfills/_fs/_fs_readv.ts b/ext/node/polyfills/_fs/_fs_readv.ts new file mode 100644 index 000000000..7d87c51f7 --- /dev/null +++ b/ext/node/polyfills/_fs/_fs_readv.ts @@ -0,0 +1,130 @@ +// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. + +// TODO(petamoriken): enable prefer-primordials for node polyfills +// deno-lint-ignore-file prefer-primordials + +import { + ERR_INVALID_ARG_TYPE, + type ErrnoException, +} from "ext:deno_node/internal/errors.ts"; +import { + getValidatedFd, + validateBufferArray, +} from "ext:deno_node/internal/fs/utils.mjs"; +import { maybeCallback } from "ext:deno_node/_fs/_fs_common.ts"; +import { validateInteger } from "ext:deno_node/internal/validators.mjs"; +import * as io from "ext:deno_io/12_io.js"; +import * as fs from "ext:deno_fs/30_fs.js"; + +type Callback = ( + err: ErrnoException | null, + bytesRead: number, + buffers: readonly ArrayBufferView[], +) => void; + +export function readv( + fd: number, + buffers: readonly ArrayBufferView[], + callback: Callback, +): void; +export function readv( + fd: number, + buffers: readonly ArrayBufferView[], + position: number | Callback, + callback?: Callback, +): void { + if (typeof fd !== "number") { + throw new ERR_INVALID_ARG_TYPE("fd", "number", fd); + } + fd = getValidatedFd(fd); + validateBufferArray(buffers); + const cb = maybeCallback(callback || position) as Callback; + let pos: number | null = null; + if (typeof position === "number") { + validateInteger(position, "position", 0); + pos = position; + } + + if (buffers.length === 0) { + process.nextTick(cb, null, 0, buffers); + return; + } + + const innerReadv = async ( + fd: number, + buffers: readonly ArrayBufferView[], + position: number | null, + ) => { + if (typeof position === "number") { + await fs.seek(fd, position, io.SeekMode.Start); + } + + let readTotal = 0; + let readInBuf = 0; + let bufIdx = 0; + let buf = buffers[bufIdx]; + while (bufIdx < buffers.length) { + const nread = await io.read(fd, buf); + if (nread === null) { + break; + } + readInBuf += nread; + if (readInBuf === buf.byteLength) { + readTotal += readInBuf; + readInBuf = 0; + bufIdx += 1; + buf = buffers[bufIdx]; + } + } + readTotal += readInBuf; + + return readTotal; + }; + + innerReadv(fd, buffers, pos).then( + (numRead) => { + cb(null, numRead, buffers); + }, + (err) => cb(err, -1, buffers), + ); +} + +export function readvSync( + fd: number, + buffers: readonly ArrayBufferView[], + position: number | null = null, +): number { + if (typeof fd !== "number") { + throw new ERR_INVALID_ARG_TYPE("fd", "number", fd); + } + fd = getValidatedFd(fd); + validateBufferArray(buffers); + if (buffers.length === 0) { + return 0; + } + if (typeof position === "number") { + validateInteger(position, "position", 0); + fs.seekSync(fd, position, io.SeekMode.Start); + } + + let readTotal = 0; + let readInBuf = 0; + let bufIdx = 0; + let buf = buffers[bufIdx]; + while (bufIdx < buffers.length) { + const nread = io.readSync(fd, buf); + if (nread === null) { + break; + } + readInBuf += nread; + if (readInBuf === buf.byteLength) { + readTotal += readInBuf; + readInBuf = 0; + bufIdx += 1; + buf = buffers[bufIdx]; + } + } + readTotal += readInBuf; + + return readTotal; +} diff --git a/ext/node/polyfills/fs.ts b/ext/node/polyfills/fs.ts index bdf7e4aa6..f788f72b5 100644 --- a/ext/node/polyfills/fs.ts +++ b/ext/node/polyfills/fs.ts @@ -110,6 +110,7 @@ import { import { write, writeSync } from "ext:deno_node/_fs/_fs_write.mjs"; // @deno-types="./_fs/_fs_writev.d.ts" import { writev, writevSync } from "ext:deno_node/_fs/_fs_writev.mjs"; +import { readv, readvSync } from "ext:deno_node/_fs/_fs_readv.ts"; import { writeFile, writeFilePromise, @@ -250,6 +251,8 @@ export default { ReadStream, realpath, realpathSync, + readv, + readvSync, rename, renameSync, rmdir, @@ -353,6 +356,8 @@ export { readlinkSync, ReadStream, readSync, + readv, + readvSync, realpath, realpathSync, rename, |