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

Convert most Buffer usage to Uint8Array #2103

Merged
merged 21 commits into from
Jul 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
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
36 changes: 17 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -105,28 +105,26 @@ import * as mm from 'music-metadata/lib/core';
Dependency diagram:
```mermaid
graph TD;
MM(music-metadata)-->S(strtok3)
MM-->TY(token-types)
MM-->FT(file-type)
MMN("music-metadata (Node.js entry point)")-->MMP
MMN-->FTN
MMP("music-metadata (primary entry point)")-->S(strtok3)
MMP-->TY(token-types)
MMP-->FTP
MMP-->UAE
FTN("file-type (Node.js entry point)")-->FTP
FTP("file-type (primary entry point)")-->S
S(strtok3)-->P(peek-readable)
S-->TO("@tokenizer/token")
TY-->TO
S(strtok3)-->TO("@tokenizer/token")
TY(token-types)-->TO
TY-->IE("ieee754")
FT-->RWNS(readable-web-to-node-stream)
FT-->S
FT-->TY
TY-->NB(node:buffer)
RWNS-->RS(readable-stream)
RS-->SD(string_decoder)
SD-->SB(safe-buffer)
RS-->UD(util-deprecate)
RS-->I(inherits)
style NB fill:#F88,stroke:#A44
style SB fill:#F88,stroke:#A44
style SD fill:#CCC,stroke:#888
FTP-->TY
NS("node:stream")
FTN-->NS
FTP-->UAE(uint8array-extras)
style NS fill:#F88,stroke:#A44
style IE fill:#CCC,stroke:#888
style UD fill:#CCC,stroke:#888
style I fill:#CCC,stroke:#888
style FTN fill:#FAA,stroke:#A44
style MMN fill:#FAA,stroke:#A44
```

Dependency list:
Expand Down
2 changes: 1 addition & 1 deletion doc/common_metadata.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ The tag mapping is strongly inspired on the [MusicBrainz Picard tag-mapping](htt
| genre | * | Genres | genre | TCO | TCON, TXXX:STYLE | TCON, TXXX:STYLE | ©GEN, GNRE | GENRE, STYLE | GENRE | WM/Genre | GNRE, IGNR | TRACK:GENRE | |
| picture | * | Embedded cover art | | PIC | APIC | APIC | COVR | METADATA_BLOCK_PICTURE | COVER ART (FRONT), COVER ART (BACK) | WM/Picture | | PICTURE | |
| composer | * | Composer | | TCM | TCOM | TCOM | ©WRT | COMPOSER | COMPOSER | WM/Composer | | | |
| lyrics | * | Lyricist | | | USLT:DESCRIPTION, SYLT | USLT:DESCRIPTION, SYLT | ©LYR | LYRICS | LYRICS | WM/Lyrics | | | |
| lyrics | * | Lyricist | | | USLT, SYLT | USLT, SYLT | ©LYR | LYRICS | LYRICS | WM/Lyrics | | | |
| albumsort | 1 | Album title, formatted for alphabetic ordering | | TSA | TSOA | TSOA | SOAL | ALBUMSORT | ALBUMSORT | WM/AlbumSortOrder | | | |
| titlesort | 1 | Track title, formatted for alphabetic ordering | | TST | TSOT | TSOT | SONM | TITLESORT | TITLESORT | WM/TitleSortOrder | | | |
| work | 1 | The canonical title of the [work](https://musicbrainz.org/doc/Work) | | | | | ©WRK | WORK | WORK | WM/Work | | | |
Expand Down
3 changes: 1 addition & 2 deletions lib/ParserFactory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import { fileTypeFromBuffer } from 'file-type';
import ContentType from 'content-type';
import MimeType from 'media-typer';
import initDebug from 'debug';
import { Buffer } from 'node:buffer';

import { INativeMetadataCollector, MetadataCollector } from './common/MetadataCollector.js';
import { AIFFParser } from './aiff/AiffParser.js';
Expand Down Expand Up @@ -89,7 +88,7 @@ export class ParserFactory {
// Parser could not be determined on MIME-type or extension
debug('Guess parser on content...');

const buf = Buffer.alloc(4100);
const buf = new Uint8Array(4100);
await tokenizer.peekBuffer(buf, {mayBeLess: true});
if (tokenizer.fileInfo.path) {
parserId = this.getParserIdForExtension(tokenizer.fileInfo.path);
Expand Down
5 changes: 2 additions & 3 deletions lib/aiff/AiffParser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -115,9 +115,8 @@ export class AIFFParser extends BasicParser {

public async readTextChunk(header: iff.IChunkHeader): Promise<number> {
const value = await this.tokenizer.readToken(new Token.StringType(header.chunkSize, 'ascii'));
value.split('\0').map(v => v.trim()).filter(v => v && v.length > 0).forEach(v => {
this.metadata.addTag('AIFF', header.chunkID, v.trim());
});
const values = value.split('\0').map(v => v.trim()).filter(v => v && v.length);
await Promise.all(values.map(v => this.metadata.addTag('AIFF', header.chunkID, v)));
return header.chunkSize;
}

Expand Down
19 changes: 9 additions & 10 deletions lib/aiff/AiffToken.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import * as Token from 'token-types';
import { Buffer } from 'node:buffer';

import { FourCcToken } from '../common/FourCC.js';
import * as iff from '../iff/index.js';

import { IGetToken } from 'strtok3';
import type { IGetToken } from 'strtok3';

/**
* The Common Chunk.
Expand All @@ -30,27 +29,27 @@ export class Common implements IGetToken<ICommon> {
this.len = header.chunkSize;
}

public get(buf: Buffer, off: number): ICommon {
public get(buf: Uint8Array, off: number): ICommon {

// see: https://cycling74.com/forums/aiffs-80-bit-sample-rate-value
const shift = buf.readUInt16BE(off + 8) - 16398;
const baseSampleRate = buf.readUInt16BE(off + 8 + 2);
const shift = Token.UINT16_BE.get(buf, off + 8) - 16398;
const baseSampleRate = Token.UINT16_BE.get(buf, off + 8 + 2);

const res: ICommon = {
numChannels: buf.readUInt16BE(off),
numSampleFrames: buf.readUInt32BE(off + 2),
sampleSize: buf.readUInt16BE(off + 6),
numChannels: Token.UINT16_BE.get(buf, off),
numSampleFrames: Token.UINT32_BE.get(buf, off + 2),
sampleSize: Token.UINT16_BE.get(buf, off + 6),
sampleRate: shift < 0 ? baseSampleRate >> Math.abs(shift) : baseSampleRate << shift
};

if (this.isAifc) {
res.compressionType = FourCcToken.get(buf, off + 18);
if (this.len > 22) {
const strLen = buf.readInt8(off + 22);
const strLen = Token.UINT8.get(buf, off + 22);
if (strLen > 0) {
const padding = (strLen + 1) % 2;
if (23 + strLen + padding === this.len) {
res.compressionName = new Token.StringType(strLen, 'binary').get(buf, off + 23);
res.compressionName = new Token.StringType(strLen, 'latin1').get(buf, off + 23);
} else {
throw new Error('Illegal pstring length');
}
Expand Down
22 changes: 10 additions & 12 deletions lib/apev2/APEv2Parser.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import initDebug from 'debug';
import * as strtok3 from 'strtok3/core';
import { StringType } from 'token-types';
import { Buffer } from 'node:buffer';
import { uint8ArrayToString } from 'uint8array-extras';

import * as util from '../common/Util.js';
import { IOptions, IRandomReader, IApeHeader } from '../type.js';
Expand Down Expand Up @@ -56,7 +56,7 @@ export class APEv2Parser extends BasicParser {
*/
public static async findApeFooterOffset(reader: IRandomReader, offset: number): Promise<IApeHeader> {
// Search for APE footer header at the end of the file
const apeBuf = Buffer.alloc(TagFooter.len);
const apeBuf = new Uint8Array(TagFooter.len);
await reader.randomRead(apeBuf, 0, TagFooter.len, offset - TagFooter.len);
const tagFooter = TagFooter.get(apeBuf, 0);
if (tagFooter.ID === 'APETAGEX') {
Expand All @@ -65,7 +65,7 @@ export class APEv2Parser extends BasicParser {
}
}

private static parseTagFooter(metadata: INativeMetadataCollector, buffer: Buffer, options: IOptions): Promise<void> {
private static parseTagFooter(metadata: INativeMetadataCollector, buffer: Uint8Array, options: IOptions): Promise<void> {
const footer = TagFooter.get(buffer, buffer.length - TagFooter.len);
if (footer.ID !== preamble) throw new Error('Unexpected APEv2 Footer ID preamble value.');
strtok3.fromBuffer(buffer);
Expand Down Expand Up @@ -95,7 +95,7 @@ export class APEv2Parser extends BasicParser {
if (this.tokenizer.fileInfo.size) {
// Try to read the APEv2 header using just the footer-header
const remaining = this.tokenizer.fileInfo.size - this.tokenizer.position; // ToDo: take ID3v1 into account
const buffer = Buffer.alloc(remaining);
const buffer = new Uint8Array(remaining);
await this.tokenizer.readBuffer(buffer);
return APEv2Parser.parseTagFooter(this.metadata, buffer, this.options);
}
Expand All @@ -117,7 +117,7 @@ export class APEv2Parser extends BasicParser {

public async parseTags(footer: IFooter): Promise<void> {

const keyBuffer = Buffer.alloc(256); // maximum tag key length
const keyBuffer = new Uint8Array(256); // maximum tag key length

let bytesRemaining = footer.size - TagFooter.len;

Expand All @@ -144,24 +144,22 @@ export class APEv2Parser extends BasicParser {
const value = await this.tokenizer.readToken<string>(new StringType(tagItemHeader.size, 'utf8'));
const values = value.split(/\x00/g);

for (const val of values) {
this.metadata.addTag(tagFormat, key, val);
}
await Promise.all(values.map(val => this.metadata.addTag(tagFormat, key, val)));
break;
}

case DataType.binary: // binary (probably artwork)
if (this.options.skipCovers) {
await this.tokenizer.ignore(tagItemHeader.size);
} else {
const picData = Buffer.alloc(tagItemHeader.size);
const picData = new Uint8Array(tagItemHeader.size);
await this.tokenizer.readBuffer(picData);

zero = util.findZero(picData, 0, picData.length);
const description = picData.toString('utf8', 0, zero);
const description = uint8ArrayToString(picData.slice(0, zero));
const data = picData.slice(zero + 1);

const data = Buffer.from(picData.slice(zero + 1));
this.metadata.addTag(tagFormat, key, {
await this.metadata.addTag(tagFormat, key, {
description,
data
});
Expand Down
3 changes: 1 addition & 2 deletions lib/apev2/APEv2Token.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import * as Token from 'token-types';
import { IGetToken } from 'strtok3/core';
import { Buffer } from 'node:buffer';

import { FourCcToken } from '../common/FourCC.js';

Expand Down Expand Up @@ -158,7 +157,7 @@ export const Header: IGetToken<IHeader> = {
export const TagFooter: IGetToken<IFooter> = {
len: 32,

get: (buf: Buffer, off) => {
get: (buf, off) => {
return {
// should equal 'APETAGEX'
ID: new Token.StringType(8, 'ascii').get(buf, off),
Expand Down
Loading
Loading