Warning, /firebird/packages/root2dex/src/byte-range-source.ts is written in an unsupported language. File is not indexed.
0001 /**
0002 * A ROOT source built from nothing but "give me bytes [pos, pos+len)".
0003 *
0004 * `PodioEventFile` already handles local files and http(s) URLs directly. This
0005 * is the seam for everything else: an XRootD proxy endpoint, a service worker
0006 * cache, a test double that counts how much was read. Implement
0007 * `ByteRangeReader` and hand the result to `PodioEventFile.open` /
0008 * `Root2DexConverter.open`.
0009 *
0010 * Implement the optional `readRanges` when the transport can answer several
0011 * ranges in one round trip - JSROOT asks for all the baskets of one entry at
0012 * once, and a proxy that batches them turns an event into a single request.
0013 */
0014
0015 import { FileProxy } from 'jsroot/io';
0016 import type { RootSource } from './podio-file';
0017
0018 /** What a byte-range transport has to provide. */
0019 export interface ByteRangeReader {
0020 /** File name, used for messages and for JSROOT's file-name checks. */
0021 readonly name: string;
0022 /** Total size in bytes; JSROOT seeks relative to it. */
0023 readonly size: number;
0024 /** Reads one range. */
0025 readRange(position: number, length: number): Promise<ArrayBuffer | DataView>;
0026 /** Optional batched form: all ranges of one request in one round trip. */
0027 readRanges?(ranges: Array<[position: number, length: number]>): Promise<DataView[]>;
0028 close?(): void;
0029 }
0030
0031 function toDataView(data: ArrayBuffer | DataView): DataView {
0032 return data instanceof DataView ? data : new DataView(data);
0033 }
0034
0035 /**
0036 * Wraps a `ByteRangeReader` into the object JSROOT's `openFile` accepts.
0037 *
0038 * `FileProxy` is a JSROOT base class and `openFile` checks the instance type,
0039 * so the subclass is created here rather than declared at module scope.
0040 */
0041 export function createByteRangeSource(reader: ByteRangeReader): RootSource {
0042 class ReaderProxy extends FileProxy {
0043 async openFile(): Promise<boolean> {
0044 return true;
0045 }
0046 getFileName(): string {
0047 return reader.name;
0048 }
0049 getFileSize(): number {
0050 return reader.size;
0051 }
0052 async readBuffer(position: number, length: number): Promise<DataView> {
0053 return toDataView(await reader.readRange(position, length));
0054 }
0055 closeFile(): void {
0056 reader.close?.();
0057 }
0058 }
0059
0060 const proxy = new ReaderProxy() as ReaderProxy & {
0061 readBuffers?: (place: number[]) => Promise<DataView[]>;
0062 };
0063
0064 if (reader.readRanges) {
0065 // JSROOT passes places as a flat [pos, len, pos, len, ...] array
0066 proxy.readBuffers = async (place: number[]) => {
0067 const ranges: Array<[number, number]> = [];
0068 for (let i = 0; i < place.length; i += 2) ranges.push([place[i], place[i + 1]]);
0069 return reader.readRanges!(ranges);
0070 };
0071 }
0072
0073 return proxy;
0074 }