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

/**
 * A transform stream that only transforms from the zero-indexed `start` and
 * `end` bytes (both inclusive).
 *
 * @example Basic usage
 * ```ts
 * import { ByteSliceStream } from "@std/streams/byte-slice-stream";
 * import { assertEquals } from "@std/assert/assert-equals";
 *
 * const stream = ReadableStream.from([
 *   new Uint8Array([0, 1]),
 *   new Uint8Array([2, 3, 4]),
 * ]);
 * const slicedStream = stream.pipeThrough(new ByteSliceStream(1, 3));
 *
 * assertEquals(
 *   await Array.fromAsync(slicedStream),
 *  [new Uint8Array([1]), new Uint8Array([2, 3])]
 * );
 * ```
 *
 * @example Get a range of bytes from a fetch response body
 * ```ts
 * import { ByteSliceStream } from "@std/streams/byte-slice-stream";
 * import { assertEquals } from "@std/assert/assert-equals";
 *
 * const response = await fetch("https://example.com");
 * const rangedStream = response.body!
 *   .pipeThrough(new ByteSliceStream(3, 8));
 * const collected = await Array.fromAsync(rangedStream);
 * assertEquals(collected[0]?.length, 6);
 * ```
 */
export class ByteSliceStream extends TransformStream<Uint8Array, Uint8Array> {
  #offsetStart = 0;
  #offsetEnd = 0;

  /**
   * Constructs a new instance.
   *
   * @param start The zero-indexed byte index to start reading from.
   * @param end The zero-indexed byte index to stop reading at. Inclusive.
   *
   * @example No parameters
   * ```ts no-assert
   * import { ByteSliceStream } from "@std/streams/byte-slice-stream";
   *
   * const byteSliceStream = new ByteSliceStream();
   * ```
   *
   * @example start = 4, end = 11
   * ```ts no-assert
   * import { ByteSliceStream } from "@std/streams/byte-slice-stream";
   *
   * const byteSliceStream = new ByteSliceStream(4, 11);
   * ```
   */
  constructor(start = 0, end: number = Infinity) {
    super({
      start: () => {
        if (start < 0) {
          throw new RangeError("`start` must be greater than 0");
        }
        end += 1;
      },
      transform: (chunk, controller) => {
        this.#offsetStart = this.#offsetEnd;
        this.#offsetEnd += chunk.byteLength;
        if (this.#offsetEnd > start) {
          if (this.#offsetStart < start) {
            chunk = chunk.slice(start - this.#offsetStart);
          }
          if (this.#offsetEnd >= end) {
            chunk = chunk.slice(0, chunk.byteLength - this.#offsetEnd + end);
            controller.enqueue(chunk);
            controller.terminate();
          } else {
            controller.enqueue(chunk);
          }
        }
      },
    });
  }
}

// denoCacheMetadata={"headers":{"cross-origin-resource-policy":"cross-origin","etag":"\"afc9b5dc3ca6e5e6194e8259ea665b67\"","access-control-expose-headers":"*","nel":"{\"report_to\":\"cf-nel\",\"success_fraction\":0.0,\"max_age\":604800}","alt-svc":"h3=\":443\"; ma=86400","x-robots-tag":"noindex","cf-ray":"a223e657caa27db6-LAX","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';","set-cookie":"__cf_bm=mymcRxQ501zhqfuA772j9DjrqaHpek.CNNA4Frfeg7o-1785241875.1750903-1.0.1.1-Tn6ta.9cmH3JmDWIx_unH.bgqwWNEotFj33dFlpuJ.0Csi.NToP6yH7iU8n..ymZFpODgzHGA9Uhj5sq48BsXQyuEjy28fU3MW_3m7A8Ud_w4bpiSYIzAUnKVh7kwmMC; HttpOnly; SameSite=None; Secure; Path=/; Domain=jsr.io; Expires=Tue, 28 Jul 2026 13:01:15 GMT","content-type":"text/typescript","vary":"Origin","content-length":"2656","cache-control":"public, max-age=31536000, immutable","date":"Tue, 28 Jul 2026 12:31:15 GMT","access-control-allow-origin":"*","x-content-type-options":"nosniff","x-jsr-backend":"modules","server":"cloudflare","report-to":"{\"group\":\"cf-nel\",\"max_age\":604800,\"endpoints\":[{\"url\":\"https://a.nel.cloudflare.com/report/v4?s=QbyaICHJhSSKdch4Ns9mh%2FoTmW6bbIMh1Vlu6LszWMFJmwOvHUctRHYvA1fm8YxTqxO7K3yfSxkWCdKWop4Wvb9ARXfwMG6u6BC8nUyvR%2BDaZdclkYV26UQ%3D\"}]}"},"url":"https://jsr.io/@std/streams/0.224.5/byte_slice_stream.ts","time":1785241875}