feat: a better type system and type hints that depend on it

This commit is contained in:
master 2025-03-18 02:32:45 +08:00
parent 85eecbf6ac
commit fb58f35a6a
14 changed files with 215 additions and 222 deletions

View File

@ -17,6 +17,7 @@ This package is serving as a fork with extensive rewrites and enhancements to [e
- better [unknown size vint][unknown size vint] support - better [unknown size vint][unknown size vint] support
- bigint support for vint, unsigned and signed int data type - bigint support for vint, unsigned and signed int data type
- better type system and type hints that depend on it
- better error types - better error types
# Install # Install

View File

@ -9,7 +9,11 @@
"noNonNullAssertion": "off", "noNonNullAssertion": "off",
"noParameterAssign": "off", "noParameterAssign": "off",
"useFilenamingConvention": "off", "useFilenamingConvention": "off",
"noParameterProperties": "off" "noParameterProperties": "off",
"useImportType": {
"level": "error",
"fix": "unsafe"
}
}, },
"suspicious": { "suspicious": {
"noExplicitAny": "off" "noExplicitAny": "off"

View File

@ -1,6 +1,6 @@
{ {
"name": "konoebml", "name": "konoebml",
"version": "0.1.0-rc.3", "version": "0.1.0-rc.4",
"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",

View File

@ -7,6 +7,7 @@ import type {
import { decodeEbmlContent } from './decode-utils'; import { decodeEbmlContent } from './decode-utils';
import { StreamFlushReason, UnreachableOrLogicError } from './errors'; 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
@ -18,10 +19,9 @@ export interface EbmlDecodeStreamTransformerOptions {
streamStartOffset?: number; streamStartOffset?: number;
} }
export class EbmlDecodeStreamTransformer export class EbmlDecodeStreamTransformer<
implements E extends EbmlTagType | EbmlTagTrait = EbmlTagType,
Transformer<EbmlStreamDecoderChunkType, EbmlTagTrait>, > implements Transformer<EbmlStreamDecoderChunkType, E>, FileDataViewController
FileDataViewController
{ {
private _offset = 0; private _offset = 0;
private _buffer: Uint8Array = new Uint8Array(0); private _buffer: Uint8Array = new Uint8Array(0);
@ -153,19 +153,19 @@ export class EbmlDecodeStreamTransformer
} }
private waitBufferRelease( private waitBufferRelease(
ctrl: TransformStreamDefaultController<EbmlTagTrait>, ctrl: TransformStreamDefaultController<E>,
isFlush: boolean isFlush: boolean
) { ) {
while (this._writeBuffer.size) { while (this._writeBuffer.size) {
if (ctrl.desiredSize! <= 0 && !isFlush) { if (ctrl.desiredSize! <= 0 && !isFlush) {
break; break;
} }
ctrl.enqueue(this._writeBuffer.dequeue()); ctrl.enqueue(this._writeBuffer.dequeue() as unknown as E);
} }
} }
private async tick( private async tick(
ctrl: TransformStreamDefaultController<EbmlTagTrait>, ctrl: TransformStreamDefaultController<E>,
isFlush: boolean isFlush: boolean
) { ) {
const waitIdle = new Promise<void>((resolve) => { const waitIdle = new Promise<void>((resolve) => {
@ -204,7 +204,7 @@ export class EbmlDecodeStreamTransformer
this.waitBufferRelease(ctrl, isFlush); this.waitBufferRelease(ctrl, isFlush);
} }
async start(ctrl: TransformStreamDefaultController<EbmlTagTrait>) { async start(ctrl: TransformStreamDefaultController<E>) {
this._offset = this.options.streamStartOffset ?? 0; this._offset = this.options.streamStartOffset ?? 0;
this._buffer = new Uint8Array(0); this._buffer = new Uint8Array(0);
this._requests.clear(); this._requests.clear();
@ -215,7 +215,7 @@ export class EbmlDecodeStreamTransformer
async transform( async transform(
chunk: EbmlStreamDecoderChunkType, chunk: EbmlStreamDecoderChunkType,
ctrl: TransformStreamDefaultController<EbmlTagTrait> ctrl: TransformStreamDefaultController<E>
): Promise<void> { ): Promise<void> {
if (chunk.byteLength === 0) { if (chunk.byteLength === 0) {
return; return;
@ -234,7 +234,7 @@ export class EbmlDecodeStreamTransformer
await this.tick(ctrl, false); await this.tick(ctrl, false);
} }
async flush(ctrl: TransformStreamDefaultController<EbmlTagTrait>) { async flush(ctrl: TransformStreamDefaultController<E>) {
await this.tick(ctrl, true); await this.tick(ctrl, true);
} }
} }
@ -242,14 +242,13 @@ export class EbmlDecodeStreamTransformer
export interface EbmlStreamDecoderOptions export interface EbmlStreamDecoderOptions
extends EbmlDecodeStreamTransformerOptions {} extends EbmlDecodeStreamTransformerOptions {}
export class EbmlStreamDecoder extends TransformStream< export class EbmlStreamDecoder<
EbmlStreamDecoderChunkType, E extends EbmlTagType | EbmlTagTrait = EbmlTagType,
EbmlTagTrait > extends TransformStream<EbmlStreamDecoderChunkType, E> {
> { public readonly transformer: EbmlDecodeStreamTransformer<E>;
public readonly transformer: EbmlDecodeStreamTransformer;
constructor(options: EbmlStreamDecoderOptions = {}) { constructor(options: EbmlStreamDecoderOptions = {}) {
const transformer = new EbmlDecodeStreamTransformer(options); const transformer = new EbmlDecodeStreamTransformer<E>(options);
super(transformer); super(transformer);
this.transformer = transformer; this.transformer = transformer;
} }

View File

@ -3,9 +3,10 @@ import { EbmlTagTrait } from './models/tag-trait';
import { EbmlTagPosition } from './models/enums'; import { EbmlTagPosition } from './models/enums';
import { EbmlMasterTag } from './models/tag-master'; import { EbmlMasterTag } from './models/tag-master';
import { EbmlTreeMasterNotMatchError, UnreachableOrLogicError } from './errors'; import { EbmlTreeMasterNotMatchError, UnreachableOrLogicError } from './errors';
import type { EbmlTagType } from './models/tag';
export class EbmlEncodeStreamTransformer export class EbmlEncodeStreamTransformer
implements Transformer<EbmlTagTrait, Uint8Array> implements Transformer<EbmlTagTrait | EbmlTagType, Uint8Array>
{ {
stack = new Stack<[EbmlMasterTag, Uint8Array[]]>(); stack = new Stack<[EbmlMasterTag, Uint8Array[]]>();
_writeBuffer = new Queue<Uint8Array>(); _writeBuffer = new Queue<Uint8Array>();
@ -38,7 +39,7 @@ export class EbmlEncodeStreamTransformer
// biome-ignore lint/complexity/noExcessiveCognitiveComplexity: <explanation> // biome-ignore lint/complexity/noExcessiveCognitiveComplexity: <explanation>
async transform( async transform(
tag: EbmlTagTrait, tag: EbmlTagTrait | EbmlTagType,
ctrl: TransformStreamDefaultController<Uint8Array> ctrl: TransformStreamDefaultController<Uint8Array>
) { ) {
if (!(tag instanceof EbmlTagTrait)) { if (!(tag instanceof EbmlTagTrait)) {
@ -81,7 +82,7 @@ export class EbmlEncodeStreamTransformer
} }
export class EbmlStreamEncoder extends TransformStream< export class EbmlStreamEncoder extends TransformStream<
EbmlTagTrait, EbmlTagTrait | EbmlTagType,
Uint8Array Uint8Array
> { > {
public readonly transformer: EbmlEncodeStreamTransformer; public readonly transformer: EbmlEncodeStreamTransformer;

View File

@ -79,7 +79,7 @@ export function createEbmlTag(arg1: unknown, arg2: unknown): EbmlTagTrait {
} else if (isEbmlFloatDataTagId(id)) { } else if (isEbmlFloatDataTagId(id)) {
foundType = EbmlElementType.Float; foundType = EbmlElementType.Float;
} else if (isEbmlStringDataTagId(id)) { } else if (isEbmlStringDataTagId(id)) {
foundType = EbmlElementType.String; foundType = EbmlElementType.Ascii;
} else if (isEbmlUtf8DataTagId(id)) { } else if (isEbmlUtf8DataTagId(id)) {
foundType = EbmlElementType.UTF8; foundType = EbmlElementType.UTF8;
} else if (isEbmlDateDataTagId(id)) { } else if (isEbmlDateDataTagId(id)) {

View File

@ -49,10 +49,11 @@ export {
type EbmlFloatDataTagIdType, type EbmlFloatDataTagIdType,
type EbmlIntDataTagIdType, type EbmlIntDataTagIdType,
type EbmlSimpleBlockTagIdType, type EbmlSimpleBlockTagIdType,
type EbmlStringDataTagIdType, type EbmlAsciiDataTagIdType as EbmlStringDataTagIdType,
type EbmlUintDataTagIdType, type EbmlUintDataTagIdType,
type EbmlUtf8DataTagIdType, type EbmlUtf8DataTagIdType,
type EbmlTagIdType, type EbmlTagIdType,
type EbmlUnknownTagIdType,
isEbmlBinaryDataTagId, isEbmlBinaryDataTagId,
isEbmlBlockTagId, isEbmlBlockTagId,
isEbmlDateDataTagId, isEbmlDateDataTagId,
@ -63,5 +64,21 @@ export {
isEbmlStringDataTagId, isEbmlStringDataTagId,
isEbmlUintDataTagId, isEbmlUintDataTagId,
isEbmlUtf8DataTagId, isEbmlUtf8DataTagId,
isUnknownDataTagId, isUnknownTagId,
} from './models/enums'; } from './models/enums';
export {
EbmlUnknownTagType,
EbmlUintTagType,
EbmlUtf8TagType,
EbmlBinaryTagType,
EbmlAsciiTagType,
EbmlDateTagType,
EbmlDataTagType,
EbmlFloatTagType,
EbmlIntTagType,
EbmlBlockTagType,
EbmlSimpleBlockTagType,
EbmlMasterTagType,
EbmlTagExcludeField,
EbmlTagType,
} from './models/tag';

View File

@ -2,7 +2,7 @@ export enum EbmlElementType {
Master = 'm', Master = 'm',
UnsignedInt = 'u', UnsignedInt = 'u',
Integer = 'i', Integer = 'i',
String = 's', Ascii = 's',
UTF8 = '8', UTF8 = '8',
Binary = 'b', Binary = 'b',
Float = 'f', Float = 'f',
@ -245,8 +245,6 @@ export enum EbmlTagIdEnum {
EBML = 0x1a45dfa3, EBML = 0x1a45dfa3,
} }
export type EbmlTagIdType = EbmlTagIdEnum | number | bigint;
export type EbmlMasterTagIdType = export type EbmlMasterTagIdType =
| EbmlTagIdEnum.ChapterDisplay | EbmlTagIdEnum.ChapterDisplay
| EbmlTagIdEnum.ContentCompression | EbmlTagIdEnum.ContentCompression
@ -297,185 +295,6 @@ export type EbmlMasterTagIdType =
| EbmlTagIdEnum.SignatureSlot | EbmlTagIdEnum.SignatureSlot
| EbmlTagIdEnum.EBML; | EbmlTagIdEnum.EBML;
export type EbmlDataTagIdType =
| EbmlTagIdEnum.TrackType
| EbmlTagIdEnum.FlagDefault
| EbmlTagIdEnum.ChapterTrackNumber
| EbmlTagIdEnum.ChapterTimeStart
| EbmlTagIdEnum.ChapterTimeEnd
| EbmlTagIdEnum.CueRefTime
| EbmlTagIdEnum.CueRefCluster
| EbmlTagIdEnum.ChapterFlagHidden
| EbmlTagIdEnum.ContentCompAlgo
| EbmlTagIdEnum.DocTypeReadVersion
| EbmlTagIdEnum.EBMLVersion
| EbmlTagIdEnum.DocTypeVersion
| EbmlTagIdEnum.TagDefault
| EbmlTagIdEnum.ChapterFlagEnabled
| EbmlTagIdEnum.FileUsedStartTime
| EbmlTagIdEnum.FileUsedEndTime
| EbmlTagIdEnum.ContentEncodingOrder
| EbmlTagIdEnum.ContentEncodingScope
| EbmlTagIdEnum.ContentEncodingType
| EbmlTagIdEnum.CueBlockNumber
| EbmlTagIdEnum.BitDepth
| EbmlTagIdEnum.ChapProcessTime
| EbmlTagIdEnum.ChapProcessCodecID
| EbmlTagIdEnum.AttachmentLink
| EbmlTagIdEnum.TagAttachmentUID
| EbmlTagIdEnum.TagChapterUID
| EbmlTagIdEnum.TagEditionUID
| EbmlTagIdEnum.TagTrackUID
| EbmlTagIdEnum.TargetTypeValue
| EbmlTagIdEnum.ChapterPhysicalEquiv
| EbmlTagIdEnum.ChapterSegmentEditionUID
| EbmlTagIdEnum.ChapterUID
| EbmlTagIdEnum.EditionFlagOrdered
| EbmlTagIdEnum.EditionFlagDefault
| EbmlTagIdEnum.EditionFlagHidden
| EbmlTagIdEnum.EditionUID
| EbmlTagIdEnum.FileUID
| EbmlTagIdEnum.CueRefCodecState
| EbmlTagIdEnum.CueRefNumber
| EbmlTagIdEnum.CueCodecState
| EbmlTagIdEnum.CueDuration
| EbmlTagIdEnum.CueRelativePosition
| EbmlTagIdEnum.CueClusterPosition
| EbmlTagIdEnum.CueTrack
| EbmlTagIdEnum.CueTime
| EbmlTagIdEnum.AESSettingsCipherMode
| EbmlTagIdEnum.ContentSigHashAlgo
| EbmlTagIdEnum.ContentSigAlgo
| EbmlTagIdEnum.ContentEncAlgo
| EbmlTagIdEnum.TrickMasterTrackUID
| EbmlTagIdEnum.TrickTrackFlag
| EbmlTagIdEnum.TrickTrackUID
| EbmlTagIdEnum.TrackJoinUID
| EbmlTagIdEnum.TrackPlaneType
| EbmlTagIdEnum.TrackPlaneUID
| EbmlTagIdEnum.Channels
| EbmlTagIdEnum.AspectRatioType
| EbmlTagIdEnum.DisplayUnit
| EbmlTagIdEnum.DisplayHeight
| EbmlTagIdEnum.DisplayWidth
| EbmlTagIdEnum.PixelCropRight
| EbmlTagIdEnum.PixelCropLeft
| EbmlTagIdEnum.PixelCropTop
| EbmlTagIdEnum.PixelCropBottom
| EbmlTagIdEnum.PixelHeight
| EbmlTagIdEnum.PixelWidth
| EbmlTagIdEnum.OldStereoMode
| EbmlTagIdEnum.AlphaMode
| EbmlTagIdEnum.StereoMode
| EbmlTagIdEnum.FlagInterlaced
| EbmlTagIdEnum.TrackTranslateCodec
| EbmlTagIdEnum.TrackTranslateEditionUID
| EbmlTagIdEnum.SeekPreRoll
| EbmlTagIdEnum.CodecDelay
| EbmlTagIdEnum.TrackOverlay
| EbmlTagIdEnum.CodecDecodeAll
| EbmlTagIdEnum.MaxBlockAdditionID
| EbmlTagIdEnum.DefaultDecodedFieldDuration
| EbmlTagIdEnum.DefaultDuration
| EbmlTagIdEnum.MaxCache
| EbmlTagIdEnum.MinCache
| EbmlTagIdEnum.FlagLacing
| EbmlTagIdEnum.FlagForced
| EbmlTagIdEnum.FlagEnabled
| EbmlTagIdEnum.TrackUID
| EbmlTagIdEnum.TrackNumber
| EbmlTagIdEnum.ReferenceTimeCode
| EbmlTagIdEnum.ReferenceOffset
| EbmlTagIdEnum.SliceDuration
| EbmlTagIdEnum.Delay
| EbmlTagIdEnum.BlockAdditionID
| EbmlTagIdEnum.FrameNumber
| EbmlTagIdEnum.LaceNumber
| EbmlTagIdEnum.ReferencePriority
| EbmlTagIdEnum.BlockDuration
| EbmlTagIdEnum.BlockAddID
| EbmlTagIdEnum.PrevSize
| EbmlTagIdEnum.Position
| EbmlTagIdEnum.SilentTrackNumber
| EbmlTagIdEnum.Timecode
| EbmlTagIdEnum.TimecodeScaleDenominator
| EbmlTagIdEnum.TimecodeScale
| EbmlTagIdEnum.ChapterTranslateCodec
| EbmlTagIdEnum.ChapterTranslateEditionUID
| EbmlTagIdEnum.SeekPosition
| EbmlTagIdEnum.SignatureHash
| EbmlTagIdEnum.SignatureAlgo
| EbmlTagIdEnum.EBMLMaxSizeLength
| EbmlTagIdEnum.EBMLMaxIDLength
| EbmlTagIdEnum.EBMLReadVersion
| EbmlTagIdEnum.TrackOffset
| EbmlTagIdEnum.DiscardPadding
| EbmlTagIdEnum.ReferenceVirtual
| EbmlTagIdEnum.ReferenceBlock
| EbmlTagIdEnum.CodecID
| EbmlTagIdEnum.DocType
| EbmlTagIdEnum.FileMimeType
| EbmlTagIdEnum.TagLanguage
| EbmlTagIdEnum.TargetType
| EbmlTagIdEnum.ChapCountry
| EbmlTagIdEnum.ChapLanguage
| EbmlTagIdEnum.CodecDownloadURL
| EbmlTagIdEnum.CodecInfoURL
| EbmlTagIdEnum.Language
| EbmlTagIdEnum.ChapString
| EbmlTagIdEnum.TagString
| EbmlTagIdEnum.ChapterStringUID
| EbmlTagIdEnum.WritingApp
| EbmlTagIdEnum.SegmentFilename
| EbmlTagIdEnum.CodecName
| EbmlTagIdEnum.TagName
| EbmlTagIdEnum.FileName
| EbmlTagIdEnum.FileDescription
| EbmlTagIdEnum.CodecSettings
| EbmlTagIdEnum.Name
| EbmlTagIdEnum.MuxingApp
| EbmlTagIdEnum.Title
| EbmlTagIdEnum.NextFilename
| EbmlTagIdEnum.PrevFilename
| EbmlTagIdEnum.ContentCompSettings
| EbmlTagIdEnum.SegmentFamily
| EbmlTagIdEnum.TagBinary
| EbmlTagIdEnum.FileReferral
| EbmlTagIdEnum.SignedElement
| EbmlTagIdEnum.ChapProcessData
| EbmlTagIdEnum.ChapProcessPrivate
| EbmlTagIdEnum.ChapterSegmentUID
| EbmlTagIdEnum.FileData
| EbmlTagIdEnum.ContentSigKeyID
| EbmlTagIdEnum.ContentSignature
| EbmlTagIdEnum.ContentEncKeyID
| EbmlTagIdEnum.TrickMasterTrackSegmentUID
| EbmlTagIdEnum.TrickTrackSegmentUID
| EbmlTagIdEnum.ChannelPositions
| EbmlTagIdEnum.ColourSpace
| EbmlTagIdEnum.TrackTranslateTrackID
| EbmlTagIdEnum.CodecPrivate
| EbmlTagIdEnum.EncryptedBlock
| EbmlTagIdEnum.CodecState
| EbmlTagIdEnum.BlockAdditional
| EbmlTagIdEnum.BlockVirtual
| EbmlTagIdEnum.ChapterTranslateID
| EbmlTagIdEnum.NextUID
| EbmlTagIdEnum.PrevUID
| EbmlTagIdEnum.SegmentUID
| EbmlTagIdEnum.SeekID
| EbmlTagIdEnum.Signature
| EbmlTagIdEnum.SignaturePublicKey
| EbmlTagIdEnum.CRC32
| EbmlTagIdEnum.Void
| EbmlTagIdEnum.Duration
| EbmlTagIdEnum.OutputSamplingFrequency
| EbmlTagIdEnum.SamplingFrequency
| EbmlTagIdEnum.FrameRate
| EbmlTagIdEnum.GammaValue
| EbmlTagIdEnum.TrackTimecodeScale
| EbmlTagIdEnum.DateUTC;
export type EbmlBlockTagIdType = EbmlTagIdEnum.Block; export type EbmlBlockTagIdType = EbmlTagIdEnum.Block;
export type EbmlSimpleBlockTagIdType = EbmlTagIdEnum.SimpleBlock; export type EbmlSimpleBlockTagIdType = EbmlTagIdEnum.SimpleBlock;
@ -598,7 +417,7 @@ export type EbmlIntDataTagIdType =
| EbmlTagIdEnum.ReferenceVirtual | EbmlTagIdEnum.ReferenceVirtual
| EbmlTagIdEnum.ReferenceBlock; | EbmlTagIdEnum.ReferenceBlock;
export type EbmlStringDataTagIdType = export type EbmlAsciiDataTagIdType =
| EbmlTagIdEnum.CodecID | EbmlTagIdEnum.CodecID
| EbmlTagIdEnum.DocType | EbmlTagIdEnum.DocType
| EbmlTagIdEnum.FileMimeType | EbmlTagIdEnum.FileMimeType
@ -670,6 +489,24 @@ export type EbmlBinaryDataTagIdType =
| EbmlTagIdEnum.CRC32 | EbmlTagIdEnum.CRC32
| EbmlTagIdEnum.Void; | EbmlTagIdEnum.Void;
export type EbmlUnknownTagIdType = number | bigint;
export type EbmlDataTagIdType =
| EbmlBinaryDataTagIdType
| EbmlIntDataTagIdType
| EbmlUintDataTagIdType
| EbmlDateDataTagIdType
| EbmlFloatDataTagIdType
| EbmlAsciiDataTagIdType
| EbmlUtf8DataTagIdType;
export type EbmlTagIdType =
| EbmlMasterTagIdType
| EbmlBlockTagIdType
| EbmlSimpleBlockTagIdType
| EbmlDataTagIdType
| EbmlUnknownTagIdType;
export function isEbmlMasterTagId( export function isEbmlMasterTagId(
tagId: EbmlTagIdType tagId: EbmlTagIdType
): tagId is EbmlMasterTagIdType { ): tagId is EbmlMasterTagIdType {
@ -892,7 +729,7 @@ export function isEbmlFloatDataTagId(
export function isEbmlStringDataTagId( export function isEbmlStringDataTagId(
tagId: EbmlTagIdType tagId: EbmlTagIdType
): tagId is EbmlStringDataTagIdType { ): tagId is EbmlAsciiDataTagIdType {
switch (tagId) { switch (tagId) {
case EbmlTagIdEnum.CodecID: case EbmlTagIdEnum.CodecID:
case EbmlTagIdEnum.DocType: case EbmlTagIdEnum.DocType:
@ -982,10 +819,10 @@ export function isEbmlBinaryDataTagId(
} }
} }
export function isUnknownDataTagId( export function isUnknownTagId(
tagId: EbmlDataTagIdType tagId: EbmlDataTagIdType
): tagId is Exclude<EbmlDataTagIdType, EbmlTagIdEnum> { ): tagId is Exclude<EbmlDataTagIdType, EbmlTagIdEnum> {
return tagId in EbmlTagIdEnum; return !(tagId in EbmlTagIdEnum);
} }
export enum EbmlBlockLacing { export enum EbmlBlockLacing {
None = 1, None = 1,

View File

@ -46,7 +46,7 @@ export class EbmlDataTag extends EbmlTagTrait {
case EbmlElementType.Integer: case EbmlElementType.Integer:
this.data = readSigned(view); this.data = readSigned(view);
break; break;
case EbmlElementType.String: case EbmlElementType.Ascii:
this.data = readAscii(view); this.data = readAscii(view);
break; break;
case EbmlElementType.UTF8: case EbmlElementType.UTF8:
@ -70,7 +70,7 @@ export class EbmlDataTag extends EbmlTagTrait {
case EbmlElementType.Integer: case EbmlElementType.Integer:
yield writeSigned(this.data as any); yield writeSigned(this.data as any);
break; break;
case EbmlElementType.String: case EbmlElementType.Ascii:
yield writeAscii(this.data as any); yield writeAscii(this.data as any);
break; break;
case EbmlElementType.UTF8: case EbmlElementType.UTF8:

View File

@ -14,7 +14,7 @@ export interface CreateEbmlTagOptions {
contentLength: number; contentLength: number;
startOffset: number; startOffset: number;
endOffset?: number; endOffset?: number;
parent?: EbmlTagTrait; parent?: EbmlMasterTag;
} }
export type DecodeContentCollectChildPredicate = export type DecodeContentCollectChildPredicate =

133
src/models/tag.ts Normal file
View File

@ -0,0 +1,133 @@
import type {
EbmlAsciiDataTagIdType,
EbmlBinaryDataTagIdType,
EbmlBlockTagIdType,
EbmlDateDataTagIdType,
EbmlElementType,
EbmlFloatDataTagIdType,
EbmlIntDataTagIdType,
EbmlMasterTagIdType,
EbmlSimpleBlockTagIdType,
EbmlTagPosition,
EbmlUintDataTagIdType,
EbmlUnknownTagIdType,
EbmlUtf8DataTagIdType,
} from './enums';
import type { EbmlBlockTag } from './tag-block';
import type { EbmlDataTag } from './tag-data';
import type { EbmlMasterTag } from './tag-master';
import type { EbmlSimpleBlockTag } from './tag-simple-block';
export type EbmlTagExcludeField =
| 'id'
| 'position'
| 'parent'
| 'type'
| 'data';
export type EbmlUintTagType = Omit<EbmlDataTag, EbmlTagExcludeField> & {
id: EbmlUintDataTagIdType;
position: EbmlTagPosition.Content;
parent?: EbmlMasterTag;
type: EbmlElementType.UnsignedInt;
data: number | bigint;
};
export type EbmlIntTagType = Omit<EbmlDataTag, EbmlTagExcludeField> & {
id: EbmlIntDataTagIdType;
position: EbmlTagPosition.Content;
parent?: EbmlMasterTag;
type: EbmlElementType.Integer;
data: number | bigint;
};
export type EbmlUtf8TagType = Omit<EbmlDataTag, EbmlTagExcludeField> & {
id: EbmlUtf8DataTagIdType;
position: EbmlTagPosition.Content;
parent?: EbmlMasterTag;
type: EbmlElementType.UTF8;
data: string;
};
export type EbmlAsciiTagType = Omit<EbmlDataTag, EbmlTagExcludeField> & {
id: EbmlAsciiDataTagIdType;
position: EbmlTagPosition.Content;
parent?: EbmlMasterTag;
type: EbmlElementType.Ascii;
data: string;
};
export type EbmlDateTagType = Omit<EbmlDataTag, EbmlTagExcludeField> & {
id: EbmlDateDataTagIdType;
position: EbmlTagPosition.Content;
parent?: EbmlMasterTag;
type: EbmlElementType.Date;
data: Uint8Array;
};
export type EbmlFloatTagType = Omit<EbmlDataTag, EbmlTagExcludeField> & {
id: EbmlFloatDataTagIdType;
position: EbmlTagPosition.Content;
parent?: EbmlMasterTag;
type: EbmlElementType.Float;
data: number;
};
export type EbmlBinaryTagType = Omit<EbmlDataTag, EbmlTagExcludeField> & {
id: EbmlBinaryDataTagIdType;
position: EbmlTagPosition.Content;
parent?: EbmlMasterTag;
type: EbmlElementType.Binary;
data: Uint8Array;
};
export type EbmlUnknownTagType = Omit<EbmlDataTag, EbmlTagExcludeField> & {
id: EbmlUnknownTagIdType;
position: EbmlTagPosition.Content;
parent?: EbmlMasterTag;
type?: undefined;
data: Uint8Array;
};
export type EbmlDataTagType =
| EbmlAsciiTagType
| EbmlBinaryTagType
| EbmlUintTagType
| EbmlIntTagType
| EbmlFloatTagType
| EbmlDateTagType
| EbmlUtf8TagType;
export type EbmlBlockTagType = Omit<EbmlBlockTag, EbmlTagExcludeField> & {
id: EbmlBlockTagIdType;
position: EbmlTagPosition.Content;
parent?: EbmlMasterTag;
type?: undefined;
data?: undefined;
};
export type EbmlSimpleBlockTagType = Omit<
EbmlSimpleBlockTag,
EbmlTagExcludeField
> & {
id: EbmlSimpleBlockTagIdType;
position: EbmlTagPosition.Content;
parent?: EbmlMasterTag;
type?: undefined;
data?: undefined;
};
export type EbmlMasterTagType = Omit<EbmlMasterTag, EbmlTagExcludeField> & {
id: EbmlMasterTagIdType;
type: EbmlElementType.Master;
position: EbmlTagPosition.Start | EbmlTagPosition.End;
parent?: EbmlMasterTag;
children: EbmlTagType[];
data?: undefined;
};
export type EbmlTagType =
| EbmlMasterTagType
| EbmlSimpleBlockTagType
| EbmlBlockTagType
| EbmlDataTagType;

View File

@ -4,7 +4,7 @@ import {
EbmlElementType, EbmlElementType,
EbmlStreamDecoder as Decoder, EbmlStreamDecoder as Decoder,
EbmlDataTag, EbmlDataTag,
type EbmlTagTrait, type EbmlTagType,
} from 'konoebml'; } from 'konoebml';
const bufFrom = (data: Uint8Array | readonly number[]): ArrayBuffer => const bufFrom = (data: Uint8Array | readonly number[]): ArrayBuffer =>
@ -16,8 +16,8 @@ const getDecoderWithNullSink = () => {
return decoder; return decoder;
}; };
async function collectTags(decoder: Decoder): Promise<EbmlTagTrait[]> { async function collectTags(decoder: Decoder): Promise<EbmlTagType[]> {
const tags: EbmlTagTrait[] = []; const tags: EbmlTagType[] = [];
await decoder.readable.pipeTo( await decoder.readable.pipeTo(
new WritableStream({ new WritableStream({
write: (tag) => { write: (tag) => {

View File

@ -6,6 +6,7 @@ import {
EbmlTagIdEnum, EbmlTagIdEnum,
type EbmlBlockTag, type EbmlBlockTag,
createEbmlTagForManuallyBuild, createEbmlTagForManuallyBuild,
type EbmlTagType,
} from 'konoebml'; } from 'konoebml';
import { concatArrayBuffers } from 'konoebml/tools'; import { concatArrayBuffers } from 'konoebml/tools';
@ -69,7 +70,7 @@ describe('EBML Pipeline', () => {
block.payload = payload; block.payload = payload;
const encoder = new EbmlStreamEncoder(); const encoder = new EbmlStreamEncoder();
const decoder = new EbmlStreamDecoder(); const decoder = new EbmlStreamDecoder();
const tags: EbmlTagTrait[] = []; const tags: EbmlTagType[] = [];
await new Promise<void>((resolve, reject) => { await new Promise<void>((resolve, reject) => {
const source = new ReadableStream<EbmlTagTrait>({ const source = new ReadableStream<EbmlTagTrait>({
pull(controller) { pull(controller) {
@ -81,7 +82,7 @@ describe('EBML Pipeline', () => {
.pipeThrough(encoder) .pipeThrough(encoder)
.pipeThrough(decoder) .pipeThrough(decoder)
.pipeTo( .pipeTo(
new WritableStream<EbmlTagTrait>({ new WritableStream({
write(tag) { write(tag) {
tags.push(tag); tags.push(tag);
}, },

View File

@ -5,7 +5,7 @@ import {
EbmlTagIdEnum, EbmlTagIdEnum,
EbmlSimpleBlockTag as SimpleBlock, EbmlSimpleBlockTag as SimpleBlock,
EbmlDataTag, EbmlDataTag,
type EbmlMasterTag, type EbmlTagType,
} from 'konoebml'; } from 'konoebml';
import { Readable } from 'node:stream'; import { Readable } from 'node:stream';
import { WritableStream } from 'node:stream/web'; import { WritableStream } from 'node:stream/web';
@ -19,14 +19,14 @@ const createReadStream = (file: string) =>
const makeDataStreamTest = const makeDataStreamTest =
(stream: () => ReadableStream<Uint8Array>) => (stream: () => ReadableStream<Uint8Array>) =>
async (cb: (tag: EbmlMasterTag | EbmlDataTag, done: () => void) => void) => { async (cb: (tag: EbmlTagType, done: () => void) => void) => {
await new Promise((resolve, reject) => { await new Promise((resolve, reject) => {
stream() stream()
.pipeThrough(new EbmlStreamDecoder()) .pipeThrough(new EbmlStreamDecoder())
.pipeTo( .pipeTo(
new WritableStream({ new WritableStream({
write: async (tag) => { write: async (tag) => {
cb(tag as EbmlMasterTag | EbmlDataTag, () => resolve(true)); cb(tag, () => resolve(true));
}, },
close: () => { close: () => {
reject('hit end of file without calling done'); reject('hit end of file without calling done');
@ -75,7 +75,7 @@ describe('EBML Values in tags', () => {
it('should get a correct TrackUID value from a file (56-bit integer in hex)', () => it('should get a correct TrackUID value from a file (56-bit integer in hex)', () =>
makeAVC1StreamTest((tag, done) => { makeAVC1StreamTest((tag, done) => {
if (tag instanceof EbmlDataTag && tag.id === EbmlTagIdEnum.TrackUID) { if (tag.id === EbmlTagIdEnum.TrackUID) {
assert.strictEqual(tag.data, 7990710658693702); assert.strictEqual(tag.data, 7990710658693702);
done(); done();
} }