summaryrefslogtreecommitdiff
path: root/ext/node/polyfills/_fs/_fs_readv.ts
diff options
context:
space:
mode:
authorNathan Whitaker <17734409+nathanwhit@users.noreply.github.com>2024-04-01 20:42:49 -0700
committerGitHub <noreply@github.com>2024-04-01 20:42:49 -0700
commit7ad76fd453972e9262985c61840c77b8b8a6dbb7 (patch)
treea97eb0a22d7931ff9ac161f9be97e1faf1358547 /ext/node/polyfills/_fs/_fs_readv.ts
parentca5e5c7e9c8bb68beb751c25f2f08f18a59cd76e (diff)
fix(ext/node): Add fs.readv, fs.readvSync (#23166)
Part of #18218. Implements `fs.readv` and `fs.readvSync` and enables the corresponding `node_compat` tests.
Diffstat (limited to 'ext/node/polyfills/_fs/_fs_readv.ts')
-rw-r--r--ext/node/polyfills/_fs/_fs_readv.ts130
1 files changed, 130 insertions, 0 deletions
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;
+}