From 22509b5cbc78b3465ba187dd257466ea981de15d Mon Sep 17 00:00:00 2001 From: Asher Gomez Date: Wed, 25 Sep 2024 12:32:17 +1000 Subject: [PATCH] BREAKING(io/unstable): remove `readRange()` --- io/deno.json | 1 - io/mod.ts | 1 - io/read_range.ts | 127 ------------------------------ io/read_range_test.ts | 175 ------------------------------------------ 4 files changed, 304 deletions(-) delete mode 100644 io/read_range.ts delete mode 100644 io/read_range_test.ts diff --git a/io/deno.json b/io/deno.json index 99b897d3abec..4f5a91c3bfa1 100644 --- a/io/deno.json +++ b/io/deno.json @@ -16,7 +16,6 @@ "./read-int": "./read_int.ts", "./read-lines": "./read_lines.ts", "./read-long": "./read_long.ts", - "./read-range": "./read_range.ts", "./read-short": "./read_short.ts", "./read-string-delim": "./read_string_delim.ts", "./reader-from-stream-reader": "./reader_from_stream_reader.ts", diff --git a/io/mod.ts b/io/mod.ts index ff0d0214ad39..54b8e27699de 100644 --- a/io/mod.ts +++ b/io/mod.ts @@ -29,7 +29,6 @@ export * from "./read_delim.ts"; export * from "./read_int.ts"; export * from "./read_lines.ts"; export * from "./read_long.ts"; -export * from "./read_range.ts"; export * from "./read_short.ts"; export * from "./read_string_delim.ts"; export * from "./reader_from_stream_reader.ts"; diff --git a/io/read_range.ts b/io/read_range.ts deleted file mode 100644 index 9cea8c5e79b1..000000000000 --- a/io/read_range.ts +++ /dev/null @@ -1,127 +0,0 @@ -// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. - -import { copy as copyBytes } from "@std/bytes/copy"; -import type { Reader, ReaderSync, Seeker, SeekerSync } from "./types.ts"; - -const DEFAULT_BUFFER_SIZE = 32 * 1024; - -/** - * The range of bytes to read from a file or other resource that is readable. - * - * @deprecated This will be removed in 1.0.0. Use the {@link https://developer.mozilla.org/en-US/docs/Web/API/Streams_API | Web Streams API} instead. - */ -export interface ByteRange { - /** The 0 based index of the start byte for a range. */ - start: number; - - /** The 0 based index of the end byte for a range, which is inclusive. */ - end: number; -} - -/** - * Read a range of bytes from a file or other resource that is readable and - * seekable. The range start and end are inclusive of the bytes within that - * range. - * - * @example Usage - * ```ts ignore - * import { assertEquals } from "@std/assert"; - * import { readRange } from "@std/io/read-range"; - * - * // Read the first 10 bytes of a file - * const file = await Deno.open("example.txt", { read: true }); - * const bytes = await readRange(file, { start: 0, end: 9 }); - * assertEquals(bytes.length, 10); - * ``` - * - * @param r The reader to read from - * @param range The range of bytes to read - * @returns The bytes read - * - * @deprecated Use - * {@linkcode https://jsr.io/@std/streams/doc/byte-slice-stream/~/ByteSliceStream | ByteSliceStream} - * instead. This will be removed in 0.225.0. - */ -export async function readRange( - r: Reader & Seeker, - range: ByteRange, -): Promise { - // byte ranges are inclusive, so we have to add one to the end - let length = range.end - range.start + 1; - if (length <= 0) { - throw new RangeError("Byte range start cannot be larger than end"); - } - await r.seek(range.start, Deno.SeekMode.Start); - const result = new Uint8Array(length); - let off = 0; - while (length) { - const p = new Uint8Array(Math.min(length, DEFAULT_BUFFER_SIZE)); - const nread = await r.read(p); - if (nread === null) { - throw new Error("Unexpected EOF reach while reading a range"); - } - if (nread === 0) { - throw new Error("Unexpected read of 0 bytes while reading a range"); - } - copyBytes(p, result, off); - off += nread; - length -= nread; - if (length < 0) { - throw new Error("Unexpected length remaining after reading range"); - } - } - return result; -} - -/** - * Read a range of bytes synchronously from a file or other resource that is - * readable and seekable. The range start and end are inclusive of the bytes - * within that range. - * - * @example Usage - * ```ts ignore - * import { assertEquals } from "@std/assert"; - * import { readRangeSync } from "@std/io/read-range"; - * - * // Read the first 10 bytes of a file - * const file = Deno.openSync("example.txt", { read: true }); - * const bytes = readRangeSync(file, { start: 0, end: 9 }); - * assertEquals(bytes.length, 10); - * ``` - * - * @param r The reader to read from - * @param range The range of bytes to read - * @returns The bytes read - * - * @deprecated This will be removed in 1.0.0. Use the {@link https://developer.mozilla.org/en-US/docs/Web/API/Streams_API | Web Streams API} instead. - */ -export function readRangeSync( - r: ReaderSync & SeekerSync, - range: ByteRange, -): Uint8Array { - // byte ranges are inclusive, so we have to add one to the end - let length = range.end - range.start + 1; - if (length <= 0) { - throw new RangeError("Byte range start cannot be larger than end"); - } - r.seekSync(range.start, Deno.SeekMode.Start); - const result = new Uint8Array(length); - let off = 0; - while (length) { - const p = new Uint8Array(Math.min(length, DEFAULT_BUFFER_SIZE)); - const nread = r.readSync(p); - if (nread === null) { - throw new Error("Unexpected EOF reach while reading a range"); - } - if (nread === 0) { - throw new Error("Unexpected read of 0 bytes while reading a range"); - } - copyBytes(p, result, off); - off += nread; - length -= nread; - if (length < 0) { - throw new Error("Unexpected length remaining after reading range"); - } - } - return result; -} diff --git a/io/read_range_test.ts b/io/read_range_test.ts deleted file mode 100644 index 9cd5bafa2e22..000000000000 --- a/io/read_range_test.ts +++ /dev/null @@ -1,175 +0,0 @@ -// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. - -import { copy } from "@std/bytes/copy"; -import { assert, assertEquals, assertRejects, assertThrows } from "@std/assert"; -import { readRange, readRangeSync } from "./read_range.ts"; -import type { - Closer, - Reader, - ReaderSync, - Seeker, - SeekerSync, -} from "./types.ts"; - -// N controls how many iterations of certain checks are performed. -const N = 100; -let testBytes: Uint8Array | undefined; - -export function init() { - if (testBytes === undefined) { - testBytes = new Uint8Array(N); - for (let i = 0; i < N; i++) { - testBytes[i] = "a".charCodeAt(0) + (i % 26); - } - } -} - -class MockFile implements Seeker, SeekerSync, Reader, ReaderSync, Closer { - #buf: Uint8Array; - #closed = false; - #offset = 0; - - get closed() { - return this.#closed; - } - - constructor(buf: Uint8Array) { - this.#buf = buf; - } - - close() { - this.#closed = true; - } - - read(p: Uint8Array): Promise { - if (this.#offset >= this.#buf.length) { - return Promise.resolve(null); - } - const nread = Math.min(p.length, 16_384, this.#buf.length - this.#offset); - if (nread === 0) { - return Promise.resolve(0); - } - copy(this.#buf.subarray(this.#offset, this.#offset + nread), p); - this.#offset += nread; - return Promise.resolve(nread); - } - - readSync(p: Uint8Array): number | null { - if (this.#offset >= this.#buf.length) { - return null; - } - const nread = Math.min(p.length, 16_384, this.#buf.length - this.#offset); - if (nread === 0) { - return 0; - } - copy(this.#buf.subarray(this.#offset, this.#offset + nread), p); - this.#offset += nread; - return nread; - } - - seek(offset: number, whence: Deno.SeekMode): Promise { - assert(whence === Deno.SeekMode.Start); - if (offset >= this.#buf.length) { - return Promise.reject( - new RangeError("Attempted to seek past end of buffer"), - ); - } - this.#offset = offset; - return Promise.resolve(this.#offset); - } - - seekSync(offset: number, whence: Deno.SeekMode): number { - assert(whence === Deno.SeekMode.Start); - if (offset >= this.#buf.length) { - throw new RangeError("Attempted to seek past end of buffer"); - } - this.#offset = offset; - return this.#offset; - } -} - -Deno.test({ - name: "readRange", - async fn() { - init(); - assert(testBytes); - const file = new MockFile(testBytes); - const actual = await readRange(file, { start: 0, end: 9 }); - assertEquals(actual, testBytes.subarray(0, 10)); - }, -}); - -Deno.test({ - name: "readRange - invalid range", - async fn() { - init(); - assert(testBytes); - const file = new MockFile(testBytes); - await assertRejects( - async () => { - await readRange(file, { start: 100, end: 0 }); - }, - Error, - "Byte range start cannot be larger than end", - ); - }, -}); - -Deno.test({ - name: "readRange - read past EOF", - async fn() { - init(); - assert(testBytes); - const file = new MockFile(testBytes); - await assertRejects( - async () => { - await readRange(file, { start: 99, end: 100 }); - }, - Error, - "Unexpected EOF reach while reading a range", - ); - }, -}); - -Deno.test({ - name: "readRangeSync", - fn() { - init(); - assert(testBytes); - const file = new MockFile(testBytes); - const actual = readRangeSync(file, { start: 0, end: 9 }); - assertEquals(actual, testBytes.subarray(0, 10)); - }, -}); - -Deno.test({ - name: "readRangeSync - invalid range", - fn() { - init(); - assert(testBytes); - const file = new MockFile(testBytes); - assertThrows( - () => { - readRangeSync(file, { start: 100, end: 0 }); - }, - Error, - "Byte range start cannot be larger than end", - ); - }, -}); - -Deno.test({ - name: "readRangeSync - read past EOF", - fn() { - init(); - assert(testBytes); - const file = new MockFile(testBytes); - assertThrows( - () => { - readRangeSync(file, { start: 99, end: 100 }); - }, - Error, - "Unexpected EOF reach while reading a range", - ); - }, -});