diff --git a/lib/src/id3/util/decodeId3ImageFrame.ts b/lib/src/id3/util/decodeId3ImageFrame.ts index 877dafa1..dcfd11f1 100644 --- a/lib/src/id3/util/decodeId3ImageFrame.ts +++ b/lib/src/id3/util/decodeId3ImageFrame.ts @@ -1,8 +1,8 @@ import { DecodedId3Frame } from '../DecodedId3Frame.js'; import { RawId3Frame } from './RawFrame.js'; import { toUint8 } from './utf8.js'; -import { BufferSource } from 'stream/web'; import { toArrayBuffer } from './toArrayBuffer.js'; +import { utf8ArrayToStr } from '../../utils.js'; interface MetadataFrame { key: string; @@ -37,7 +37,7 @@ export function decodeId3ImageFrame( if (mimeTypeEndIndex === -1) { return undefined; } - const mimeType = fromUTF8(toUint8(frame.data, 1, mimeTypeEndIndex)); + const mimeType = utf8ArrayToStr(toUint8(frame.data, 1, mimeTypeEndIndex)); const pictureType = frame.data[2 + mimeTypeEndIndex]; const descriptionEndIndex = frame.data .subarray(3 + mimeTypeEndIndex) @@ -45,13 +45,13 @@ export function decodeId3ImageFrame( if (descriptionEndIndex === -1) { return undefined; } - const description = fromUTF8( + const description = utf8ArrayToStr( toUint8(frame.data, 3 + mimeTypeEndIndex, descriptionEndIndex) ); let data; if (mimeType === '-->') { - data = fromUTF8( + data = utf8ArrayToStr( toUint8(frame.data, 4 + mimeTypeEndIndex + descriptionEndIndex) ); } @@ -67,85 +67,3 @@ export function decodeId3ImageFrame( metadataFrame.data = data; return metadataFrame; } - -function fromUTF8(data?: BufferSource) { - if (!data) { - return ''; - } - - let uint8 = toUint8(data); - // If present, strip off the UTF-8 BOM. - if (uint8[0] == 0xef && uint8[1] == 0xbb && uint8[2] == 0xbf) { - uint8 = uint8.subarray(3); - } - - let decoded = ''; - for (let i = 0; i < uint8.length; ++i) { - // By default, the 'replacement character' codepoint. - let codePoint = 0xfffd; - - // Top bit is 0, 1-byte encoding. - if ((uint8[i] & 0x80) == 0) { - codePoint = uint8[i]; - - // Top 3 bits of byte 0 are 110, top 2 bits of byte 1 are 10, - // 2-byte encoding. - } - else if ( - uint8.length >= i + 2 && - (uint8[i] & 0xe0) == 0xc0 && - (uint8[i + 1] & 0xc0) == 0x80 - ) { - codePoint = ((uint8[i] & 0x1f) << 6) | (uint8[i + 1] & 0x3f); - i += 1; // Consume one extra byte. - - // Top 4 bits of byte 0 are 1110, top 2 bits of byte 1 and 2 are 10, - // 3-byte encoding. - } - else if ( - uint8.length >= i + 3 && - (uint8[i] & 0xf0) == 0xe0 && - (uint8[i + 1] & 0xc0) == 0x80 && - (uint8[i + 2] & 0xc0) == 0x80 - ) { - codePoint = - ((uint8[i] & 0x0f) << 12) | - ((uint8[i + 1] & 0x3f) << 6) | - (uint8[i + 2] & 0x3f); - i += 2; // Consume two extra bytes. - - // Top 5 bits of byte 0 are 11110, top 2 bits of byte 1, 2 and 3 are 10, - // 4-byte encoding. - } - else if ( - uint8.length >= i + 4 && - (uint8[i] & 0xf1) == 0xf0 && - (uint8[i + 1] & 0xc0) == 0x80 && - (uint8[i + 2] & 0xc0) == 0x80 && - (uint8[i + 3] & 0xc0) == 0x80 - ) { - codePoint = - ((uint8[i] & 0x07) << 18) | - ((uint8[i + 1] & 0x3f) << 12) | - ((uint8[i + 2] & 0x3f) << 6) | - (uint8[i + 3] & 0x3f); - i += 3; // Consume three extra bytes. - } - - // JavaScript strings are a series of UTF-16 characters. - if (codePoint <= 0xffff) { - decoded += String.fromCharCode(codePoint); - } - else { - // UTF-16 surrogate-pair encoding, based on - // https://en.wikipedia.org/wiki/UTF-16#Description - const baseCodePoint = codePoint - 0x10000; - const highPart = baseCodePoint >> 10; - const lowPart = baseCodePoint & 0x3ff; - decoded += String.fromCharCode(0xd800 + highPart); - decoded += String.fromCharCode(0xdc00 + lowPart); - } - } - - return decoded; -} diff --git a/lib/test/id3/getId3Frames.test.ts b/lib/test/id3/getId3Frames.test.ts index d614bef0..ac4d3bd1 100644 --- a/lib/test/id3/getId3Frames.test.ts +++ b/lib/test/id3/getId3Frames.test.ts @@ -8,7 +8,7 @@ import { generateId3, generateId3Frame, } from '../structuredfield/util/id3Generator.js'; -import { toArrayBuffer } from '../../src/id3/util/decodeId3ImageFrame.js'; +import { toArrayBuffer } from '../../src/id3/util/toArrayBuffer.js'; describe('getId3Frames', () => { it('no valid data produces empty output', () => {