Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove remaining Node.js Buffer dependencies #2142

Merged
merged 1 commit into from
Jul 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions .eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,14 @@
},
"Symbol": {
"message": "Avoid using the `Symbol` type. Did you mean `symbol`?"
},
"Buffer": {
"message": "Do not use Node.js specific Buffer type, use Uint8Array"
}
}
}
],

"@typescript-eslint/consistent-type-assertions": "error",
"@typescript-eslint/dot-notation": "error",
"@typescript-eslint/indent": [
Expand Down Expand Up @@ -176,11 +180,11 @@
"no-new-wrappers": "error",
"no-redeclare": "error",
"no-return-await": "error",
"no-restricted-syntax": [
"no-restricted-globals": ["error", "Buffer"],
"no-restricted-imports": [
"error",
{
"selector": "CallExpression[callee.object.name='Buffer'][callee.property.name='from']",
"message": "Use of Buffer.from is forbidden."
"paths": ["node:buffer"]
}
],
"no-sequences": "error",
Expand Down
4 changes: 2 additions & 2 deletions lib/common/RandomFileReader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,13 @@ export class RandomFileReader implements IRandomReader {

/**
* Read from a given position of an abstracted file or buffer.
* @param buffer {Buffer} is the buffer that the data will be written to.
* @param buffer {Uint8Array} is the buffer that the data will be written to.
* @param offset {number} is the offset in the buffer to start writing at.
* @param length {number}is an integer specifying the number of bytes to read.
* @param position {number} is an argument specifying where to begin reading from in the file.
* @return {Promise<number>} bytes read
*/
public async randomRead(buffer: Buffer, offset: number, length: number, position: number): Promise<number> {
public async randomRead(buffer: Uint8Array, offset: number, length: number, position: number): Promise<number> {
const result = await this.fileHandle.read(buffer, offset, length, position);
return result.bytesRead;
}
Expand Down
2 changes: 1 addition & 1 deletion lib/dsf/DsfChunk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ export interface IFormatChunk {
export const FormatChunk: IGetToken<IFormatChunk> = {
len: 40,

get: (buf: Buffer, off: number): IFormatChunk => {
get: (buf: Uint8Array, off: number): IFormatChunk => {
return {
formatVersion: Token.INT32_LE.get(buf, off),
formatID: Token.INT32_LE.get(buf, off + 4),
Expand Down
4 changes: 2 additions & 2 deletions lib/flac/FlacParser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ class Metadata {
public static BlockHeader: IGetToken<IBlockHeader> = {
len: 4,

get: (buf: Buffer, off: number): IBlockHeader => {
get: (buf: Uint8Array, off: number): IBlockHeader => {
return {
lastBlock: util.getBit(buf, off, 7),
type: util.getBitAllignedNumber(buf, off, 1, 7),
Expand All @@ -207,7 +207,7 @@ class Metadata {
public static BlockStreamInfo: IGetToken<IBlockStreamInfo> = {
len: 34,

get: (buf: Buffer, off: number): IBlockStreamInfo => {
get: (buf: Uint8Array, off: number): IBlockStreamInfo => {
return {
// The minimum block size (in samples) used in the stream.
minimumBlockSize: UINT16_BE.get(buf, off),
Expand Down
4 changes: 2 additions & 2 deletions lib/id3v1/ID3v1Parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -155,9 +155,9 @@ export class ID3v1Parser extends BasicParser {

export async function hasID3v1Header(reader: IRandomReader): Promise<boolean> {
if (reader.fileSize >= 128) {
const tag = Buffer.alloc(3);
const tag = new Uint8Array(3);
await reader.randomRead(tag, 0, tag.length, reader.fileSize - 128);
return tag.toString('latin1') === 'TAG';
return new TextDecoder('latin1').decode(tag) === 'TAG';
}
return false;
}
2 changes: 1 addition & 1 deletion lib/id3v2/ID3v2Token.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ export interface IID3v2header {
export const ID3v2Header: IGetToken<IID3v2header> = {
len: 10,

get: (buf: Buffer, off): IID3v2header => {
get: (buf: Uint8Array, off): IID3v2header => {
return {
// ID3v2/file identifier "ID3"
fileIdentifier: new Token.StringType(3, 'ascii').get(buf, off),
Expand Down
8 changes: 4 additions & 4 deletions lib/lyrics3/Lyrics3.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@ export const endTag2 = 'LYRICS200';

export async function getLyricsHeaderLength(reader: IRandomReader): Promise<number> {
if (reader.fileSize >= 143) {
const buf = Buffer.alloc(15);
const buf = new Uint8Array(15);
await reader.randomRead(buf, 0, buf.length, reader.fileSize - 143);
const txt = buf.toString('latin1');
const tag = txt.substr(6);
const txt = new TextDecoder('latin1').decode(buf);
const tag = txt.slice(6);
if (tag === endTag2) {
return parseInt(txt.substr(0, 6), 10) + 15;
return parseInt(txt.slice(0, 6), 10) + 15;
}
}
return 0;
Expand Down
54 changes: 32 additions & 22 deletions lib/matroska/MatroskaParser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { DataType, IContainerType, IHeader, IMatroskaDoc, ITree, TargetType, Tra

import { IOptions, ITrackInfo } from '../type.js';
import { ITokenParser } from '../ParserFactory.js';
import * as Token from 'token-types';

const debug = initDebug('music-metadata:parser:matroska');

Expand All @@ -33,7 +34,7 @@ export class MatroskaParser extends BasicParser {
this.parserMap.set(DataType.uint, e => this.readUint(e));
this.parserMap.set(DataType.string, e => this.readString(e));
this.parserMap.set(DataType.binary, e => this.readBuffer(e));
this.parserMap.set(DataType.uid, async e => await this.readUint(e) === 1);
this.parserMap.set(DataType.uid, async e => this.readBuffer(e));
this.parserMap.set(DataType.bool, e => this.readFlag(e));
this.parserMap.set(DataType.float, e => this.readFloat(e));
}
Expand All @@ -57,11 +58,11 @@ export class MatroskaParser extends BasicParser {

const info = matroska.segment.info;
if (info) {
const timecodeScale = info.timecodeScale ? info.timecodeScale : 1000000;
const timecodeScale = info.timecodeScale ? info.timecodeScale :1000000;
if (typeof info.duration === 'number') {
const duration = info.duration * timecodeScale / 1000000000;
await this.addTag('segment:title', info.title);
this.metadata.setFormat('duration', duration);
this.metadata.setFormat('duration', Number(duration));
}
}

Expand Down Expand Up @@ -176,7 +177,7 @@ export class MatroskaParser extends BasicParser {
return tree;
}

private async readVintData(maxLength: number): Promise<Buffer> {
private async readVintData(maxLength: number): Promise<Uint8Array> {
const msb = await this.tokenizer.peekNumber(UINT8);
let mask = 0x80;
let oc = 1;
Expand All @@ -189,7 +190,7 @@ export class MatroskaParser extends BasicParser {
++oc;
mask >>= 1;
}
const id = Buffer.alloc(oc);
const id = new Uint8Array(oc);
await this.tokenizer.readBuffer(id);
return id;
}
Expand All @@ -198,23 +199,12 @@ export class MatroskaParser extends BasicParser {
const id = await this.readVintData(this.ebmlMaxIDLength);
const lenField = await this.readVintData(this.ebmlMaxSizeLength);
lenField[0] ^= 0x80 >> (lenField.length - 1);
const nrLen = Math.min(6, lenField.length); // JavaScript can max read 6 bytes integer
return {
id: id.readUIntBE(0, id.length),
len: lenField.readUIntBE(lenField.length - nrLen, nrLen)
id: MatroskaParser.readUIntBE(id, id.length),
len: MatroskaParser.readUIntBE(lenField, lenField.length)
};
}

private isMaxValue(vintData: Buffer) {
if (vintData.length === this.ebmlMaxSizeLength) {
for (let n = 1; n < this.ebmlMaxSizeLength; ++n) {
if (vintData[n] !== 0xff) return false;
}
return true;
}
return false;
}

private async readFloat(e: IHeader) {
switch (e.len) {
case 0:
Expand All @@ -236,22 +226,42 @@ export class MatroskaParser extends BasicParser {

private async readUint(e: IHeader): Promise<number> {
const buf = await this.readBuffer(e);
const nrLen = Math.min(6, e.len); // JavaScript can max read 6 bytes integer
return buf.readUIntBE(e.len - nrLen, nrLen);
return MatroskaParser.readUIntBE(buf, e.len);
}

private async readString(e: IHeader): Promise<string> {
const rawString = await this.tokenizer.readToken(new StringType(e.len, 'utf-8'));
return rawString.replace(/\x00.*$/g, '');
}

private async readBuffer(e: IHeader): Promise<Buffer> {
const buf = Buffer.alloc(e.len);
private async readBuffer(e: IHeader): Promise<Uint8Array> {
const buf = new Uint8Array(e.len);
await this.tokenizer.readBuffer(buf);
return buf;
}

private async addTag(tagId: string, value: any): Promise<void> {
await this.metadata.addTag('matroska', tagId, value);
}

private static readUIntBE(buf: Uint8Array, len: number): number {
return Number(MatroskaParser.readUIntBeAsBigInt(buf, len));
}

/**
* Reeds an unsigned integer from a big endian buffer of length `len`
* @param buf Buffer to decode from
* @param len Number of bytes
* @private
*/
private static readUIntBeAsBigInt(buf: Uint8Array, len: number): bigint {
const normalizedNumber = new Uint8Array(8);
const cleanNumber = buf.subarray(0, len);
try {
normalizedNumber.set(cleanNumber, 8 - len);
return Token.UINT64_BE.get(normalizedNumber, 0);
} catch(error) {
return BigInt(-1);
}
}
}
26 changes: 13 additions & 13 deletions lib/matroska/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,12 @@ export interface IElementType<T> {
readonly multiple?: boolean;
}

export interface IContainerType { [id: number]: IElementType<string | number | boolean | Buffer>; }
export interface IContainerType { [id: number]: IElementType<string | number | boolean | Uint8Array>; }

export interface ITree { [name: string]: string | number | boolean | Buffer | ITree | ITree[]; }
export interface ITree { [name: string]: string | number | boolean | Uint8Array | ITree | ITree[]; }

export interface ISeekHead {
id?: Buffer;
id?: Uint8Array;
position?: number;
}

Expand All @@ -26,7 +26,7 @@ export interface IMetaSeekInformation {
}

export interface ISegmentInformation {
uid?: Buffer;
uid?: Uint8Array;
timecodeScale?: number;
duration?: number;
dateUTC?: number;
Expand All @@ -36,7 +36,7 @@ export interface ISegmentInformation {
}

export interface ITrackEntry {
uid?: Buffer;
uid?: Uint8Array;
trackNumber?: number;
trackType?: TrackType;
audio?: ITrackAudio;
Expand All @@ -49,7 +49,7 @@ export interface ITrackEntry {
name?: string;
language?: string;
codecID?: string;
codecPrivate?: Buffer;
codecPrivate?: Uint8Array;
codecName?: string;
codecSettings?: string;
codecInfoUrl?: string;
Expand All @@ -67,15 +67,15 @@ export interface ITrackVideo {
displayHeight?: number;
displayUnit?: number;
aspectRatioType?: number;
colourSpace?: Buffer;
colourSpace?: Uint8Array;
gammaValue?: number;
}

export interface ITrackAudio {
samplingFrequency?: number;
outputSamplingFrequency?: number;
channels?: number;
channelPositions?: Buffer;
channelPositions?: Uint8Array;
bitDepth?: number;
}

Expand All @@ -102,7 +102,7 @@ export interface ICueReference {
export interface ISimpleTag {
name?: string;
'string'?: string;
binary?: Buffer;
binary?: Uint8Array;
language?: string;
default?: boolean;
}
Expand All @@ -128,9 +128,9 @@ export enum TrackType {
}

export interface ITarget {
trackUID?: Buffer;
chapterUID?: Buffer;
attachmentUID?: Buffer;
trackUID?: Uint8Array;
chapterUID?: Uint8Array;
attachmentUID?: Uint8Array;
targetTypeValue?: TargetType;
targetType?: string;
}
Expand All @@ -152,7 +152,7 @@ export interface IAttachmedFile {
description?: string;
name: string;
mimeType: string;
data: Buffer;
data: Uint8Array;
uid: string;
}

Expand Down
Loading
Loading