// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
// This module is browser compatible.

import type { Reader } from "./types.ts";

/**
 * Reads from `reader` but limits the amount of data returned to just `limit` bytes.
 * Each call to `read` updates `limit` to reflect the new amount remaining.
 * `read` returns `null` when `limit` <= `0` or
 * when the underlying `reader` returns `null`.
 *
 * @example Usage
 * ```ts
 * import { StringReader } from "@std/io/string-reader";
 * import { LimitedReader } from "@std/io/limited-reader";
 * import { readAll } from "@std/io/read-all";
 * import { assertEquals } from "@std/assert/equals";
 *
 * const r = new StringReader("hello world");
 * const lr = new LimitedReader(r, 5);
 * const res = await readAll(lr);
 *
 * assertEquals(new TextDecoder().decode(res), "hello");
 * ```
 *
 * @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 class LimitedReader implements Reader {
  /**
   * The reader to read from
   *
   * @example Usage
   * ```ts
   * import { StringReader } from "@std/io/string-reader";
   * import { LimitedReader } from "@std/io/limited-reader";
   * import { assertEquals } from "@std/assert/equals";
   *
   * const r = new StringReader("hello world");
   * const lr = new LimitedReader(r, 5);
   *
   * assertEquals(lr.reader, r);
   * ```
   */
  reader: Reader;
  /**
   * The number of bytes to limit the reader to
   *
   * @example Usage
   * ```ts
   * import { StringReader } from "@std/io/string-reader";
   * import { LimitedReader } from "@std/io/limited-reader";
   * import { assertEquals } from "@std/assert/equals";
   *
   * const r = new StringReader("hello world");
   * const lr = new LimitedReader(r, 5);
   *
   * assertEquals(lr.limit, 5);
   * ```
   */
  limit: number;

  /**
   * Construct a new instance.
   *
   * @param reader The reader to read from.
   * @param limit The number of bytes to limit the reader to.
   */
  constructor(reader: Reader, limit: number) {
    this.reader = reader;
    this.limit = limit;
  }

  /**
   * Reads data from the reader.
   *
   * @example Usage
   * ```ts
   * import { StringReader } from "@std/io/string-reader";
   * import { LimitedReader } from "@std/io/limited-reader";
   * import { assertEquals } from "@std/assert/equals";
   *
   * const r = new StringReader("hello world");
   * const lr = new LimitedReader(r, 5);
   *
   * const data = new Uint8Array(5);
   * const res = await lr.read(data);
   *
   * assertEquals(res, 5);
   * assertEquals(new TextDecoder().decode(data), "hello");
   * ```
   *
   * @param p The buffer to read data into.
   * @returns The number of bytes read.
   */
  async read(p: Uint8Array): Promise<number | null> {
    if (this.limit <= 0) {
      return null;
    }

    if (p.length > this.limit) {
      p = p.subarray(0, this.limit);
    }
    const n = await this.reader.read(p);
    if (n === null) {
      return null;
    }

    this.limit -= n;
    return n;
  }
}

// denoCacheMetadata={"headers":{"content-type":"text/typescript","access-control-expose-headers":"*","nel":"{\"report_to\":\"cf-nel\",\"success_fraction\":0.0,\"max_age\":604800}","date":"Tue, 28 Jul 2026 12:31:15 GMT","set-cookie":"__cf_bm=KaGi9fq3QCp6grODL_zA8spI6JvgD4LBo0xZgncd.Fg-1785241875.0332263-1.0.1.1-xZXyJDUdy0f5H0YGtj_xzDf1_s.7oV91jQo6.wrFw6Dpn2Y6EwFeBA89BcncdDL44PMBU33_vP0giXJ3ilX6IpQvzQSY.VlNQnVZdnW.MWKcpVRyjH_uL0xw_Mte0kZG; HttpOnly; SameSite=None; Secure; Path=/; Domain=jsr.io; Expires=Tue, 28 Jul 2026 13:01:15 GMT","x-robots-tag":"noindex","alt-svc":"h3=\":443\"; ma=86400","server":"cloudflare","cf-ray":"a223e656f8667db6-LAX","content-length":"3090","vary":"Origin","x-content-type-options":"nosniff","cross-origin-resource-policy":"cross-origin","report-to":"{\"group\":\"cf-nel\",\"max_age\":604800,\"endpoints\":[{\"url\":\"https://a.nel.cloudflare.com/report/v4?s=ENiTSX0yp0MKgSfk%2FwKEOsPM12Huan8iFYU7xTF4lidNYbCrHF1znFOU78BEaaV6Xp0HEixoHdpHIe6qtxf6M1XaH8kdCEpC89eYoIULPCclU9hyepwS4C0%3D\"}]}","cache-control":"public, max-age=31536000, immutable","x-jsr-backend":"modules","access-control-allow-origin":"*","etag":"\"55a245096ad3dbdf7dd360e3b6552f9a\"","content-security-policy":"default-src 'none'; script-src 'none'; style-src 'none'; img-src 'none'; font-src 'none'; connect-src 'none'; frame-src 'none'; object-src 'none'; frame-ancestors 'none'; sandbox; form-action 'none';"},"url":"https://jsr.io/@std/io/0.224.8/limited_reader.ts","time":1785241875}