fix: fix master tag type

This commit is contained in:
master 2025-03-18 02:46:18 +08:00
parent 11fdb0f2fc
commit 9a5d025f40
24 changed files with 880 additions and 905 deletions

View File

@ -1,66 +1,55 @@
{ {
"$schema": "https://biomejs.dev/schemas/1.9.4/schema.json", "$schema": "https://biomejs.dev/schemas/1.9.4/schema.json",
"extends": [ "extends": ["ultracite"],
"ultracite" "linter": {
], "rules": {
"linter": { "style": {
"noNonNullAssertion": "off",
"noParameterAssign": "off",
"useFilenamingConvention": "off",
"noParameterProperties": "off",
"useImportType": {
"level": "error",
"fix": "unsafe"
}
},
"suspicious": {
"noExplicitAny": "off"
},
"complexity": {
"noForEach": "off"
},
"correctness": {
"noUnusedImports": {
"fix": "none",
"level": "warn"
}
},
"nursery": {
"noEnum": "off",
"useConsistentMemberAccessibility": "off"
}
}
},
"files": {
"ignore": [".vscode/*.json"]
},
"overrides": [
{
"include": ["tests/**"],
"javascript": {
"globals": ["describe", "beforeEach", "it", "expect"]
},
"linter": {
"rules": { "rules": {
"style": { "performance": {
"noNonNullAssertion": "off", "useTopLevelRegex": "off"
"noParameterAssign": "off", },
"useFilenamingConvention": "off", "suspicious": {
"noParameterProperties": "off", "noMisplacedAssertion": "off"
"useImportType": { }
"level": "error",
"fix": "unsafe"
}
},
"suspicious": {
"noExplicitAny": "off"
},
"complexity": {
"noForEach": "off"
},
"correctness": {
"noUnusedImports": {
"fix": "none",
"level": "warn"
}
},
"nursery": {
"noEnum": "off",
"useConsistentMemberAccessibility": "off"
}
} }
}, }
"files": { }
"ignore": [ ]
".vscode/*.json" }
]
},
"overrides": [
{
"include": [
"tests/**"
],
"javascript": {
"globals": [
"describe",
"beforeEach",
"it",
"expect"
]
},
"linter": {
"rules": {
"performance": {
"useTopLevelRegex": "off"
},
"suspicious": {
"noMisplacedAssertion": "off"
}
}
}
}
]
}

View File

@ -1,8 +1,8 @@
import fs from 'node:fs/promises'; import fs from 'node:fs/promises';
import { import {
ReadableStream, ReadableStream,
WritableStream,
type TransformStream, type TransformStream,
WritableStream,
} from 'node:stream/web'; } from 'node:stream/web';
import { EbmlStreamDecoder } from 'konoebml'; import { EbmlStreamDecoder } from 'konoebml';

View File

@ -1,6 +1,6 @@
{ {
"name": "konoebml", "name": "konoebml",
"version": "0.1.0-rc.4", "version": "0.1.0-rc.5",
"description": "A modern JavaScript implementation of EBML RFC8794", "description": "A modern JavaScript implementation of EBML RFC8794",
"main": "./dist/index.cjs", "main": "./dist/index.cjs",
"module": "./dist/index.js", "module": "./dist/index.js",
@ -20,8 +20,8 @@
"test": "vitest --coverage", "test": "vitest --coverage",
"test-ci": "vitest --watch=false --coverage", "test-ci": "vitest --watch=false --coverage",
"prepublishOnly": "npm run build", "prepublishOnly": "npm run build",
"lint": "ultracite lint", "lint": "biome lint",
"format": "ultracite format", "lint-fix": "biome lint --fix",
"playground": "tsx --tsconfig=./tsconfig.example.json ./examples/playground.ts" "playground": "tsx --tsconfig=./tsconfig.example.json ./examples/playground.ts"
}, },
"repository": "github:dumtruck/konoebml", "repository": "github:dumtruck/konoebml",

View File

@ -1,124 +1,124 @@
import { type EbmlTagIdType, isEbmlMasterTagId } from './models/enums'; import type { FileDataViewController } from './adapters';
import type { DecodeContentOptions, EbmlTagTrait } from './models/tag-trait'; import { UnreachableOrLogicError } from './errors';
import type { FileDataViewController } from './adapters'; import { createEbmlTag } from './factory';
import { import { type EbmlTagIdType, isEbmlMasterTagId } from './models/enums';
checkVintSafeSize, import { EbmlTagPosition } from './models/enums';
dataViewSlice, import type { DecodeContentOptions, EbmlTagTrait } from './models/tag-trait';
readUnsigned, import {
readVint, type SafeSizeVint,
readVintLength, checkVintSafeSize,
type SafeSizeVint, dataViewSlice,
} from './tools'; readUnsigned,
import { EbmlTagPosition } from './models/enums'; readVint,
import { createEbmlTag } from './factory'; readVintLength,
import { UnreachableOrLogicError } from './errors'; } from './tools';
export async function decodeEbmlTagHeader( export async function decodeEbmlTagHeader(
controller: FileDataViewController controller: FileDataViewController
): Promise<{ ): Promise<{
sizeVint: SafeSizeVint; sizeVint: SafeSizeVint;
tagVint: { length: number }; tagVint: { length: number };
tagId: EbmlTagIdType; tagId: EbmlTagIdType;
}> { }> {
const offset = controller.getOffset(); const offset = controller.getOffset();
let view = await controller.read(offset, 1); let view = await controller.read(offset, 1);
const tagVintLength = readVintLength(view); const tagVintLength = readVintLength(view);
view = view =
tagVintLength > view.byteLength tagVintLength > view.byteLength
? await controller.read(offset, tagVintLength) ? await controller.read(offset, tagVintLength)
: view; : view;
const tagIdView = dataViewSlice(view, 0, tagVintLength); const tagIdView = dataViewSlice(view, 0, tagVintLength);
view = view =
tagVintLength + 1 > view.byteLength tagVintLength + 1 > view.byteLength
? await controller.read(offset, tagVintLength + 1) ? await controller.read(offset, tagVintLength + 1)
: view; : view;
const sizeVintLength = readVintLength( const sizeVintLength = readVintLength(
dataViewSlice(view, tagVintLength, tagVintLength + 1) dataViewSlice(view, tagVintLength, tagVintLength + 1)
); );
view = view =
tagVintLength + sizeVintLength > view.byteLength tagVintLength + sizeVintLength > view.byteLength
? await controller.read(offset, tagVintLength + sizeVintLength) ? await controller.read(offset, tagVintLength + sizeVintLength)
: view; : view;
const sizeVint = readVint( const sizeVint = readVint(
dataViewSlice(view, tagVintLength, tagVintLength + sizeVintLength) dataViewSlice(view, tagVintLength, tagVintLength + sizeVintLength)
)!; )!;
if (!sizeVint) { if (!sizeVint) {
throw new UnreachableOrLogicError( throw new UnreachableOrLogicError(
'size vint dataView length is invalid, check code logic!' 'size vint dataView length is invalid, check code logic!'
); );
} }
const tagId = readUnsigned(tagIdView); const tagId = readUnsigned(tagIdView);
const safeSizeVint = checkVintSafeSize(sizeVint, tagId); const safeSizeVint = checkVintSafeSize(sizeVint, tagId);
return { return {
sizeVint: safeSizeVint, sizeVint: safeSizeVint,
tagVint: { tagVint: {
length: tagVintLength, length: tagVintLength,
}, },
tagId, tagId,
}; };
} }
export async function* decodeEbmlContent( export async function* decodeEbmlContent(
options: DecodeContentOptions options: DecodeContentOptions
): AsyncGenerator<EbmlTagTrait, void, unknown> { ): AsyncGenerator<EbmlTagTrait, void, unknown> {
const controller = options.dataViewController; const controller = options.dataViewController;
while (true) { while (true) {
const offset = controller.getOffset(); const offset = controller.getOffset();
const peeked = await controller.peek(offset); const peeked = await controller.peek(offset);
if (!peeked) { if (!peeked) {
break; break;
} }
const vints = await decodeEbmlTagHeader(controller); const vints = await decodeEbmlTagHeader(controller);
const { tagId, tagVint, sizeVint } = vints; const { tagId, tagVint, sizeVint } = vints;
const headerLength = tagVint.length + sizeVint.length; const headerLength = tagVint.length + sizeVint.length;
const contentLength = sizeVint.value; const contentLength = sizeVint.value;
const isMaster = isEbmlMasterTagId(tagId); const isMaster = isEbmlMasterTagId(tagId);
if (isMaster) { if (isMaster) {
const tag: EbmlTagTrait = createEbmlTag(tagId, { const tag: EbmlTagTrait = createEbmlTag(tagId, {
headerLength, headerLength,
contentLength, contentLength,
startOffset: offset, startOffset: offset,
position: EbmlTagPosition.Start, position: EbmlTagPosition.Start,
parent: undefined, parent: undefined,
}); });
yield tag; yield tag;
} }
await controller.seek(offset + headerLength); await controller.seek(offset + headerLength);
const tag: EbmlTagTrait = createEbmlTag(tagId, { const tag: EbmlTagTrait = createEbmlTag(tagId, {
headerLength, headerLength,
contentLength, contentLength,
startOffset: offset, startOffset: offset,
position: isMaster ? EbmlTagPosition.End : EbmlTagPosition.Content, position: isMaster ? EbmlTagPosition.End : EbmlTagPosition.Content,
parent: undefined, parent: undefined,
}); });
for await (const item of tag.decodeContent(options)) { for await (const item of tag.decodeContent(options)) {
yield item; yield item;
} }
tag.endOffset = controller.getOffset(); tag.endOffset = controller.getOffset();
yield tag; yield tag;
} }
} }

View File

@ -1,13 +1,13 @@
import { Queue } from 'mnemonist'; import { Queue } from 'mnemonist';
import type { FileDataViewController } from './adapters'; import type { FileDataViewController } from './adapters';
import { decodeEbmlContent } from './decode-utils';
import { StreamFlushReason, UnreachableOrLogicError } from './errors';
import type { EbmlTagType } from './models/tag';
import type { import type {
DecodeContentCollectChildPredicate, DecodeContentCollectChildPredicate,
EbmlTagTrait, EbmlTagTrait,
} from './models/tag-trait'; } from './models/tag-trait';
import { decodeEbmlContent } from './decode-utils';
import { StreamFlushReason, UnreachableOrLogicError } from './errors';
import { dataViewSlice } from './tools'; import { dataViewSlice } from './tools';
import type { EbmlTagType } from './models/tag';
export type EbmlStreamDecoderChunkType = export type EbmlStreamDecoderChunkType =
| Uint8Array | Uint8Array

View File

@ -1,9 +1,9 @@
import { Queue, Stack } from 'mnemonist'; import { Queue, Stack } from 'mnemonist';
import { EbmlTagTrait } from './models/tag-trait';
import { EbmlTagPosition } from './models/enums';
import { EbmlMasterTag } from './models/tag-master';
import { EbmlTreeMasterNotMatchError, UnreachableOrLogicError } from './errors'; import { EbmlTreeMasterNotMatchError, UnreachableOrLogicError } from './errors';
import { EbmlTagPosition } from './models/enums';
import type { EbmlTagType } from './models/tag'; import type { EbmlTagType } from './models/tag';
import { EbmlMasterTag } from './models/tag-master';
import { EbmlTagTrait } from './models/tag-trait';
export class EbmlEncodeStreamTransformer export class EbmlEncodeStreamTransformer
implements Transformer<EbmlTagTrait | EbmlTagType, Uint8Array> implements Transformer<EbmlTagTrait | EbmlTagType, Uint8Array>

View File

@ -1,21 +1,21 @@
import { InconsistentWellKnownEbmlTagTypeError } from './errors'; import { InconsistentWellKnownEbmlTagTypeError } from './errors';
import { import {
type EbmlMasterTagIdType,
type EbmlDataTagIdType,
type EbmlBlockTagIdType, type EbmlBlockTagIdType,
type EbmlSimpleBlockTagIdType, type EbmlDataTagIdType,
EbmlElementType, EbmlElementType,
type EbmlMasterTagIdType,
type EbmlSimpleBlockTagIdType,
EbmlTagIdEnum, EbmlTagIdEnum,
isEbmlBlockTagId,
isEbmlSimpleBlockTagId,
isEbmlMasterTagId,
isEbmlUintDataTagId,
isEbmlIntDataTagId,
isEbmlFloatDataTagId,
isEbmlStringDataTagId,
isEbmlUtf8DataTagId,
isEbmlDateDataTagId,
isEbmlBinaryDataTagId, isEbmlBinaryDataTagId,
isEbmlBlockTagId,
isEbmlDateDataTagId,
isEbmlFloatDataTagId,
isEbmlIntDataTagId,
isEbmlMasterTagId,
isEbmlSimpleBlockTagId,
isEbmlStringDataTagId,
isEbmlUintDataTagId,
isEbmlUtf8DataTagId,
} from './models/enums'; } from './models/enums';
import { import {
type CreateEbmlBlockTagOptions, type CreateEbmlBlockTagOptions,

View File

@ -1,124 +1,124 @@
import { type CreateEbmlDataTagOptions, EbmlDataTag } from './tag-data'; import {
import { EbmlBlockLacing } from './enums'; dataViewSlice,
import { dataViewSliceToBuf,
dataViewSlice, readSigned,
dataViewSliceToBuf, readVint,
readSigned, writeSigned,
readVint, writeVint,
writeSigned, } from '../tools';
writeVint, import { EbmlBlockLacing } from './enums';
} from '../tools'; import {
import { type EbmlBlockTagIdType,
type EbmlBlockTagIdType, type EbmlSimpleBlockTagIdType,
type EbmlSimpleBlockTagIdType, EbmlTagIdEnum,
EbmlTagIdEnum, } from './enums';
} from './enums'; import { EbmlElementType } from './enums';
import { EbmlElementType } from './enums'; import { type CreateEbmlDataTagOptions, EbmlDataTag } from './tag-data';
import type { DecodeContentOptions } from './tag-trait'; import type { DecodeContentOptions } from './tag-trait';
export interface CreateEbmlBlockTagOptions export interface CreateEbmlBlockTagOptions
extends Omit<CreateEbmlDataTagOptions, 'id' | 'type'> { extends Omit<CreateEbmlDataTagOptions, 'id' | 'type'> {
id?: EbmlBlockTagIdType | EbmlSimpleBlockTagIdType; id?: EbmlBlockTagIdType | EbmlSimpleBlockTagIdType;
} }
export class EbmlBlockTag extends EbmlDataTag { export class EbmlBlockTag extends EbmlDataTag {
payload = new Uint8Array(0); payload = new Uint8Array(0);
track: number | bigint = 0; track: number | bigint = 0;
value = 0; value = 0;
invisible: boolean | undefined; invisible: boolean | undefined;
lacing: EbmlBlockLacing | undefined; lacing: EbmlBlockLacing | undefined;
constructor(options: CreateEbmlBlockTagOptions) { constructor(options: CreateEbmlBlockTagOptions) {
super({ super({
...options, ...options,
id: options.id ?? EbmlTagIdEnum.Block, id: options.id ?? EbmlTagIdEnum.Block,
type: EbmlElementType.Binary, type: EbmlElementType.Binary,
}); });
} }
protected writeTrackBuffer(): Uint8Array { protected writeTrackBuffer(): Uint8Array {
return writeVint(this.track); return writeVint(this.track);
} }
protected writeValueBuffer(): Uint8Array { protected writeValueBuffer(): Uint8Array {
return writeSigned(this.value, 2); return writeSigned(this.value, 2);
} }
protected writeFlagsBuffer(): Uint8Array { protected writeFlagsBuffer(): Uint8Array {
let flags = 0x00; let flags = 0x00;
if (this.invisible) { if (this.invisible) {
flags |= 0x10; flags |= 0x10;
} }
switch (this.lacing) { switch (this.lacing) {
case EbmlBlockLacing.None: case EbmlBlockLacing.None:
break; break;
case EbmlBlockLacing.Xiph: case EbmlBlockLacing.Xiph:
flags |= 0x04; flags |= 0x04;
break; break;
case EbmlBlockLacing.EBML: case EbmlBlockLacing.EBML:
flags |= 0x08; flags |= 0x08;
break; break;
case EbmlBlockLacing.FixedSize: case EbmlBlockLacing.FixedSize:
flags |= 0x0c; flags |= 0x0c;
break; break;
default: default:
} }
return new Uint8Array([flags % 256]); return new Uint8Array([flags % 256]);
} }
*encodeContent(): Generator<Uint8Array, void, unknown> { *encodeContent(): Generator<Uint8Array, void, unknown> {
yield this.writeTrackBuffer(); yield this.writeTrackBuffer();
yield this.writeValueBuffer(); yield this.writeValueBuffer();
yield this.writeFlagsBuffer(); yield this.writeFlagsBuffer();
yield this.payload; yield this.payload;
} }
// biome-ignore lint/correctness/useYield: <explanation> // biome-ignore lint/correctness/useYield: <explanation>
async *decodeContentImpl(options: DecodeContentOptions) { async *decodeContentImpl(options: DecodeContentOptions) {
const controller = options.dataViewController; const controller = options.dataViewController;
const offset = controller.getOffset(); const offset = controller.getOffset();
const view = await controller.read(offset, this.contentLength, true); const view = await controller.read(offset, this.contentLength, true);
const track = readVint(view)!; const track = readVint(view)!;
this.track = track.value; this.track = track.value;
this.value = Number( this.value = Number(
readSigned(dataViewSlice(view, track.length, track.length + 2)) readSigned(dataViewSlice(view, track.length, track.length + 2))
); );
const flags: number = view.getUint8(track.length + 2); const flags: number = view.getUint8(track.length + 2);
this.invisible = Boolean(flags & 0x10); this.invisible = Boolean(flags & 0x10);
switch (flags & 0x0c) { switch (flags & 0x0c) {
case 0x00: case 0x00:
this.lacing = EbmlBlockLacing.None; this.lacing = EbmlBlockLacing.None;
break; break;
case 0x04: case 0x04:
this.lacing = EbmlBlockLacing.Xiph; this.lacing = EbmlBlockLacing.Xiph;
break; break;
case 0x08: case 0x08:
this.lacing = EbmlBlockLacing.EBML; this.lacing = EbmlBlockLacing.EBML;
break; break;
case 0x0c: case 0x0c:
this.lacing = EbmlBlockLacing.FixedSize; this.lacing = EbmlBlockLacing.FixedSize;
break; break;
default: default:
} }
this.payload = dataViewSliceToBuf(view, track.length + 3, undefined); this.payload = dataViewSliceToBuf(view, track.length + 3, undefined);
await controller.seek(offset + view.byteLength); await controller.seek(offset + view.byteLength);
} }
override toDebugRecord() { override toDebugRecord() {
const s = super.toDebugRecord(); const s = super.toDebugRecord();
return { return {
...s, ...s,
payload: this.payload, payload: this.payload,
track: this.track, track: this.track,
value: this.value, value: this.value,
invisible: this.invisible, invisible: this.invisible,
lacing: EbmlBlockLacing[this.lacing!] || this.lacing, lacing: EbmlBlockLacing[this.lacing!] || this.lacing,
}; };
} }
} }

View File

@ -1,95 +1,95 @@
import { import {
type CreateEbmlTagOptions, dataViewSliceToBuf,
type DecodeContentOptions, readAscii,
EbmlTagTrait, readFloat,
} from './tag-trait'; readSigned,
import { EbmlElementType } from './enums'; readUnsigned,
import { readUtf8,
dataViewSliceToBuf, writeAscii,
readAscii, writeFloat,
readFloat, writeSigned,
readSigned, writeUnsigned,
readUnsigned, writeUtf8,
readUtf8, } from '../tools';
writeAscii, import { EbmlElementType } from './enums';
writeFloat, import { EbmlTagPosition } from './enums';
writeSigned, import {
writeUnsigned, type CreateEbmlTagOptions,
writeUtf8, type DecodeContentOptions,
} from '../tools'; EbmlTagTrait,
import { EbmlTagPosition } from './enums'; } from './tag-trait';
export type CreateEbmlDataTagOptions = Omit<CreateEbmlTagOptions, 'position'>; export type CreateEbmlDataTagOptions = Omit<CreateEbmlTagOptions, 'position'>;
export class EbmlDataTag extends EbmlTagTrait { export class EbmlDataTag extends EbmlTagTrait {
data: number | string | bigint | null | Uint8Array | undefined; data: number | string | bigint | null | Uint8Array | undefined;
constructor(options: CreateEbmlDataTagOptions) { constructor(options: CreateEbmlDataTagOptions) {
super({ super({
...options, ...options,
position: EbmlTagPosition.Content, position: EbmlTagPosition.Content,
}); });
} }
// biome-ignore lint/correctness/useYield: <explanation> // biome-ignore lint/correctness/useYield: <explanation>
override async *decodeContentImpl(options: DecodeContentOptions) { override async *decodeContentImpl(options: DecodeContentOptions) {
const controller = options.dataViewController; const controller = options.dataViewController;
const offset = controller.getOffset(); const offset = controller.getOffset();
const view = await controller.read(offset, this.contentLength, true); const view = await controller.read(offset, this.contentLength, true);
switch (this.type) { switch (this.type) {
case EbmlElementType.UnsignedInt: case EbmlElementType.UnsignedInt:
this.data = readUnsigned(view); this.data = readUnsigned(view);
break; break;
case EbmlElementType.Float: case EbmlElementType.Float:
this.data = readFloat(view); this.data = readFloat(view);
break; break;
case EbmlElementType.Integer: case EbmlElementType.Integer:
this.data = readSigned(view); this.data = readSigned(view);
break; break;
case EbmlElementType.Ascii: case EbmlElementType.Ascii:
this.data = readAscii(view); this.data = readAscii(view);
break; break;
case EbmlElementType.UTF8: case EbmlElementType.UTF8:
this.data = readUtf8(view); this.data = readUtf8(view);
break; break;
default: default:
this.data = dataViewSliceToBuf(view, undefined, undefined); this.data = dataViewSliceToBuf(view, undefined, undefined);
break; break;
} }
await controller.seek(offset + view.byteLength); await controller.seek(offset + view.byteLength);
} }
*encodeContent(): Generator<Uint8Array, void, unknown> { *encodeContent(): Generator<Uint8Array, void, unknown> {
switch (this.type) { switch (this.type) {
case EbmlElementType.UnsignedInt: case EbmlElementType.UnsignedInt:
yield writeUnsigned(this.data as any); yield writeUnsigned(this.data as any);
break; break;
case EbmlElementType.Float: case EbmlElementType.Float:
yield writeFloat(this.data as any); yield writeFloat(this.data as any);
break; break;
case EbmlElementType.Integer: case EbmlElementType.Integer:
yield writeSigned(this.data as any); yield writeSigned(this.data as any);
break; break;
case EbmlElementType.Ascii: case EbmlElementType.Ascii:
yield writeAscii(this.data as any); yield writeAscii(this.data as any);
break; break;
case EbmlElementType.UTF8: case EbmlElementType.UTF8:
yield writeUtf8(this.data as any); yield writeUtf8(this.data as any);
break; break;
default: default:
yield this.data as Uint8Array; yield this.data as Uint8Array;
break; break;
} }
} }
override toDebugRecord() { override toDebugRecord() {
return { return {
...super.toDebugRecord(), ...super.toDebugRecord(),
data: this.data, data: this.data,
}; };
} }
toJSON() { toJSON() {
return JSON.stringify(this.toDebugRecord(), null, 2); return JSON.stringify(this.toDebugRecord(), null, 2);
} }
} }

View File

@ -1,107 +1,107 @@
import { import { createEbmlTag } from 'src/factory';
type CreateEbmlTagOptions, import { decodeEbmlTagHeader } from '../decode-utils';
type DecodeContentOptions, import { EbmlElementType, EbmlTagPosition, isEbmlMasterTagId } from './enums';
EbmlTagTrait, import type { EbmlMasterTagIdType } from './enums';
} from './tag-trait'; import {
import { EbmlElementType, EbmlTagPosition, isEbmlMasterTagId } from './enums'; type CreateEbmlTagOptions,
import { decodeEbmlTagHeader } from '../decode-utils'; type DecodeContentOptions,
import { createEbmlTag } from 'src/factory'; EbmlTagTrait,
import type { EbmlMasterTagIdType } from './enums'; } from './tag-trait';
export interface CreateEbmlMasterTagOptions export interface CreateEbmlMasterTagOptions
extends Omit<CreateEbmlTagOptions, 'position' | 'type' | 'id'> { extends Omit<CreateEbmlTagOptions, 'position' | 'type' | 'id'> {
id: EbmlMasterTagIdType; id: EbmlMasterTagIdType;
} }
export class EbmlMasterTag extends EbmlTagTrait { export class EbmlMasterTag extends EbmlTagTrait {
private _children: EbmlTagTrait[] = []; private _children: EbmlTagTrait[] = [];
get children(): EbmlTagTrait[] { get children(): EbmlTagTrait[] {
return this._children; return this._children;
} }
set children(value: EbmlTagTrait[]) { set children(value: EbmlTagTrait[]) {
this._children = value; this._children = value;
} }
constructor(options: CreateEbmlMasterTagOptions) { constructor(options: CreateEbmlMasterTagOptions) {
super({ super({
...options, ...options,
id: options.id, id: options.id,
type: EbmlElementType.Master, type: EbmlElementType.Master,
}); });
} }
*encodeContent(): Generator<Uint8Array, void, unknown> { *encodeContent(): Generator<Uint8Array, void, unknown> {
for (const child of this.children) { for (const child of this.children) {
yield* child.encode(); yield* child.encode();
} }
} }
async *decodeContentImpl(options: DecodeContentOptions) { async *decodeContentImpl(options: DecodeContentOptions) {
const controller = options.dataViewController; const controller = options.dataViewController;
const collectChild = options.collectChild; const collectChild = options.collectChild;
while (true) { while (true) {
const offset = controller.getOffset(); const offset = controller.getOffset();
if (offset >= this.endOffset) { if (offset >= this.endOffset) {
break; break;
} }
const peeked = await controller.peek(offset); const peeked = await controller.peek(offset);
if (!peeked) { if (!peeked) {
break; break;
} }
const vints = await decodeEbmlTagHeader(controller); const vints = await decodeEbmlTagHeader(controller);
const { tagId, tagVint, sizeVint } = vints; const { tagId, tagVint, sizeVint } = vints;
const headerLength = tagVint.length + sizeVint.length; const headerLength = tagVint.length + sizeVint.length;
const contentLength = sizeVint.value; const contentLength = sizeVint.value;
const isMaster = isEbmlMasterTagId(tagId); const isMaster = isEbmlMasterTagId(tagId);
if (isMaster) { if (isMaster) {
const tag: EbmlTagTrait = createEbmlTag(tagId, { const tag: EbmlTagTrait = createEbmlTag(tagId, {
headerLength, headerLength,
contentLength, contentLength,
startOffset: offset, startOffset: offset,
position: EbmlTagPosition.Start, position: EbmlTagPosition.Start,
parent: this, parent: this,
}); });
yield tag; yield tag;
} }
await controller.seek(offset + headerLength); await controller.seek(offset + headerLength);
const tag: EbmlTagTrait = createEbmlTag(tagId, { const tag: EbmlTagTrait = createEbmlTag(tagId, {
headerLength, headerLength,
contentLength, contentLength,
startOffset: offset, startOffset: offset,
position: isMaster ? EbmlTagPosition.End : EbmlTagPosition.Content, position: isMaster ? EbmlTagPosition.End : EbmlTagPosition.Content,
parent: this, parent: this,
}); });
for await (const item of tag.decodeContent(options)) { for await (const item of tag.decodeContent(options)) {
yield item; yield item;
} }
tag.endOffset = controller.getOffset(); tag.endOffset = controller.getOffset();
let shouldCollectChild: boolean; let shouldCollectChild: boolean;
if (typeof collectChild === 'function') { if (typeof collectChild === 'function') {
shouldCollectChild = !!collectChild(tag, this); shouldCollectChild = !!collectChild(tag, this);
} else { } else {
shouldCollectChild = !!collectChild; shouldCollectChild = !!collectChild;
} }
if (shouldCollectChild) { if (shouldCollectChild) {
this._children.push(tag); this._children.push(tag);
} }
yield tag; yield tag;
} }
} }
} }

View File

@ -1,55 +1,55 @@
import { readVint } from '../tools'; import { readVint } from '../tools';
import { type CreateEbmlBlockTagOptions, EbmlBlockTag } from './tag-block'; import type { EbmlSimpleBlockTagIdType } from './enums';
import type { EbmlSimpleBlockTagIdType } from './enums'; import { type CreateEbmlBlockTagOptions, EbmlBlockTag } from './tag-block';
import type { DecodeContentOptions } from './tag-trait'; import type { DecodeContentOptions } from './tag-trait';
export interface CreateEbmlSimpleBlockTagOptions export interface CreateEbmlSimpleBlockTagOptions
extends Omit<CreateEbmlBlockTagOptions, 'id'> { extends Omit<CreateEbmlBlockTagOptions, 'id'> {
id?: EbmlSimpleBlockTagIdType; id?: EbmlSimpleBlockTagIdType;
} }
export class EbmlSimpleBlockTag extends EbmlBlockTag { export class EbmlSimpleBlockTag extends EbmlBlockTag {
discardable: boolean | undefined; discardable: boolean | undefined;
keyframe: boolean | undefined; keyframe: boolean | undefined;
// biome-ignore lint/complexity/noUselessConstructor: <explanation> // biome-ignore lint/complexity/noUselessConstructor: <explanation>
constructor(options: CreateEbmlSimpleBlockTagOptions) { constructor(options: CreateEbmlSimpleBlockTagOptions) {
super(options); super(options);
} }
*encodeContent(): Generator<Uint8Array, void, unknown> { *encodeContent(): Generator<Uint8Array, void, unknown> {
const flags = this.writeFlagsBuffer(); const flags = this.writeFlagsBuffer();
if (this.keyframe) { if (this.keyframe) {
flags[0] |= 0x80; flags[0] |= 0x80;
} }
if (this.discardable) { if (this.discardable) {
flags[0] |= 0x01; flags[0] |= 0x01;
} }
yield this.writeTrackBuffer(); yield this.writeTrackBuffer();
yield this.writeValueBuffer(); yield this.writeValueBuffer();
yield flags; yield flags;
yield this.payload; yield this.payload;
} }
async *decodeContentImpl(options: DecodeContentOptions) { async *decodeContentImpl(options: DecodeContentOptions) {
const controller = options.dataViewController; const controller = options.dataViewController;
const offset = controller.getOffset(); const offset = controller.getOffset();
const view = await controller.read(offset, this.contentLength, true); const view = await controller.read(offset, this.contentLength, true);
for await (const item of super.decodeContentImpl(options)) { for await (const item of super.decodeContentImpl(options)) {
yield item; yield item;
} }
const trackVint = readVint(view)!; const trackVint = readVint(view)!;
const flags: number = view.getUint8(trackVint.length + 2); const flags: number = view.getUint8(trackVint.length + 2);
this.keyframe = Boolean(flags & 0x80); this.keyframe = Boolean(flags & 0x80);
this.discardable = Boolean(flags & 0x01); this.discardable = Boolean(flags & 0x01);
// seeked by block tag // seeked by block tag
// await controller.seek(offset + this.contentLength); // await controller.seek(offset + this.contentLength);
} }
} }

View File

@ -1,213 +1,213 @@
import { EbmlTagPosition } from './enums'; import type { FileDataViewController } from '../adapters';
import { EbmlTagIdEnum, type EbmlTagIdType } from './enums'; import { InconsistentOffsetOnDecodingContentError } from '../errors';
import type { EbmlElementType } from './enums'; import { UNKNOWN_SIZE_VINT_BUF, hexStringToBuf, writeVint } from '../tools';
import { hexStringToBuf, UNKNOWN_SIZE_VINT_BUF, writeVint } from '../tools'; import { EbmlTagPosition } from './enums';
import type { FileDataViewController } from '../adapters'; import { EbmlTagIdEnum, type EbmlTagIdType } from './enums';
import { InconsistentOffsetOnDecodingContentError } from '../errors'; import type { EbmlElementType } from './enums';
import type { EbmlMasterTag } from './tag-master'; import type { EbmlMasterTag } from './tag-master';
export interface CreateEbmlTagOptions { export interface CreateEbmlTagOptions {
id: EbmlTagIdType; id: EbmlTagIdType;
type?: EbmlElementType; type?: EbmlElementType;
position?: EbmlTagPosition; position?: EbmlTagPosition;
headerLength: number; headerLength: number;
contentLength: number; contentLength: number;
startOffset: number; startOffset: number;
endOffset?: number; endOffset?: number;
parent?: EbmlMasterTag; parent?: EbmlMasterTag;
} }
export type DecodeContentCollectChildPredicate = export type DecodeContentCollectChildPredicate =
| boolean | boolean
| ((child: EbmlTagTrait, parent: EbmlMasterTag) => boolean); | ((child: EbmlTagTrait, parent: EbmlMasterTag) => boolean);
export interface DecodeContentOptions { export interface DecodeContentOptions {
collectChild?: DecodeContentCollectChildPredicate; collectChild?: DecodeContentCollectChildPredicate;
dataViewController: FileDataViewController; dataViewController: FileDataViewController;
} }
export abstract class EbmlTagTrait { export abstract class EbmlTagTrait {
/** /**
* The id of the EBML tag. * The id of the EBML tag.
* In most documentation this number is in hexadecimal format * In most documentation this number is in hexadecimal format
*/ */
id: EbmlTagIdType; id: EbmlTagIdType;
/** /**
* The data type of the EBML tag * The data type of the EBML tag
*/ */
type?: EbmlElementType; type?: EbmlElementType;
/** /**
* The position of this EBML tag. * The position of this EBML tag.
* Currently, one of "Start", "Content", or "End". * Currently, one of "Start", "Content", or "End".
* "Start" and "End" only for Master type * "Start" and "End" only for Master type
*/ */
position: EbmlTagPosition; position: EbmlTagPosition;
/** /**
* Size vint length + tag vint length * Size vint length + tag vint length
*/ */
headerLength: number; headerLength: number;
/** /**
* Start offset relative to context (stream or file) start * Start offset relative to context (stream or file) start
*/ */
startOffset: number; startOffset: number;
/** /**
* Parent node * Parent node
*/ */
parent?: EbmlTagTrait; parent?: EbmlTagTrait;
/** /**
* Content length in ebml data * Content length in ebml data
* Return Number.POSITIVE_INFINITY as "unknown" * Return Number.POSITIVE_INFINITY as "unknown"
*/ */
private _contentLength: number; private _contentLength: number;
/** /**
* Caculated end offset when * Caculated end offset when
*/ */
private _endOffset?: number; private _endOffset?: number;
constructor(options: CreateEbmlTagOptions) { constructor(options: CreateEbmlTagOptions) {
this.id = options.id; this.id = options.id;
this.type = options.type; this.type = options.type;
this.position = options.position ?? EbmlTagPosition.Content; this.position = options.position ?? EbmlTagPosition.Content;
this.parent = options.parent; this.parent = options.parent;
this.startOffset = options.startOffset; this.startOffset = options.startOffset;
this.headerLength = options.headerLength; this.headerLength = options.headerLength;
this._contentLength = options.contentLength; this._contentLength = options.contentLength;
this._endOffset = options.endOffset; this._endOffset = options.endOffset;
} }
public set contentLength(value: number) { public set contentLength(value: number) {
this._contentLength = value; this._contentLength = value;
} }
/** /**
* After caculated or known, manually set endOffset * After caculated or known, manually set endOffset
*/ */
public set endOffset(offset: number) { public set endOffset(offset: number) {
this._endOffset = offset; this._endOffset = offset;
} }
/** /**
* End offset relative to context (stream or file) start * End offset relative to context (stream or file) start
* Calcalate from self _contentLength and parent end offset * Calcalate from self _contentLength and parent end offset
* Return Number.POSITIVE_INFINITY as "unknown" * Return Number.POSITIVE_INFINITY as "unknown"
*/ */
public get endOffset(): number { public get endOffset(): number {
if (this._endOffset) { if (this._endOffset) {
return this._endOffset; return this._endOffset;
} }
if (this._contentLength === Number.POSITIVE_INFINITY) { if (this._contentLength === Number.POSITIVE_INFINITY) {
return this.parent?.endOffset ?? Number.POSITIVE_INFINITY; return this.parent?.endOffset ?? Number.POSITIVE_INFINITY;
} }
return this.startOffset + this.headerLength + this._contentLength; return this.startOffset + this.headerLength + this._contentLength;
} }
/** /**
* Header length + Content Length * Header length + Content Length
* Calcalate from self _contentLength and parent end offset * Calcalate from self _contentLength and parent end offset
* Return Number.POSITIVE_INFINITY as "unknown" * Return Number.POSITIVE_INFINITY as "unknown"
*/ */
public get totalLength(): number { public get totalLength(): number {
return this.endOffset - this.startOffset; return this.endOffset - this.startOffset;
} }
/** /**
* Content Length * Content Length
* Calcalate from self _contentLength and parent end offset * Calcalate from self _contentLength and parent end offset
* Return Number.POSITIVE_INFINITY as "unknown" * Return Number.POSITIVE_INFINITY as "unknown"
*/ */
public get contentLength(): number { public get contentLength(): number {
return this.totalLength - this.headerLength; return this.totalLength - this.headerLength;
} }
protected abstract encodeContent(): Generator<Uint8Array, void, unknown>; protected abstract encodeContent(): Generator<Uint8Array, void, unknown>;
/** /**
* Deep traversal and parse all descendants then yield as AsyncGenerator * Deep traversal and parse all descendants then yield as AsyncGenerator
* @param controller DataView controller, simulate async filesystem file * @param controller DataView controller, simulate async filesystem file
*/ */
protected abstract decodeContentImpl( protected abstract decodeContentImpl(
options: DecodeContentOptions options: DecodeContentOptions
): AsyncGenerator<EbmlTagTrait, void, unknown>; ): AsyncGenerator<EbmlTagTrait, void, unknown>;
/** /**
* Wrap of abstract decode content impl function, add before and after lifecircle check * Wrap of abstract decode content impl function, add before and after lifecircle check
* @param controller DataView controller, simulate async filesystem file * @param controller DataView controller, simulate async filesystem file
* @returns Deep traversal async iterators of all descendants * @returns Deep traversal async iterators of all descendants
*/ */
public async *decodeContent( public async *decodeContent(
options: DecodeContentOptions options: DecodeContentOptions
): AsyncGenerator<EbmlTagTrait, void, unknown> { ): AsyncGenerator<EbmlTagTrait, void, unknown> {
const controller = options.dataViewController; const controller = options.dataViewController;
if (this.contentLength === 0 || this.position === EbmlTagPosition.Start) { if (this.contentLength === 0 || this.position === EbmlTagPosition.Start) {
return; return;
} }
const startOffset = controller.getOffset(); const startOffset = controller.getOffset();
for await (const tag of this.decodeContentImpl(options)) { for await (const tag of this.decodeContentImpl(options)) {
yield tag; yield tag;
} }
const endOffset = controller.getOffset(); const endOffset = controller.getOffset();
if ( if (
startOffset + this.contentLength !== endOffset && startOffset + this.contentLength !== endOffset &&
this.contentLength !== Number.POSITIVE_INFINITY this.contentLength !== Number.POSITIVE_INFINITY
) { ) {
throw new InconsistentOffsetOnDecodingContentError(this, endOffset); throw new InconsistentOffsetOnDecodingContentError(this, endOffset);
} }
} }
private getTagDeclaration(): Uint8Array { private getTagDeclaration(): Uint8Array {
let tagHex = this.id.toString(16); let tagHex = this.id.toString(16);
if (tagHex.length % 2 !== 0) { if (tagHex.length % 2 !== 0) {
tagHex = `0${tagHex}`; tagHex = `0${tagHex}`;
} }
return hexStringToBuf(tagHex); return hexStringToBuf(tagHex);
} }
public *encodeHeader(): Generator<Uint8Array, void, unknown> { public *encodeHeader(): Generator<Uint8Array, void, unknown> {
const tagEncoded = this.getTagDeclaration(); const tagEncoded = this.getTagDeclaration();
yield tagEncoded; yield tagEncoded;
if (this._contentLength === Number.POSITIVE_INFINITY) { if (this._contentLength === Number.POSITIVE_INFINITY) {
const mayBeSizeLength = this.headerLength - tagEncoded.byteLength; const mayBeSizeLength = this.headerLength - tagEncoded.byteLength;
if (mayBeSizeLength > 0 && mayBeSizeLength <= 8) { if (mayBeSizeLength > 0 && mayBeSizeLength <= 8) {
yield UNKNOWN_SIZE_VINT_BUF[mayBeSizeLength]; yield UNKNOWN_SIZE_VINT_BUF[mayBeSizeLength];
} else { } else {
yield UNKNOWN_SIZE_VINT_BUF[2]; yield UNKNOWN_SIZE_VINT_BUF[2];
} }
} else { } else {
yield writeVint(this._contentLength); yield writeVint(this._contentLength);
} }
} }
public *encode(): Generator<Uint8Array, void, unknown> { public *encode(): Generator<Uint8Array, void, unknown> {
if (this._contentLength === Number.POSITIVE_INFINITY) { if (this._contentLength === Number.POSITIVE_INFINITY) {
yield* this.encodeHeader(); yield* this.encodeHeader();
for (const part of this.encodeContent()) { for (const part of this.encodeContent()) {
yield part; yield part;
} }
} else { } else {
let size = 0; let size = 0;
const parts: Uint8Array[] = []; const parts: Uint8Array[] = [];
for (const part of this.encodeContent()) { for (const part of this.encodeContent()) {
parts.push(part); parts.push(part);
size += part.byteLength; size += part.byteLength;
} }
this._contentLength = size; this._contentLength = size;
yield* this.encodeHeader(); yield* this.encodeHeader();
for (const part of parts) { for (const part of parts) {
yield part; yield part;
} }
} }
} }
public toDebugRecord(): Record<string, any> { public toDebugRecord(): Record<string, any> {
return { return {
id: EbmlTagIdEnum[this.id as any] || this.id, id: EbmlTagIdEnum[this.id as any] || this.id,
type: this.type, type: this.type,
position: EbmlTagPosition[this.position], position: EbmlTagPosition[this.position],
contentLength: this.contentLength, contentLength: this.contentLength,
headerLength: this.headerLength, headerLength: this.headerLength,
startOffset: this.startOffset, startOffset: this.startOffset,
endOffset: this.endOffset, endOffset: this.endOffset,
}; };
} }
} }

View File

@ -23,7 +23,8 @@ export type EbmlTagExcludeField =
| 'position' | 'position'
| 'parent' | 'parent'
| 'type' | 'type'
| 'data'; | 'data'
| 'children';
export type EbmlUintTagType = Omit<EbmlDataTag, EbmlTagExcludeField> & { export type EbmlUintTagType = Omit<EbmlDataTag, EbmlTagExcludeField> & {
id: EbmlUintDataTagIdType; id: EbmlUintDataTagIdType;
@ -31,6 +32,7 @@ export type EbmlUintTagType = Omit<EbmlDataTag, EbmlTagExcludeField> & {
parent?: EbmlMasterTag; parent?: EbmlMasterTag;
type: EbmlElementType.UnsignedInt; type: EbmlElementType.UnsignedInt;
data: number | bigint; data: number | bigint;
children?: [];
}; };
export type EbmlIntTagType = Omit<EbmlDataTag, EbmlTagExcludeField> & { export type EbmlIntTagType = Omit<EbmlDataTag, EbmlTagExcludeField> & {
@ -39,6 +41,7 @@ export type EbmlIntTagType = Omit<EbmlDataTag, EbmlTagExcludeField> & {
parent?: EbmlMasterTag; parent?: EbmlMasterTag;
type: EbmlElementType.Integer; type: EbmlElementType.Integer;
data: number | bigint; data: number | bigint;
children?: [];
}; };
export type EbmlUtf8TagType = Omit<EbmlDataTag, EbmlTagExcludeField> & { export type EbmlUtf8TagType = Omit<EbmlDataTag, EbmlTagExcludeField> & {
@ -47,6 +50,7 @@ export type EbmlUtf8TagType = Omit<EbmlDataTag, EbmlTagExcludeField> & {
parent?: EbmlMasterTag; parent?: EbmlMasterTag;
type: EbmlElementType.UTF8; type: EbmlElementType.UTF8;
data: string; data: string;
children?: [];
}; };
export type EbmlAsciiTagType = Omit<EbmlDataTag, EbmlTagExcludeField> & { export type EbmlAsciiTagType = Omit<EbmlDataTag, EbmlTagExcludeField> & {
@ -55,6 +59,7 @@ export type EbmlAsciiTagType = Omit<EbmlDataTag, EbmlTagExcludeField> & {
parent?: EbmlMasterTag; parent?: EbmlMasterTag;
type: EbmlElementType.Ascii; type: EbmlElementType.Ascii;
data: string; data: string;
children?: [];
}; };
export type EbmlDateTagType = Omit<EbmlDataTag, EbmlTagExcludeField> & { export type EbmlDateTagType = Omit<EbmlDataTag, EbmlTagExcludeField> & {
@ -63,6 +68,7 @@ export type EbmlDateTagType = Omit<EbmlDataTag, EbmlTagExcludeField> & {
parent?: EbmlMasterTag; parent?: EbmlMasterTag;
type: EbmlElementType.Date; type: EbmlElementType.Date;
data: Uint8Array; data: Uint8Array;
children?: [];
}; };
export type EbmlFloatTagType = Omit<EbmlDataTag, EbmlTagExcludeField> & { export type EbmlFloatTagType = Omit<EbmlDataTag, EbmlTagExcludeField> & {
@ -71,6 +77,7 @@ export type EbmlFloatTagType = Omit<EbmlDataTag, EbmlTagExcludeField> & {
parent?: EbmlMasterTag; parent?: EbmlMasterTag;
type: EbmlElementType.Float; type: EbmlElementType.Float;
data: number; data: number;
children?: [];
}; };
export type EbmlBinaryTagType = Omit<EbmlDataTag, EbmlTagExcludeField> & { export type EbmlBinaryTagType = Omit<EbmlDataTag, EbmlTagExcludeField> & {
@ -79,6 +86,7 @@ export type EbmlBinaryTagType = Omit<EbmlDataTag, EbmlTagExcludeField> & {
parent?: EbmlMasterTag; parent?: EbmlMasterTag;
type: EbmlElementType.Binary; type: EbmlElementType.Binary;
data: Uint8Array; data: Uint8Array;
children?: [];
}; };
export type EbmlUnknownTagType = Omit<EbmlDataTag, EbmlTagExcludeField> & { export type EbmlUnknownTagType = Omit<EbmlDataTag, EbmlTagExcludeField> & {
@ -87,6 +95,7 @@ export type EbmlUnknownTagType = Omit<EbmlDataTag, EbmlTagExcludeField> & {
parent?: EbmlMasterTag; parent?: EbmlMasterTag;
type?: undefined; type?: undefined;
data: Uint8Array; data: Uint8Array;
children?: [];
}; };
export type EbmlDataTagType = export type EbmlDataTagType =
@ -104,6 +113,7 @@ export type EbmlBlockTagType = Omit<EbmlBlockTag, EbmlTagExcludeField> & {
parent?: EbmlMasterTag; parent?: EbmlMasterTag;
type?: undefined; type?: undefined;
data?: undefined; data?: undefined;
children?: [];
}; };
export type EbmlSimpleBlockTagType = Omit< export type EbmlSimpleBlockTagType = Omit<
@ -115,6 +125,7 @@ export type EbmlSimpleBlockTagType = Omit<
parent?: EbmlMasterTag; parent?: EbmlMasterTag;
type?: undefined; type?: undefined;
data?: undefined; data?: undefined;
children?: [];
}; };
export type EbmlMasterTagType = Omit<EbmlMasterTag, EbmlTagExcludeField> & { export type EbmlMasterTagType = Omit<EbmlMasterTag, EbmlTagExcludeField> & {

View File

@ -1,13 +1,13 @@
import { import {
VintOutOfRangeError,
VintLengthOutOfRangeError,
ElementIdVintDataAllOnesError, ElementIdVintDataAllOnesError,
ElementIdVintDataAllZerosError, ElementIdVintDataAllZerosError,
ElementIdVintDataNotShortestError, ElementIdVintDataNotShortestError,
UnsupportLengthForElementTypeError,
OutOfRangeForElementTypeError, OutOfRangeForElementTypeError,
SizeUnitOutOfSafeIntegerRangeError, SizeUnitOutOfSafeIntegerRangeError,
UnreachableOrLogicError, UnreachableOrLogicError,
UnsupportLengthForElementTypeError,
VintLengthOutOfRangeError,
VintOutOfRangeError,
} from './errors'; } from './errors';
import { import {
EbmlElementType, EbmlElementType,

View File

@ -1,11 +1,11 @@
import { assert, describe, it } from 'vitest';
import { import {
EbmlTagPosition,
EbmlElementType,
EbmlStreamDecoder as Decoder, EbmlStreamDecoder as Decoder,
EbmlDataTag, EbmlDataTag,
EbmlElementType,
EbmlTagPosition,
type EbmlTagType, type EbmlTagType,
} from 'konoebml'; } from 'konoebml';
import { assert, describe, it } from 'vitest';
const bufFrom = (data: Uint8Array | readonly number[]): ArrayBuffer => const bufFrom = (data: Uint8Array | readonly number[]): ArrayBuffer =>
new Uint8Array(data).buffer; new Uint8Array(data).buffer;

View File

@ -1,11 +1,11 @@
import { assert, expect, describe, it } from 'vitest';
import { import {
EbmlStreamEncoder,
EbmlTagIdEnum,
EbmlTagPosition, EbmlTagPosition,
type EbmlTagTrait, type EbmlTagTrait,
EbmlTagIdEnum,
createEbmlTagForManuallyBuild, createEbmlTagForManuallyBuild,
EbmlStreamEncoder,
} from 'konoebml'; } from 'konoebml';
import { assert, describe, expect, it } from 'vitest';
const invalidTag: EbmlTagTrait = <EbmlTagTrait>(<any>{ const invalidTag: EbmlTagTrait = <EbmlTagTrait>(<any>{
id: undefined, id: undefined,

View File

@ -1,14 +1,14 @@
import { assert, describe, it, expect } from 'vitest';
import { import {
type EbmlBlockTag,
EbmlStreamDecoder, EbmlStreamDecoder,
EbmlStreamEncoder, EbmlStreamEncoder,
type EbmlTagTrait,
EbmlTagIdEnum, EbmlTagIdEnum,
type EbmlBlockTag, type EbmlTagTrait,
createEbmlTagForManuallyBuild,
type EbmlTagType, type EbmlTagType,
createEbmlTagForManuallyBuild,
} from 'konoebml'; } from 'konoebml';
import { concatArrayBuffers } from 'konoebml/tools'; import { concatArrayBuffers } from 'konoebml/tools';
import { assert, describe, expect, it } from 'vitest';
describe('EBML Pipeline', () => { describe('EBML Pipeline', () => {
async function assertPipelineOutputEquals( async function assertPipelineOutputEquals(

View File

@ -1,4 +1,3 @@
import { assert, describe, it } from 'vitest';
import { import {
readAscii, readAscii,
readElementIdVint, readElementIdVint,
@ -9,6 +8,7 @@ import {
readVint, readVint,
writeVint, writeVint,
} from 'konoebml/tools'; } from 'konoebml/tools';
import { assert, describe, it } from 'vitest';
function bufFrom(data: Uint8Array | readonly number[]): Uint8Array { function bufFrom(data: Uint8Array | readonly number[]): Uint8Array {
return new Uint8Array(data); return new Uint8Array(data);

View File

@ -1,14 +1,14 @@
import fs from 'node:fs'; import fs from 'node:fs';
import { assert, describe, it } from 'vitest';
import {
EbmlStreamDecoder,
EbmlTagIdEnum,
EbmlSimpleBlockTag as SimpleBlock,
EbmlDataTag,
type EbmlTagType,
} from 'konoebml';
import { Readable } from 'node:stream'; import { Readable } from 'node:stream';
import { WritableStream } from 'node:stream/web'; import { WritableStream } from 'node:stream/web';
import {
EbmlDataTag,
EbmlStreamDecoder,
EbmlTagIdEnum,
type EbmlTagType,
EbmlSimpleBlockTag as SimpleBlock,
} from 'konoebml';
import { assert, describe, it } from 'vitest';
process.setMaxListeners(Number.POSITIVE_INFINITY); process.setMaxListeners(Number.POSITIVE_INFINITY);

View File

@ -1,19 +1,15 @@
{ {
"compilerOptions": { "compilerOptions": {
"forceConsistentCasingInFileNames": true, "forceConsistentCasingInFileNames": true,
"esModuleInterop": true, "esModuleInterop": true,
"strict": true, "strict": true,
"skipLibCheck": true, "skipLibCheck": true,
"noFallthroughCasesInSwitch": true, "noFallthroughCasesInSwitch": true,
"useDefineForClassFields": true, "useDefineForClassFields": true,
"resolveJsonModule": true, "resolveJsonModule": true,
"moduleResolution": "bundler", "moduleResolution": "bundler",
"target": "ES2021", "target": "ES2021",
"module": "ESNext", "module": "ESNext",
"lib": [ "lib": ["ES2021", "DOM", "DOM.Iterable"]
"ES2021", }
"DOM", }
"DOM.Iterable"
]
}
}

View File

@ -1,28 +1,20 @@
{ {
"extends": "./tsconfig.base.json", "extends": "./tsconfig.base.json",
"compilerOptions": { "compilerOptions": {
"composite": true, "composite": true,
"rootDir": ".", "rootDir": ".",
"types": [ "types": ["node"],
"node" "noEmit": true,
], "paths": {
"noEmit": true, "konoebml": ["./src/index.ts"],
"paths": { "konoebml/*": ["./src/*"]
"konoebml": [ }
"./src/index.ts" },
], "files": [],
"konoebml/*": [ "include": ["examples/*"],
"./src/*" "references": [
] {
} "path": "./tsconfig.lib.json"
}, }
"files": [], ]
"include": [ }
"examples/*"
],
"references": [
{
"path": "./tsconfig.lib.json"
}
]
}

View File

@ -2,9 +2,7 @@
"extends": "./tsconfig.base.json", "extends": "./tsconfig.base.json",
"files": [], "files": [],
"include": [], "include": [],
"exclude": [ "exclude": ["node_modules"],
"node_modules"
],
"references": [ "references": [
{ {
"path": "./tsconfig.lib.json" "path": "./tsconfig.lib.json"
@ -16,4 +14,4 @@
"path": "./tsconfig.example.json" "path": "./tsconfig.example.json"
} }
] ]
} }

View File

@ -1,17 +1,15 @@
{ {
"extends": "./tsconfig.base.json", "extends": "./tsconfig.base.json",
"compilerOptions": { "compilerOptions": {
"composite": true, "composite": true,
"rootDir": "./src", "rootDir": "./src",
"baseUrl": ".", "baseUrl": ".",
"declarationDir": "./dist", "declarationDir": "./dist",
"outDir": "./dist", "outDir": "./dist",
"declaration": true, "declaration": true,
"declarationMap": true, "declarationMap": true,
"emitDeclarationOnly": true "emitDeclarationOnly": true
}, },
"include": [ "include": ["src"],
"src" "exclude": []
], }
"exclude": []
}

View File

@ -3,27 +3,18 @@
"compilerOptions": { "compilerOptions": {
"composite": true, "composite": true,
"rootDir": ".", "rootDir": ".",
"types": [ "types": ["vitest/globals", "node"],
"vitest/globals",
"node"
],
"noEmit": true, "noEmit": true,
"paths": { "paths": {
"konoebml": [ "konoebml": ["./src/index.ts"],
"./src/index.ts" "konoebml/*": ["./src/*"]
],
"konoebml/*": [
"./src/*"
]
} }
}, },
"files": [], "files": [],
"include": [ "include": ["tests/*"],
"tests/*"
],
"references": [ "references": [
{ {
"path": "./tsconfig.lib.json" "path": "./tsconfig.lib.json"
} }
] ]
} }