diff --git a/biome.jsonc b/biome.jsonc index 21cdadb..8b35ab3 100644 --- a/biome.jsonc +++ b/biome.jsonc @@ -1,66 +1,55 @@ { - "$schema": "https://biomejs.dev/schemas/1.9.4/schema.json", - "extends": [ - "ultracite" - ], - "linter": { + "$schema": "https://biomejs.dev/schemas/1.9.4/schema.json", + "extends": ["ultracite"], + "linter": { + "rules": { + "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": { - "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" - } + "performance": { + "useTopLevelRegex": "off" + }, + "suspicious": { + "noMisplacedAssertion": "off" + } } - }, - "files": { - "ignore": [ - ".vscode/*.json" - ] - }, - "overrides": [ - { - "include": [ - "tests/**" - ], - "javascript": { - "globals": [ - "describe", - "beforeEach", - "it", - "expect" - ] - }, - "linter": { - "rules": { - "performance": { - "useTopLevelRegex": "off" - }, - "suspicious": { - "noMisplacedAssertion": "off" - } - } - } - } - ] -} \ No newline at end of file + } + } + ] +} diff --git a/examples/playground.ts b/examples/playground.ts index 275cb89..32be857 100644 --- a/examples/playground.ts +++ b/examples/playground.ts @@ -1,8 +1,8 @@ import fs from 'node:fs/promises'; import { ReadableStream, - WritableStream, type TransformStream, + WritableStream, } from 'node:stream/web'; import { EbmlStreamDecoder } from 'konoebml'; diff --git a/package.json b/package.json index 7971f8a..58a91dc 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "konoebml", - "version": "0.1.0-rc.4", + "version": "0.1.0-rc.5", "description": "A modern JavaScript implementation of EBML RFC8794", "main": "./dist/index.cjs", "module": "./dist/index.js", @@ -20,8 +20,8 @@ "test": "vitest --coverage", "test-ci": "vitest --watch=false --coverage", "prepublishOnly": "npm run build", - "lint": "ultracite lint", - "format": "ultracite format", + "lint": "biome lint", + "lint-fix": "biome lint --fix", "playground": "tsx --tsconfig=./tsconfig.example.json ./examples/playground.ts" }, "repository": "github:dumtruck/konoebml", diff --git a/src/decode-utils.ts b/src/decode-utils.ts index 268ded5..a7f29cf 100644 --- a/src/decode-utils.ts +++ b/src/decode-utils.ts @@ -1,124 +1,124 @@ -import { type EbmlTagIdType, isEbmlMasterTagId } from './models/enums'; -import type { DecodeContentOptions, EbmlTagTrait } from './models/tag-trait'; -import type { FileDataViewController } from './adapters'; -import { - checkVintSafeSize, - dataViewSlice, - readUnsigned, - readVint, - readVintLength, - type SafeSizeVint, -} from './tools'; -import { EbmlTagPosition } from './models/enums'; -import { createEbmlTag } from './factory'; -import { UnreachableOrLogicError } from './errors'; - -export async function decodeEbmlTagHeader( - controller: FileDataViewController -): Promise<{ - sizeVint: SafeSizeVint; - tagVint: { length: number }; - tagId: EbmlTagIdType; -}> { - const offset = controller.getOffset(); - - let view = await controller.read(offset, 1); - - const tagVintLength = readVintLength(view); - - view = - tagVintLength > view.byteLength - ? await controller.read(offset, tagVintLength) - : view; - - const tagIdView = dataViewSlice(view, 0, tagVintLength); - - view = - tagVintLength + 1 > view.byteLength - ? await controller.read(offset, tagVintLength + 1) - : view; - - const sizeVintLength = readVintLength( - dataViewSlice(view, tagVintLength, tagVintLength + 1) - ); - - view = - tagVintLength + sizeVintLength > view.byteLength - ? await controller.read(offset, tagVintLength + sizeVintLength) - : view; - - const sizeVint = readVint( - dataViewSlice(view, tagVintLength, tagVintLength + sizeVintLength) - )!; - - if (!sizeVint) { - throw new UnreachableOrLogicError( - 'size vint dataView length is invalid, check code logic!' - ); - } - - const tagId = readUnsigned(tagIdView); - - const safeSizeVint = checkVintSafeSize(sizeVint, tagId); - - return { - sizeVint: safeSizeVint, - tagVint: { - length: tagVintLength, - }, - tagId, - }; -} - -export async function* decodeEbmlContent( - options: DecodeContentOptions -): AsyncGenerator { - const controller = options.dataViewController; - while (true) { - const offset = controller.getOffset(); - - const peeked = await controller.peek(offset); - - if (!peeked) { - break; - } - - const vints = await decodeEbmlTagHeader(controller); - - const { tagId, tagVint, sizeVint } = vints; - - const headerLength = tagVint.length + sizeVint.length; - const contentLength = sizeVint.value; - - const isMaster = isEbmlMasterTagId(tagId); - - if (isMaster) { - const tag: EbmlTagTrait = createEbmlTag(tagId, { - headerLength, - contentLength, - startOffset: offset, - position: EbmlTagPosition.Start, - parent: undefined, - }); - yield tag; - } - - await controller.seek(offset + headerLength); - - const tag: EbmlTagTrait = createEbmlTag(tagId, { - headerLength, - contentLength, - startOffset: offset, - position: isMaster ? EbmlTagPosition.End : EbmlTagPosition.Content, - parent: undefined, - }); - - for await (const item of tag.decodeContent(options)) { - yield item; - } - - tag.endOffset = controller.getOffset(); - - yield tag; - } -} +import type { FileDataViewController } from './adapters'; +import { UnreachableOrLogicError } from './errors'; +import { createEbmlTag } from './factory'; +import { type EbmlTagIdType, isEbmlMasterTagId } from './models/enums'; +import { EbmlTagPosition } from './models/enums'; +import type { DecodeContentOptions, EbmlTagTrait } from './models/tag-trait'; +import { + type SafeSizeVint, + checkVintSafeSize, + dataViewSlice, + readUnsigned, + readVint, + readVintLength, +} from './tools'; + +export async function decodeEbmlTagHeader( + controller: FileDataViewController +): Promise<{ + sizeVint: SafeSizeVint; + tagVint: { length: number }; + tagId: EbmlTagIdType; +}> { + const offset = controller.getOffset(); + + let view = await controller.read(offset, 1); + + const tagVintLength = readVintLength(view); + + view = + tagVintLength > view.byteLength + ? await controller.read(offset, tagVintLength) + : view; + + const tagIdView = dataViewSlice(view, 0, tagVintLength); + + view = + tagVintLength + 1 > view.byteLength + ? await controller.read(offset, tagVintLength + 1) + : view; + + const sizeVintLength = readVintLength( + dataViewSlice(view, tagVintLength, tagVintLength + 1) + ); + + view = + tagVintLength + sizeVintLength > view.byteLength + ? await controller.read(offset, tagVintLength + sizeVintLength) + : view; + + const sizeVint = readVint( + dataViewSlice(view, tagVintLength, tagVintLength + sizeVintLength) + )!; + + if (!sizeVint) { + throw new UnreachableOrLogicError( + 'size vint dataView length is invalid, check code logic!' + ); + } + + const tagId = readUnsigned(tagIdView); + + const safeSizeVint = checkVintSafeSize(sizeVint, tagId); + + return { + sizeVint: safeSizeVint, + tagVint: { + length: tagVintLength, + }, + tagId, + }; +} + +export async function* decodeEbmlContent( + options: DecodeContentOptions +): AsyncGenerator { + const controller = options.dataViewController; + while (true) { + const offset = controller.getOffset(); + + const peeked = await controller.peek(offset); + + if (!peeked) { + break; + } + + const vints = await decodeEbmlTagHeader(controller); + + const { tagId, tagVint, sizeVint } = vints; + + const headerLength = tagVint.length + sizeVint.length; + const contentLength = sizeVint.value; + + const isMaster = isEbmlMasterTagId(tagId); + + if (isMaster) { + const tag: EbmlTagTrait = createEbmlTag(tagId, { + headerLength, + contentLength, + startOffset: offset, + position: EbmlTagPosition.Start, + parent: undefined, + }); + yield tag; + } + + await controller.seek(offset + headerLength); + + const tag: EbmlTagTrait = createEbmlTag(tagId, { + headerLength, + contentLength, + startOffset: offset, + position: isMaster ? EbmlTagPosition.End : EbmlTagPosition.Content, + parent: undefined, + }); + + for await (const item of tag.decodeContent(options)) { + yield item; + } + + tag.endOffset = controller.getOffset(); + + yield tag; + } +} diff --git a/src/decoder.ts b/src/decoder.ts index 37e25fe..851e1cf 100644 --- a/src/decoder.ts +++ b/src/decoder.ts @@ -1,13 +1,13 @@ import { Queue } from 'mnemonist'; import type { FileDataViewController } from './adapters'; +import { decodeEbmlContent } from './decode-utils'; +import { StreamFlushReason, UnreachableOrLogicError } from './errors'; +import type { EbmlTagType } from './models/tag'; import type { DecodeContentCollectChildPredicate, EbmlTagTrait, } from './models/tag-trait'; -import { decodeEbmlContent } from './decode-utils'; -import { StreamFlushReason, UnreachableOrLogicError } from './errors'; import { dataViewSlice } from './tools'; -import type { EbmlTagType } from './models/tag'; export type EbmlStreamDecoderChunkType = | Uint8Array diff --git a/src/encoder.ts b/src/encoder.ts index 3dc4920..de88181 100644 --- a/src/encoder.ts +++ b/src/encoder.ts @@ -1,9 +1,9 @@ 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 { EbmlTagPosition } from './models/enums'; import type { EbmlTagType } from './models/tag'; +import { EbmlMasterTag } from './models/tag-master'; +import { EbmlTagTrait } from './models/tag-trait'; export class EbmlEncodeStreamTransformer implements Transformer diff --git a/src/factory.ts b/src/factory.ts index b22acbf..fc9d4c8 100644 --- a/src/factory.ts +++ b/src/factory.ts @@ -1,21 +1,21 @@ import { InconsistentWellKnownEbmlTagTypeError } from './errors'; import { - type EbmlMasterTagIdType, - type EbmlDataTagIdType, type EbmlBlockTagIdType, - type EbmlSimpleBlockTagIdType, + type EbmlDataTagIdType, EbmlElementType, + type EbmlMasterTagIdType, + type EbmlSimpleBlockTagIdType, EbmlTagIdEnum, - isEbmlBlockTagId, - isEbmlSimpleBlockTagId, - isEbmlMasterTagId, - isEbmlUintDataTagId, - isEbmlIntDataTagId, - isEbmlFloatDataTagId, - isEbmlStringDataTagId, - isEbmlUtf8DataTagId, - isEbmlDateDataTagId, isEbmlBinaryDataTagId, + isEbmlBlockTagId, + isEbmlDateDataTagId, + isEbmlFloatDataTagId, + isEbmlIntDataTagId, + isEbmlMasterTagId, + isEbmlSimpleBlockTagId, + isEbmlStringDataTagId, + isEbmlUintDataTagId, + isEbmlUtf8DataTagId, } from './models/enums'; import { type CreateEbmlBlockTagOptions, diff --git a/src/models/tag-block.ts b/src/models/tag-block.ts index 496f18d..87ecee4 100644 --- a/src/models/tag-block.ts +++ b/src/models/tag-block.ts @@ -1,124 +1,124 @@ -import { type CreateEbmlDataTagOptions, EbmlDataTag } from './tag-data'; -import { EbmlBlockLacing } from './enums'; -import { - dataViewSlice, - dataViewSliceToBuf, - readSigned, - readVint, - writeSigned, - writeVint, -} from '../tools'; -import { - type EbmlBlockTagIdType, - type EbmlSimpleBlockTagIdType, - EbmlTagIdEnum, -} from './enums'; -import { EbmlElementType } from './enums'; -import type { DecodeContentOptions } from './tag-trait'; - -export interface CreateEbmlBlockTagOptions - extends Omit { - id?: EbmlBlockTagIdType | EbmlSimpleBlockTagIdType; -} - -export class EbmlBlockTag extends EbmlDataTag { - payload = new Uint8Array(0); - track: number | bigint = 0; - value = 0; - - invisible: boolean | undefined; - lacing: EbmlBlockLacing | undefined; - - constructor(options: CreateEbmlBlockTagOptions) { - super({ - ...options, - id: options.id ?? EbmlTagIdEnum.Block, - type: EbmlElementType.Binary, - }); - } - - protected writeTrackBuffer(): Uint8Array { - return writeVint(this.track); - } - - protected writeValueBuffer(): Uint8Array { - return writeSigned(this.value, 2); - } - - protected writeFlagsBuffer(): Uint8Array { - let flags = 0x00; - if (this.invisible) { - flags |= 0x10; - } - - switch (this.lacing) { - case EbmlBlockLacing.None: - break; - case EbmlBlockLacing.Xiph: - flags |= 0x04; - break; - case EbmlBlockLacing.EBML: - flags |= 0x08; - break; - case EbmlBlockLacing.FixedSize: - flags |= 0x0c; - break; - default: - } - - return new Uint8Array([flags % 256]); - } - - *encodeContent(): Generator { - yield this.writeTrackBuffer(); - yield this.writeValueBuffer(); - yield this.writeFlagsBuffer(); - yield this.payload; - } - - // biome-ignore lint/correctness/useYield: - async *decodeContentImpl(options: DecodeContentOptions) { - const controller = options.dataViewController; - const offset = controller.getOffset(); - const view = await controller.read(offset, this.contentLength, true); - const track = readVint(view)!; - this.track = track.value; - this.value = Number( - readSigned(dataViewSlice(view, track.length, track.length + 2)) - ); - const flags: number = view.getUint8(track.length + 2); - this.invisible = Boolean(flags & 0x10); - switch (flags & 0x0c) { - case 0x00: - this.lacing = EbmlBlockLacing.None; - break; - - case 0x04: - this.lacing = EbmlBlockLacing.Xiph; - break; - - case 0x08: - this.lacing = EbmlBlockLacing.EBML; - break; - - case 0x0c: - this.lacing = EbmlBlockLacing.FixedSize; - break; - default: - } - this.payload = dataViewSliceToBuf(view, track.length + 3, undefined); - await controller.seek(offset + view.byteLength); - } - - override toDebugRecord() { - const s = super.toDebugRecord(); - return { - ...s, - payload: this.payload, - track: this.track, - value: this.value, - invisible: this.invisible, - lacing: EbmlBlockLacing[this.lacing!] || this.lacing, - }; - } -} +import { + dataViewSlice, + dataViewSliceToBuf, + readSigned, + readVint, + writeSigned, + writeVint, +} from '../tools'; +import { EbmlBlockLacing } from './enums'; +import { + type EbmlBlockTagIdType, + type EbmlSimpleBlockTagIdType, + EbmlTagIdEnum, +} from './enums'; +import { EbmlElementType } from './enums'; +import { type CreateEbmlDataTagOptions, EbmlDataTag } from './tag-data'; +import type { DecodeContentOptions } from './tag-trait'; + +export interface CreateEbmlBlockTagOptions + extends Omit { + id?: EbmlBlockTagIdType | EbmlSimpleBlockTagIdType; +} + +export class EbmlBlockTag extends EbmlDataTag { + payload = new Uint8Array(0); + track: number | bigint = 0; + value = 0; + + invisible: boolean | undefined; + lacing: EbmlBlockLacing | undefined; + + constructor(options: CreateEbmlBlockTagOptions) { + super({ + ...options, + id: options.id ?? EbmlTagIdEnum.Block, + type: EbmlElementType.Binary, + }); + } + + protected writeTrackBuffer(): Uint8Array { + return writeVint(this.track); + } + + protected writeValueBuffer(): Uint8Array { + return writeSigned(this.value, 2); + } + + protected writeFlagsBuffer(): Uint8Array { + let flags = 0x00; + if (this.invisible) { + flags |= 0x10; + } + + switch (this.lacing) { + case EbmlBlockLacing.None: + break; + case EbmlBlockLacing.Xiph: + flags |= 0x04; + break; + case EbmlBlockLacing.EBML: + flags |= 0x08; + break; + case EbmlBlockLacing.FixedSize: + flags |= 0x0c; + break; + default: + } + + return new Uint8Array([flags % 256]); + } + + *encodeContent(): Generator { + yield this.writeTrackBuffer(); + yield this.writeValueBuffer(); + yield this.writeFlagsBuffer(); + yield this.payload; + } + + // biome-ignore lint/correctness/useYield: + async *decodeContentImpl(options: DecodeContentOptions) { + const controller = options.dataViewController; + const offset = controller.getOffset(); + const view = await controller.read(offset, this.contentLength, true); + const track = readVint(view)!; + this.track = track.value; + this.value = Number( + readSigned(dataViewSlice(view, track.length, track.length + 2)) + ); + const flags: number = view.getUint8(track.length + 2); + this.invisible = Boolean(flags & 0x10); + switch (flags & 0x0c) { + case 0x00: + this.lacing = EbmlBlockLacing.None; + break; + + case 0x04: + this.lacing = EbmlBlockLacing.Xiph; + break; + + case 0x08: + this.lacing = EbmlBlockLacing.EBML; + break; + + case 0x0c: + this.lacing = EbmlBlockLacing.FixedSize; + break; + default: + } + this.payload = dataViewSliceToBuf(view, track.length + 3, undefined); + await controller.seek(offset + view.byteLength); + } + + override toDebugRecord() { + const s = super.toDebugRecord(); + return { + ...s, + payload: this.payload, + track: this.track, + value: this.value, + invisible: this.invisible, + lacing: EbmlBlockLacing[this.lacing!] || this.lacing, + }; + } +} diff --git a/src/models/tag-data.ts b/src/models/tag-data.ts index b183547..27edeef 100644 --- a/src/models/tag-data.ts +++ b/src/models/tag-data.ts @@ -1,95 +1,95 @@ -import { - type CreateEbmlTagOptions, - type DecodeContentOptions, - EbmlTagTrait, -} from './tag-trait'; -import { EbmlElementType } from './enums'; -import { - dataViewSliceToBuf, - readAscii, - readFloat, - readSigned, - readUnsigned, - readUtf8, - writeAscii, - writeFloat, - writeSigned, - writeUnsigned, - writeUtf8, -} from '../tools'; -import { EbmlTagPosition } from './enums'; - -export type CreateEbmlDataTagOptions = Omit; - -export class EbmlDataTag extends EbmlTagTrait { - data: number | string | bigint | null | Uint8Array | undefined; - - constructor(options: CreateEbmlDataTagOptions) { - super({ - ...options, - position: EbmlTagPosition.Content, - }); - } - - // biome-ignore lint/correctness/useYield: - override async *decodeContentImpl(options: DecodeContentOptions) { - const controller = options.dataViewController; - const offset = controller.getOffset(); - const view = await controller.read(offset, this.contentLength, true); - switch (this.type) { - case EbmlElementType.UnsignedInt: - this.data = readUnsigned(view); - break; - case EbmlElementType.Float: - this.data = readFloat(view); - break; - case EbmlElementType.Integer: - this.data = readSigned(view); - break; - case EbmlElementType.Ascii: - this.data = readAscii(view); - break; - case EbmlElementType.UTF8: - this.data = readUtf8(view); - break; - default: - this.data = dataViewSliceToBuf(view, undefined, undefined); - break; - } - await controller.seek(offset + view.byteLength); - } - - *encodeContent(): Generator { - switch (this.type) { - case EbmlElementType.UnsignedInt: - yield writeUnsigned(this.data as any); - break; - case EbmlElementType.Float: - yield writeFloat(this.data as any); - break; - case EbmlElementType.Integer: - yield writeSigned(this.data as any); - break; - case EbmlElementType.Ascii: - yield writeAscii(this.data as any); - break; - case EbmlElementType.UTF8: - yield writeUtf8(this.data as any); - break; - default: - yield this.data as Uint8Array; - break; - } - } - - override toDebugRecord() { - return { - ...super.toDebugRecord(), - data: this.data, - }; - } - - toJSON() { - return JSON.stringify(this.toDebugRecord(), null, 2); - } -} +import { + dataViewSliceToBuf, + readAscii, + readFloat, + readSigned, + readUnsigned, + readUtf8, + writeAscii, + writeFloat, + writeSigned, + writeUnsigned, + writeUtf8, +} from '../tools'; +import { EbmlElementType } from './enums'; +import { EbmlTagPosition } from './enums'; +import { + type CreateEbmlTagOptions, + type DecodeContentOptions, + EbmlTagTrait, +} from './tag-trait'; + +export type CreateEbmlDataTagOptions = Omit; + +export class EbmlDataTag extends EbmlTagTrait { + data: number | string | bigint | null | Uint8Array | undefined; + + constructor(options: CreateEbmlDataTagOptions) { + super({ + ...options, + position: EbmlTagPosition.Content, + }); + } + + // biome-ignore lint/correctness/useYield: + override async *decodeContentImpl(options: DecodeContentOptions) { + const controller = options.dataViewController; + const offset = controller.getOffset(); + const view = await controller.read(offset, this.contentLength, true); + switch (this.type) { + case EbmlElementType.UnsignedInt: + this.data = readUnsigned(view); + break; + case EbmlElementType.Float: + this.data = readFloat(view); + break; + case EbmlElementType.Integer: + this.data = readSigned(view); + break; + case EbmlElementType.Ascii: + this.data = readAscii(view); + break; + case EbmlElementType.UTF8: + this.data = readUtf8(view); + break; + default: + this.data = dataViewSliceToBuf(view, undefined, undefined); + break; + } + await controller.seek(offset + view.byteLength); + } + + *encodeContent(): Generator { + switch (this.type) { + case EbmlElementType.UnsignedInt: + yield writeUnsigned(this.data as any); + break; + case EbmlElementType.Float: + yield writeFloat(this.data as any); + break; + case EbmlElementType.Integer: + yield writeSigned(this.data as any); + break; + case EbmlElementType.Ascii: + yield writeAscii(this.data as any); + break; + case EbmlElementType.UTF8: + yield writeUtf8(this.data as any); + break; + default: + yield this.data as Uint8Array; + break; + } + } + + override toDebugRecord() { + return { + ...super.toDebugRecord(), + data: this.data, + }; + } + + toJSON() { + return JSON.stringify(this.toDebugRecord(), null, 2); + } +} diff --git a/src/models/tag-master.ts b/src/models/tag-master.ts index 27cd4ee..9a94564 100644 --- a/src/models/tag-master.ts +++ b/src/models/tag-master.ts @@ -1,107 +1,107 @@ -import { - type CreateEbmlTagOptions, - type DecodeContentOptions, - EbmlTagTrait, -} from './tag-trait'; -import { EbmlElementType, EbmlTagPosition, isEbmlMasterTagId } from './enums'; -import { decodeEbmlTagHeader } from '../decode-utils'; -import { createEbmlTag } from 'src/factory'; -import type { EbmlMasterTagIdType } from './enums'; - -export interface CreateEbmlMasterTagOptions - extends Omit { - id: EbmlMasterTagIdType; -} - -export class EbmlMasterTag extends EbmlTagTrait { - private _children: EbmlTagTrait[] = []; - - get children(): EbmlTagTrait[] { - return this._children; - } - - set children(value: EbmlTagTrait[]) { - this._children = value; - } - - constructor(options: CreateEbmlMasterTagOptions) { - super({ - ...options, - id: options.id, - type: EbmlElementType.Master, - }); - } - - *encodeContent(): Generator { - for (const child of this.children) { - yield* child.encode(); - } - } - - async *decodeContentImpl(options: DecodeContentOptions) { - const controller = options.dataViewController; - const collectChild = options.collectChild; - while (true) { - const offset = controller.getOffset(); - - if (offset >= this.endOffset) { - break; - } - - const peeked = await controller.peek(offset); - - if (!peeked) { - break; - } - - const vints = await decodeEbmlTagHeader(controller); - - const { tagId, tagVint, sizeVint } = vints; - - const headerLength = tagVint.length + sizeVint.length; - const contentLength = sizeVint.value; - - const isMaster = isEbmlMasterTagId(tagId); - - if (isMaster) { - const tag: EbmlTagTrait = createEbmlTag(tagId, { - headerLength, - contentLength, - startOffset: offset, - position: EbmlTagPosition.Start, - parent: this, - }); - yield tag; - } - - await controller.seek(offset + headerLength); - - const tag: EbmlTagTrait = createEbmlTag(tagId, { - headerLength, - contentLength, - startOffset: offset, - position: isMaster ? EbmlTagPosition.End : EbmlTagPosition.Content, - parent: this, - }); - - for await (const item of tag.decodeContent(options)) { - yield item; - } - - tag.endOffset = controller.getOffset(); - - let shouldCollectChild: boolean; - if (typeof collectChild === 'function') { - shouldCollectChild = !!collectChild(tag, this); - } else { - shouldCollectChild = !!collectChild; - } - - if (shouldCollectChild) { - this._children.push(tag); - } - - yield tag; - } - } -} +import { createEbmlTag } from 'src/factory'; +import { decodeEbmlTagHeader } from '../decode-utils'; +import { EbmlElementType, EbmlTagPosition, isEbmlMasterTagId } from './enums'; +import type { EbmlMasterTagIdType } from './enums'; +import { + type CreateEbmlTagOptions, + type DecodeContentOptions, + EbmlTagTrait, +} from './tag-trait'; + +export interface CreateEbmlMasterTagOptions + extends Omit { + id: EbmlMasterTagIdType; +} + +export class EbmlMasterTag extends EbmlTagTrait { + private _children: EbmlTagTrait[] = []; + + get children(): EbmlTagTrait[] { + return this._children; + } + + set children(value: EbmlTagTrait[]) { + this._children = value; + } + + constructor(options: CreateEbmlMasterTagOptions) { + super({ + ...options, + id: options.id, + type: EbmlElementType.Master, + }); + } + + *encodeContent(): Generator { + for (const child of this.children) { + yield* child.encode(); + } + } + + async *decodeContentImpl(options: DecodeContentOptions) { + const controller = options.dataViewController; + const collectChild = options.collectChild; + while (true) { + const offset = controller.getOffset(); + + if (offset >= this.endOffset) { + break; + } + + const peeked = await controller.peek(offset); + + if (!peeked) { + break; + } + + const vints = await decodeEbmlTagHeader(controller); + + const { tagId, tagVint, sizeVint } = vints; + + const headerLength = tagVint.length + sizeVint.length; + const contentLength = sizeVint.value; + + const isMaster = isEbmlMasterTagId(tagId); + + if (isMaster) { + const tag: EbmlTagTrait = createEbmlTag(tagId, { + headerLength, + contentLength, + startOffset: offset, + position: EbmlTagPosition.Start, + parent: this, + }); + yield tag; + } + + await controller.seek(offset + headerLength); + + const tag: EbmlTagTrait = createEbmlTag(tagId, { + headerLength, + contentLength, + startOffset: offset, + position: isMaster ? EbmlTagPosition.End : EbmlTagPosition.Content, + parent: this, + }); + + for await (const item of tag.decodeContent(options)) { + yield item; + } + + tag.endOffset = controller.getOffset(); + + let shouldCollectChild: boolean; + if (typeof collectChild === 'function') { + shouldCollectChild = !!collectChild(tag, this); + } else { + shouldCollectChild = !!collectChild; + } + + if (shouldCollectChild) { + this._children.push(tag); + } + + yield tag; + } + } +} diff --git a/src/models/tag-simple-block.ts b/src/models/tag-simple-block.ts index 67da4e8..fa0a633 100644 --- a/src/models/tag-simple-block.ts +++ b/src/models/tag-simple-block.ts @@ -1,55 +1,55 @@ -import { readVint } from '../tools'; -import { type CreateEbmlBlockTagOptions, EbmlBlockTag } from './tag-block'; -import type { EbmlSimpleBlockTagIdType } from './enums'; -import type { DecodeContentOptions } from './tag-trait'; - -export interface CreateEbmlSimpleBlockTagOptions - extends Omit { - id?: EbmlSimpleBlockTagIdType; -} - -export class EbmlSimpleBlockTag extends EbmlBlockTag { - discardable: boolean | undefined; - keyframe: boolean | undefined; - - // biome-ignore lint/complexity/noUselessConstructor: - constructor(options: CreateEbmlSimpleBlockTagOptions) { - super(options); - } - - *encodeContent(): Generator { - const flags = this.writeFlagsBuffer(); - - if (this.keyframe) { - flags[0] |= 0x80; - } - if (this.discardable) { - flags[0] |= 0x01; - } - - yield this.writeTrackBuffer(); - yield this.writeValueBuffer(); - yield flags; - yield this.payload; - } - - async *decodeContentImpl(options: DecodeContentOptions) { - const controller = options.dataViewController; - const offset = controller.getOffset(); - - const view = await controller.read(offset, this.contentLength, true); - - for await (const item of super.decodeContentImpl(options)) { - yield item; - } - - const trackVint = readVint(view)!; - - const flags: number = view.getUint8(trackVint.length + 2); - this.keyframe = Boolean(flags & 0x80); - this.discardable = Boolean(flags & 0x01); - - // seeked by block tag - // await controller.seek(offset + this.contentLength); - } -} +import { readVint } from '../tools'; +import type { EbmlSimpleBlockTagIdType } from './enums'; +import { type CreateEbmlBlockTagOptions, EbmlBlockTag } from './tag-block'; +import type { DecodeContentOptions } from './tag-trait'; + +export interface CreateEbmlSimpleBlockTagOptions + extends Omit { + id?: EbmlSimpleBlockTagIdType; +} + +export class EbmlSimpleBlockTag extends EbmlBlockTag { + discardable: boolean | undefined; + keyframe: boolean | undefined; + + // biome-ignore lint/complexity/noUselessConstructor: + constructor(options: CreateEbmlSimpleBlockTagOptions) { + super(options); + } + + *encodeContent(): Generator { + const flags = this.writeFlagsBuffer(); + + if (this.keyframe) { + flags[0] |= 0x80; + } + if (this.discardable) { + flags[0] |= 0x01; + } + + yield this.writeTrackBuffer(); + yield this.writeValueBuffer(); + yield flags; + yield this.payload; + } + + async *decodeContentImpl(options: DecodeContentOptions) { + const controller = options.dataViewController; + const offset = controller.getOffset(); + + const view = await controller.read(offset, this.contentLength, true); + + for await (const item of super.decodeContentImpl(options)) { + yield item; + } + + const trackVint = readVint(view)!; + + const flags: number = view.getUint8(trackVint.length + 2); + this.keyframe = Boolean(flags & 0x80); + this.discardable = Boolean(flags & 0x01); + + // seeked by block tag + // await controller.seek(offset + this.contentLength); + } +} diff --git a/src/models/tag-trait.ts b/src/models/tag-trait.ts index 8ffd402..e5d8007 100644 --- a/src/models/tag-trait.ts +++ b/src/models/tag-trait.ts @@ -1,213 +1,213 @@ -import { EbmlTagPosition } from './enums'; -import { EbmlTagIdEnum, type EbmlTagIdType } from './enums'; -import type { EbmlElementType } from './enums'; -import { hexStringToBuf, UNKNOWN_SIZE_VINT_BUF, writeVint } from '../tools'; -import type { FileDataViewController } from '../adapters'; -import { InconsistentOffsetOnDecodingContentError } from '../errors'; -import type { EbmlMasterTag } from './tag-master'; - -export interface CreateEbmlTagOptions { - id: EbmlTagIdType; - type?: EbmlElementType; - position?: EbmlTagPosition; - headerLength: number; - contentLength: number; - startOffset: number; - endOffset?: number; - parent?: EbmlMasterTag; -} - -export type DecodeContentCollectChildPredicate = - | boolean - | ((child: EbmlTagTrait, parent: EbmlMasterTag) => boolean); - -export interface DecodeContentOptions { - collectChild?: DecodeContentCollectChildPredicate; - dataViewController: FileDataViewController; -} - -export abstract class EbmlTagTrait { - /** - * The id of the EBML tag. - * In most documentation this number is in hexadecimal format - */ - id: EbmlTagIdType; - /** - * The data type of the EBML tag - */ - type?: EbmlElementType; - /** - * The position of this EBML tag. - * Currently, one of "Start", "Content", or "End". - * "Start" and "End" only for Master type - */ - position: EbmlTagPosition; - /** - * Size vint length + tag vint length - */ - headerLength: number; - /** - * Start offset relative to context (stream or file) start - */ - startOffset: number; - /** - * Parent node - */ - parent?: EbmlTagTrait; - - /** - * Content length in ebml data - * Return Number.POSITIVE_INFINITY as "unknown" - */ - private _contentLength: number; - /** - * Caculated end offset when - */ - private _endOffset?: number; - - constructor(options: CreateEbmlTagOptions) { - this.id = options.id; - this.type = options.type; - this.position = options.position ?? EbmlTagPosition.Content; - this.parent = options.parent; - this.startOffset = options.startOffset; - this.headerLength = options.headerLength; - this._contentLength = options.contentLength; - this._endOffset = options.endOffset; - } - - public set contentLength(value: number) { - this._contentLength = value; - } - - /** - * After caculated or known, manually set endOffset - */ - public set endOffset(offset: number) { - this._endOffset = offset; - } - - /** - * End offset relative to context (stream or file) start - * Calcalate from self _contentLength and parent end offset - * Return Number.POSITIVE_INFINITY as "unknown" - */ - public get endOffset(): number { - if (this._endOffset) { - return this._endOffset; - } - if (this._contentLength === Number.POSITIVE_INFINITY) { - return this.parent?.endOffset ?? Number.POSITIVE_INFINITY; - } - return this.startOffset + this.headerLength + this._contentLength; - } - - /** - * Header length + Content Length - * Calcalate from self _contentLength and parent end offset - * Return Number.POSITIVE_INFINITY as "unknown" - */ - public get totalLength(): number { - return this.endOffset - this.startOffset; - } - - /** - * Content Length - * Calcalate from self _contentLength and parent end offset - * Return Number.POSITIVE_INFINITY as "unknown" - */ - public get contentLength(): number { - return this.totalLength - this.headerLength; - } - - protected abstract encodeContent(): Generator; - - /** - * Deep traversal and parse all descendants then yield as AsyncGenerator - * @param controller DataView controller, simulate async filesystem file - */ - protected abstract decodeContentImpl( - options: DecodeContentOptions - ): AsyncGenerator; - - /** - * Wrap of abstract decode content impl function, add before and after lifecircle check - * @param controller DataView controller, simulate async filesystem file - * @returns Deep traversal async iterators of all descendants - */ - public async *decodeContent( - options: DecodeContentOptions - ): AsyncGenerator { - const controller = options.dataViewController; - if (this.contentLength === 0 || this.position === EbmlTagPosition.Start) { - return; - } - const startOffset = controller.getOffset(); - for await (const tag of this.decodeContentImpl(options)) { - yield tag; - } - const endOffset = controller.getOffset(); - if ( - startOffset + this.contentLength !== endOffset && - this.contentLength !== Number.POSITIVE_INFINITY - ) { - throw new InconsistentOffsetOnDecodingContentError(this, endOffset); - } - } - - private getTagDeclaration(): Uint8Array { - let tagHex = this.id.toString(16); - if (tagHex.length % 2 !== 0) { - tagHex = `0${tagHex}`; - } - return hexStringToBuf(tagHex); - } - - public *encodeHeader(): Generator { - const tagEncoded = this.getTagDeclaration(); - yield tagEncoded; - if (this._contentLength === Number.POSITIVE_INFINITY) { - const mayBeSizeLength = this.headerLength - tagEncoded.byteLength; - if (mayBeSizeLength > 0 && mayBeSizeLength <= 8) { - yield UNKNOWN_SIZE_VINT_BUF[mayBeSizeLength]; - } else { - yield UNKNOWN_SIZE_VINT_BUF[2]; - } - } else { - yield writeVint(this._contentLength); - } - } - - public *encode(): Generator { - if (this._contentLength === Number.POSITIVE_INFINITY) { - yield* this.encodeHeader(); - for (const part of this.encodeContent()) { - yield part; - } - } else { - let size = 0; - const parts: Uint8Array[] = []; - for (const part of this.encodeContent()) { - parts.push(part); - size += part.byteLength; - } - this._contentLength = size; - yield* this.encodeHeader(); - for (const part of parts) { - yield part; - } - } - } - - public toDebugRecord(): Record { - return { - id: EbmlTagIdEnum[this.id as any] || this.id, - type: this.type, - position: EbmlTagPosition[this.position], - contentLength: this.contentLength, - headerLength: this.headerLength, - startOffset: this.startOffset, - endOffset: this.endOffset, - }; - } -} +import type { FileDataViewController } from '../adapters'; +import { InconsistentOffsetOnDecodingContentError } from '../errors'; +import { UNKNOWN_SIZE_VINT_BUF, hexStringToBuf, writeVint } from '../tools'; +import { EbmlTagPosition } from './enums'; +import { EbmlTagIdEnum, type EbmlTagIdType } from './enums'; +import type { EbmlElementType } from './enums'; +import type { EbmlMasterTag } from './tag-master'; + +export interface CreateEbmlTagOptions { + id: EbmlTagIdType; + type?: EbmlElementType; + position?: EbmlTagPosition; + headerLength: number; + contentLength: number; + startOffset: number; + endOffset?: number; + parent?: EbmlMasterTag; +} + +export type DecodeContentCollectChildPredicate = + | boolean + | ((child: EbmlTagTrait, parent: EbmlMasterTag) => boolean); + +export interface DecodeContentOptions { + collectChild?: DecodeContentCollectChildPredicate; + dataViewController: FileDataViewController; +} + +export abstract class EbmlTagTrait { + /** + * The id of the EBML tag. + * In most documentation this number is in hexadecimal format + */ + id: EbmlTagIdType; + /** + * The data type of the EBML tag + */ + type?: EbmlElementType; + /** + * The position of this EBML tag. + * Currently, one of "Start", "Content", or "End". + * "Start" and "End" only for Master type + */ + position: EbmlTagPosition; + /** + * Size vint length + tag vint length + */ + headerLength: number; + /** + * Start offset relative to context (stream or file) start + */ + startOffset: number; + /** + * Parent node + */ + parent?: EbmlTagTrait; + + /** + * Content length in ebml data + * Return Number.POSITIVE_INFINITY as "unknown" + */ + private _contentLength: number; + /** + * Caculated end offset when + */ + private _endOffset?: number; + + constructor(options: CreateEbmlTagOptions) { + this.id = options.id; + this.type = options.type; + this.position = options.position ?? EbmlTagPosition.Content; + this.parent = options.parent; + this.startOffset = options.startOffset; + this.headerLength = options.headerLength; + this._contentLength = options.contentLength; + this._endOffset = options.endOffset; + } + + public set contentLength(value: number) { + this._contentLength = value; + } + + /** + * After caculated or known, manually set endOffset + */ + public set endOffset(offset: number) { + this._endOffset = offset; + } + + /** + * End offset relative to context (stream or file) start + * Calcalate from self _contentLength and parent end offset + * Return Number.POSITIVE_INFINITY as "unknown" + */ + public get endOffset(): number { + if (this._endOffset) { + return this._endOffset; + } + if (this._contentLength === Number.POSITIVE_INFINITY) { + return this.parent?.endOffset ?? Number.POSITIVE_INFINITY; + } + return this.startOffset + this.headerLength + this._contentLength; + } + + /** + * Header length + Content Length + * Calcalate from self _contentLength and parent end offset + * Return Number.POSITIVE_INFINITY as "unknown" + */ + public get totalLength(): number { + return this.endOffset - this.startOffset; + } + + /** + * Content Length + * Calcalate from self _contentLength and parent end offset + * Return Number.POSITIVE_INFINITY as "unknown" + */ + public get contentLength(): number { + return this.totalLength - this.headerLength; + } + + protected abstract encodeContent(): Generator; + + /** + * Deep traversal and parse all descendants then yield as AsyncGenerator + * @param controller DataView controller, simulate async filesystem file + */ + protected abstract decodeContentImpl( + options: DecodeContentOptions + ): AsyncGenerator; + + /** + * Wrap of abstract decode content impl function, add before and after lifecircle check + * @param controller DataView controller, simulate async filesystem file + * @returns Deep traversal async iterators of all descendants + */ + public async *decodeContent( + options: DecodeContentOptions + ): AsyncGenerator { + const controller = options.dataViewController; + if (this.contentLength === 0 || this.position === EbmlTagPosition.Start) { + return; + } + const startOffset = controller.getOffset(); + for await (const tag of this.decodeContentImpl(options)) { + yield tag; + } + const endOffset = controller.getOffset(); + if ( + startOffset + this.contentLength !== endOffset && + this.contentLength !== Number.POSITIVE_INFINITY + ) { + throw new InconsistentOffsetOnDecodingContentError(this, endOffset); + } + } + + private getTagDeclaration(): Uint8Array { + let tagHex = this.id.toString(16); + if (tagHex.length % 2 !== 0) { + tagHex = `0${tagHex}`; + } + return hexStringToBuf(tagHex); + } + + public *encodeHeader(): Generator { + const tagEncoded = this.getTagDeclaration(); + yield tagEncoded; + if (this._contentLength === Number.POSITIVE_INFINITY) { + const mayBeSizeLength = this.headerLength - tagEncoded.byteLength; + if (mayBeSizeLength > 0 && mayBeSizeLength <= 8) { + yield UNKNOWN_SIZE_VINT_BUF[mayBeSizeLength]; + } else { + yield UNKNOWN_SIZE_VINT_BUF[2]; + } + } else { + yield writeVint(this._contentLength); + } + } + + public *encode(): Generator { + if (this._contentLength === Number.POSITIVE_INFINITY) { + yield* this.encodeHeader(); + for (const part of this.encodeContent()) { + yield part; + } + } else { + let size = 0; + const parts: Uint8Array[] = []; + for (const part of this.encodeContent()) { + parts.push(part); + size += part.byteLength; + } + this._contentLength = size; + yield* this.encodeHeader(); + for (const part of parts) { + yield part; + } + } + } + + public toDebugRecord(): Record { + return { + id: EbmlTagIdEnum[this.id as any] || this.id, + type: this.type, + position: EbmlTagPosition[this.position], + contentLength: this.contentLength, + headerLength: this.headerLength, + startOffset: this.startOffset, + endOffset: this.endOffset, + }; + } +} diff --git a/src/models/tag.ts b/src/models/tag.ts index a8a85e2..21cc4d1 100644 --- a/src/models/tag.ts +++ b/src/models/tag.ts @@ -23,7 +23,8 @@ export type EbmlTagExcludeField = | 'position' | 'parent' | 'type' - | 'data'; + | 'data' + | 'children'; export type EbmlUintTagType = Omit & { id: EbmlUintDataTagIdType; @@ -31,6 +32,7 @@ export type EbmlUintTagType = Omit & { parent?: EbmlMasterTag; type: EbmlElementType.UnsignedInt; data: number | bigint; + children?: []; }; export type EbmlIntTagType = Omit & { @@ -39,6 +41,7 @@ export type EbmlIntTagType = Omit & { parent?: EbmlMasterTag; type: EbmlElementType.Integer; data: number | bigint; + children?: []; }; export type EbmlUtf8TagType = Omit & { @@ -47,6 +50,7 @@ export type EbmlUtf8TagType = Omit & { parent?: EbmlMasterTag; type: EbmlElementType.UTF8; data: string; + children?: []; }; export type EbmlAsciiTagType = Omit & { @@ -55,6 +59,7 @@ export type EbmlAsciiTagType = Omit & { parent?: EbmlMasterTag; type: EbmlElementType.Ascii; data: string; + children?: []; }; export type EbmlDateTagType = Omit & { @@ -63,6 +68,7 @@ export type EbmlDateTagType = Omit & { parent?: EbmlMasterTag; type: EbmlElementType.Date; data: Uint8Array; + children?: []; }; export type EbmlFloatTagType = Omit & { @@ -71,6 +77,7 @@ export type EbmlFloatTagType = Omit & { parent?: EbmlMasterTag; type: EbmlElementType.Float; data: number; + children?: []; }; export type EbmlBinaryTagType = Omit & { @@ -79,6 +86,7 @@ export type EbmlBinaryTagType = Omit & { parent?: EbmlMasterTag; type: EbmlElementType.Binary; data: Uint8Array; + children?: []; }; export type EbmlUnknownTagType = Omit & { @@ -87,6 +95,7 @@ export type EbmlUnknownTagType = Omit & { parent?: EbmlMasterTag; type?: undefined; data: Uint8Array; + children?: []; }; export type EbmlDataTagType = @@ -104,6 +113,7 @@ export type EbmlBlockTagType = Omit & { parent?: EbmlMasterTag; type?: undefined; data?: undefined; + children?: []; }; export type EbmlSimpleBlockTagType = Omit< @@ -115,6 +125,7 @@ export type EbmlSimpleBlockTagType = Omit< parent?: EbmlMasterTag; type?: undefined; data?: undefined; + children?: []; }; export type EbmlMasterTagType = Omit & { diff --git a/src/tools.ts b/src/tools.ts index a8e2971..329ea1f 100644 --- a/src/tools.ts +++ b/src/tools.ts @@ -1,13 +1,13 @@ import { - VintOutOfRangeError, - VintLengthOutOfRangeError, ElementIdVintDataAllOnesError, ElementIdVintDataAllZerosError, ElementIdVintDataNotShortestError, - UnsupportLengthForElementTypeError, OutOfRangeForElementTypeError, SizeUnitOutOfSafeIntegerRangeError, UnreachableOrLogicError, + UnsupportLengthForElementTypeError, + VintLengthOutOfRangeError, + VintOutOfRangeError, } from './errors'; import { EbmlElementType, diff --git a/tests/decoder.spec.ts b/tests/decoder.spec.ts index 08e71a5..d2dbc06 100644 --- a/tests/decoder.spec.ts +++ b/tests/decoder.spec.ts @@ -1,11 +1,11 @@ -import { assert, describe, it } from 'vitest'; import { - EbmlTagPosition, - EbmlElementType, EbmlStreamDecoder as Decoder, EbmlDataTag, + EbmlElementType, + EbmlTagPosition, type EbmlTagType, } from 'konoebml'; +import { assert, describe, it } from 'vitest'; const bufFrom = (data: Uint8Array | readonly number[]): ArrayBuffer => new Uint8Array(data).buffer; diff --git a/tests/encoder.spec.ts b/tests/encoder.spec.ts index dccaf94..82b3e64 100644 --- a/tests/encoder.spec.ts +++ b/tests/encoder.spec.ts @@ -1,11 +1,11 @@ -import { assert, expect, describe, it } from 'vitest'; import { + EbmlStreamEncoder, + EbmlTagIdEnum, EbmlTagPosition, type EbmlTagTrait, - EbmlTagIdEnum, createEbmlTagForManuallyBuild, - EbmlStreamEncoder, } from 'konoebml'; +import { assert, describe, expect, it } from 'vitest'; const invalidTag: EbmlTagTrait = ({ id: undefined, diff --git a/tests/pipeline.spec.ts b/tests/pipeline.spec.ts index c66d1b4..3902ea8 100644 --- a/tests/pipeline.spec.ts +++ b/tests/pipeline.spec.ts @@ -1,14 +1,14 @@ -import { assert, describe, it, expect } from 'vitest'; import { + type EbmlBlockTag, EbmlStreamDecoder, EbmlStreamEncoder, - type EbmlTagTrait, EbmlTagIdEnum, - type EbmlBlockTag, - createEbmlTagForManuallyBuild, + type EbmlTagTrait, type EbmlTagType, + createEbmlTagForManuallyBuild, } from 'konoebml'; import { concatArrayBuffers } from 'konoebml/tools'; +import { assert, describe, expect, it } from 'vitest'; describe('EBML Pipeline', () => { async function assertPipelineOutputEquals( diff --git a/tests/tools.spec.ts b/tests/tools.spec.ts index df0b45d..74cb2de 100644 --- a/tests/tools.spec.ts +++ b/tests/tools.spec.ts @@ -1,4 +1,3 @@ -import { assert, describe, it } from 'vitest'; import { readAscii, readElementIdVint, @@ -9,6 +8,7 @@ import { readVint, writeVint, } from 'konoebml/tools'; +import { assert, describe, it } from 'vitest'; function bufFrom(data: Uint8Array | readonly number[]): Uint8Array { return new Uint8Array(data); diff --git a/tests/value.spec.ts b/tests/value.spec.ts index f062a4f..ccb952b 100644 --- a/tests/value.spec.ts +++ b/tests/value.spec.ts @@ -1,14 +1,14 @@ 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 { 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); diff --git a/tsconfig.base.json b/tsconfig.base.json index 484e0bd..d28840e 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -1,19 +1,15 @@ { - "compilerOptions": { - "forceConsistentCasingInFileNames": true, - "esModuleInterop": true, - "strict": true, - "skipLibCheck": true, - "noFallthroughCasesInSwitch": true, - "useDefineForClassFields": true, - "resolveJsonModule": true, - "moduleResolution": "bundler", - "target": "ES2021", - "module": "ESNext", - "lib": [ - "ES2021", - "DOM", - "DOM.Iterable" - ] - } -} \ No newline at end of file + "compilerOptions": { + "forceConsistentCasingInFileNames": true, + "esModuleInterop": true, + "strict": true, + "skipLibCheck": true, + "noFallthroughCasesInSwitch": true, + "useDefineForClassFields": true, + "resolveJsonModule": true, + "moduleResolution": "bundler", + "target": "ES2021", + "module": "ESNext", + "lib": ["ES2021", "DOM", "DOM.Iterable"] + } +} diff --git a/tsconfig.example.json b/tsconfig.example.json index f6bf889..9fd7c5b 100644 --- a/tsconfig.example.json +++ b/tsconfig.example.json @@ -1,28 +1,20 @@ { - "extends": "./tsconfig.base.json", - "compilerOptions": { - "composite": true, - "rootDir": ".", - "types": [ - "node" - ], - "noEmit": true, - "paths": { - "konoebml": [ - "./src/index.ts" - ], - "konoebml/*": [ - "./src/*" - ] - } - }, - "files": [], - "include": [ - "examples/*" - ], - "references": [ - { - "path": "./tsconfig.lib.json" - } - ] -} \ No newline at end of file + "extends": "./tsconfig.base.json", + "compilerOptions": { + "composite": true, + "rootDir": ".", + "types": ["node"], + "noEmit": true, + "paths": { + "konoebml": ["./src/index.ts"], + "konoebml/*": ["./src/*"] + } + }, + "files": [], + "include": ["examples/*"], + "references": [ + { + "path": "./tsconfig.lib.json" + } + ] +} diff --git a/tsconfig.json b/tsconfig.json index cb5fadc..1b99600 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -2,9 +2,7 @@ "extends": "./tsconfig.base.json", "files": [], "include": [], - "exclude": [ - "node_modules" - ], + "exclude": ["node_modules"], "references": [ { "path": "./tsconfig.lib.json" @@ -16,4 +14,4 @@ "path": "./tsconfig.example.json" } ] -} \ No newline at end of file +} diff --git a/tsconfig.lib.json b/tsconfig.lib.json index 9ea054a..d327dbe 100644 --- a/tsconfig.lib.json +++ b/tsconfig.lib.json @@ -1,17 +1,15 @@ { - "extends": "./tsconfig.base.json", - "compilerOptions": { - "composite": true, - "rootDir": "./src", - "baseUrl": ".", - "declarationDir": "./dist", - "outDir": "./dist", - "declaration": true, - "declarationMap": true, - "emitDeclarationOnly": true - }, - "include": [ - "src" - ], - "exclude": [] -} \ No newline at end of file + "extends": "./tsconfig.base.json", + "compilerOptions": { + "composite": true, + "rootDir": "./src", + "baseUrl": ".", + "declarationDir": "./dist", + "outDir": "./dist", + "declaration": true, + "declarationMap": true, + "emitDeclarationOnly": true + }, + "include": ["src"], + "exclude": [] +} diff --git a/tsconfig.spec.json b/tsconfig.spec.json index c421382..45103a7 100644 --- a/tsconfig.spec.json +++ b/tsconfig.spec.json @@ -3,27 +3,18 @@ "compilerOptions": { "composite": true, "rootDir": ".", - "types": [ - "vitest/globals", - "node" - ], + "types": ["vitest/globals", "node"], "noEmit": true, "paths": { - "konoebml": [ - "./src/index.ts" - ], - "konoebml/*": [ - "./src/*" - ] + "konoebml": ["./src/index.ts"], + "konoebml/*": ["./src/*"] } }, "files": [], - "include": [ - "tests/*" - ], + "include": ["tests/*"], "references": [ { "path": "./tsconfig.lib.json" } ] -} \ No newline at end of file +}