Skip to content

Commit

Permalink
Remove remaining Buffer usages.
Browse files Browse the repository at this point in the history
Add lint rule to prevent global Buffer usage.
  • Loading branch information
Borewit committed Jul 12, 2024
1 parent 84f234a commit 3f8aa15
Show file tree
Hide file tree
Showing 22 changed files with 131 additions and 102 deletions.
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

0 comments on commit 3f8aa15

Please sign in to comment.