/** * @module node-opcua-address-space * * Where a NodeSet2 document comes from. The loader does not need a file system: it reads a * source as a sequence of chunks, text or UTF-8 bytes, and parses them as they arrive. A source * may hold the XML, or a precompiled image of it (see `nodeset_image.ts`), told apart by the * first bytes. */ /** one piece of a NodeSet2 document: text, or UTF-8 bytes */ export type NodesetChunk = string | Uint8Array; /** a document delivered in pieces: an async iterable (a Node.js Readable, a web ReadableStream, an async generator) or a plain iterable */ export type NodesetChunkStream = AsyncIterable | Iterable; /** * a NodeSet2 document, as one of: * * - the whole document as a string or as UTF-8 bytes; * - a stream of chunks; it is read once, from the start, so a stream that has already been * partly consumed cannot be used; * - a function opening such a stream, called once when the loader gets to it, so that a * list of files does not hold every descriptor open from the start; * - any of the above with a `name`, used in error messages, and optionally an `imageKey`. * * A byte-order mark at the start is dropped; a multi-byte character may straddle two chunks. * Decompression is the caller's business and needs no library support: * * ```ts * // Node.js * { name: file, source: () => fs.createReadStream(file).pipe(zlib.createGunzip()) } * // browser * { name: url, source: async function* () { yield* (await fetch(url)).body!.pipeThrough(new DecompressionStream("gzip")); } } * ``` * * An array given to `generateAddressSpaceRaw` is always a list of documents; chunks of one * document held in an array go through the named form: `{ name, source: chunks }`. * * A source may hold a precompiled image instead of the XML; it is recognized by its first * bytes and replayed, whether or not an image store is configured. */ export type NodesetSource = string | Uint8Array | NodesetChunkStream | (() => NodesetChunkStream) | NamedNodesetSource; export interface NamedNodesetSource { name: string; source: string | Uint8Array | NodesetChunkStream | (() => NodesetChunkStream); /** * the digest under which an image store holds this document's image. A document given * whole (a string, bytes) is hashed by the loader; a stream is read once, so its digest is * only known after it has been parsed, and the store is consulted for it only when the * caller names the key here (the loader logs the digest it computed, for a later run). */ imageKey?: string; } /** what a source turned out to hold */ export type NodesetSourceKind = "xml" | "image"; export interface NodesetReaderOptions { /** keep the bytes read so that {@link NodesetReader.digest} can be computed */ hash?: boolean; imageKey?: string; } /** * reads a source as text, once: the head first, as far as a predicate needs it, then the whole * document with the head included, so that a stream that cannot be reopened is never read twice * @internal */ export declare class NodesetReader { readonly name: string; private readonly open; /** true when the whole document is in memory: its digest can be computed before it is parsed */ readonly whole: boolean; private readonly options; private iterator; private exhausted; /** * the chunks read so far and not yet delivered to the body, in the form the document has: * text once decoded for XML, raw bytes for an image (the kind is fixed by the first chunk) */ private head; private bodyStarted; private decoder; private atStart; private kind; private readonly hashed; private bytesRead; private readonly encoder; private digestValue; constructor(name: string, open: () => NodesetChunkStream, /** true when the whole document is in memory: its digest can be computed before it is parsed */ whole: boolean, options?: NodesetReaderOptions); /** the key a caller named for this source, if any */ get imageKey(): string | undefined; /** XML or image: decided on the first bytes */ probe(): Promise; /** * read from the start until `complete(text)` holds or the source ends; what was read stays * in the reader and is delivered again, first, by {@link chunks} */ readHead(complete: (text: string) => boolean): Promise; /** the whole document as text chunks, from the start; usable once */ chunks(): AsyncGenerator; /** the whole document as raw bytes, from the start, for a source holding an image; usable once */ bytes(): AsyncGenerator; /** the whole document as one byte array; reads the source to its end and keeps it */ allBytes(): Promise; /** the bytes read so far; the whole document once it has been read */ get length(): number; /** * the SHA-256 of the bytes of the document, hex; available at any time for a document given * whole, once the body has been read to its end otherwise */ digest(): Promise; private startBody; /** the next non-empty chunk, kept in the head until the body starts; undefined at the end */ private pull; /** classify on the first chunk, hash, decode; returns the chunk in the form the document has, or undefined when empty */ private accept; } /** the SHA-256 of `bytes`, lower-case hex: the digest a nodeset image carries for its source */ export declare function sha256Hex(bytes: Uint8Array): Promise; /** * a reader over a source; `index` names an anonymous source in error messages * @internal */ export declare function openNodesetSource(source: NodesetSource, index: number, options?: { hash?: boolean; whole?: boolean; }): NodesetReader;