BREAKING(io): remove readRange[Sync]() (#6049)

BREAKING(io/unstable): remove `readRange()`
This commit is contained in:
Asher Gomez 2024-09-25 14:00:21 +10:00 committed by GitHub
parent eb064eba09
commit 3500797dcb
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 0 additions and 304 deletions

View File

@ -14,7 +14,6 @@
"./read-delim": "./read_delim.ts",
"./read-int": "./read_int.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",

View File

@ -27,7 +27,6 @@ export * from "./read_all.ts";
export * from "./read_delim.ts";
export * from "./read_int.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";

View File

@ -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<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");
}
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;
}

View File

@ -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<number | null> {
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<number> {
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",
);
},
});