API reference

Every public class, method, and event in @codexo/exojs. Generated from source.

C

classContainerReader

@codexo/exojs / assets / stable

Reads assets out of a `.exoa` container, fetching only the blocks it needs. A container's data section is tiled by independently compressed blocks, and a block boundary always falls on an entry boundary. Reading an entry is therefore: find the blocks covering it, obtain each one, decode, slice. Where a block comes from - a byte range, a block store, or a buffer already held - changes the cost but not the result. Decoded blocks are held for the reader's lifetime, so entries sharing a block decode it once. That is the whole reason readEntries exists: reading entries one at a time through separate readers would decompress a shared block once per entry. A reader is not thread-safe across `await` boundaries in the sense of cancellation: pass a `signal` through `init` to abandon in-flight requests.

3
props
7
methods
0
events
Import
import { ContainerReader } from '@codexo/exojs'

Reads assets out of a `.exoa` container, fetching only the blocks it needs.

A container's data section is tiled by independently compressed blocks, and a block boundary always falls on an entry boundary. Reading an entry is therefore: find the blocks covering it, obtain each one, decode, slice. Where a block comes from - a byte range, a block store, or a buffer already held - changes the cost but not the result.

Decoded blocks are held for the reader's lifetime, so entries sharing a block decode it once. That is the whole reason readEntries exists: reading entries one at a time through separate readers would decompress a shared block once per entry.

A reader is not thread-safe across `await` boundaries in the sense of cancellation: pass a `signal` through `init` to abandon in-flight requests.

Methods7
Read several entries, in the order given. Every block the entries touch is obtained once, concurrently, and each entry is then sliced out of the decoded regions. An entry spanning two blocks is joined across them.
Read one entry's asset bytes. Prefer readEntries for several: entries commonly share a block, and reading them together is what keeps a shared block fetched and decoded once.
Read part of one entry - a video segment, a region of a large buffer - without the rest of it. This only avoids work for an entry stored uncompressed, which is what the writer's "keep the compression only if it shrinks" rule already decides for H.264, AAC, Opus and KTX2. A compressed entry still has its covering blocks decoded whole, because that is the unit the codec framing allows.
release(): void
Drop every decoded block. The reader stays usable and will decode again on the next read.
fromBuffer(buffer: ArrayBuffer, options: ContainerReaderOptionsHow a ContainerReader is opened.): ContainerReader
Open a container already held whole in memory - the single-request path.
open(url: string, options: ContainerReaderOptionsHow a ContainerReader is opened.): Promise<ContainerReader>
Open the container at url, reading its head and nothing else where the server allows it. Costs one request. A server that honours byte ranges leaves the reader able to fetch blocks individually; one that does not - or one that content-encodes its responses, where offsets could not be trusted - hands over the whole file, and the reader serves every later read from memory. Throws when the file cannot be fetched, or is not a container this build reads.
Properties3
The validated head: entries, blocks and where the data section begins.
byteLength: number
Byte length of the whole container file, however much of it this reader has actually read.
ranged: boolean
Whether reads cost only the bytes they need, rather than being served from a buffer already fetched whole.
Source