UNPKG

taglib-wasm

Version:

TagLib-Wasm is the universal tagging library for TypeScript/JavaScript platforms: Browsers, Node.js, Deno, Bun, Cloudflare Workers, and Electron apps

217 lines (216 loc) 5.69 kB
import { decode } from "@msgpack/msgpack"; import { errorMessage, MetadataError } from "../errors/classes.js"; import { remapKeysFromTagLib } from "../constants/properties.js"; const MSGPACK_DECODE_OPTIONS = { useBigInt64: false, extensionCodec: void 0, maxStrLength: 1e6, maxBinLength: 5e7, maxArrayLength: 1e4, maxMapLength: 1e3, maxExtLength: 5e7 }; function decodeTagData(msgpackBuffer) { try { const raw = decode(msgpackBuffer, MSGPACK_DECODE_OPTIONS); return remapKeysFromTagLib(raw); } catch (error) { throw new MetadataError( "read", `Failed to decode tag data: ${errorMessage(error)}` ); } } function decodeAudioProperties(msgpackBuffer) { try { const raw = decode(msgpackBuffer, MSGPACK_DECODE_OPTIONS); if ("length" in raw && !("duration" in raw)) { raw.duration = raw.length; delete raw.length; } return raw; } catch (error) { throw new MetadataError( "read", `Failed to decode audio properties: ${errorMessage(error)}` ); } } function decodePropertyMap(msgpackBuffer) { try { return decode(msgpackBuffer, MSGPACK_DECODE_OPTIONS); } catch (error) { throw new MetadataError( "read", `Failed to decode property map: ${errorMessage(error)}` ); } } function decodePicture(msgpackBuffer) { try { const picture = decode(msgpackBuffer, MSGPACK_DECODE_OPTIONS); coercePictureData(picture); return picture; } catch (error) { throw new MetadataError( "read", `Failed to decode picture data: ${errorMessage(error)}` ); } } function decodePictureArray(msgpackBuffer) { try { const pictures = decode(msgpackBuffer, MSGPACK_DECODE_OPTIONS); return pictures.map((picture) => { coercePictureData(picture); return picture; }); } catch (error) { throw new MetadataError( "read", `Failed to decode picture array: ${errorMessage(error)}` ); } } function decodeMessagePack(msgpackBuffer, options = {}) { try { const mergedOptions = { ...MSGPACK_DECODE_OPTIONS, ...options }; return decode(msgpackBuffer, mergedOptions); } catch (error) { throw new MetadataError( "read", `Failed to decode data: ${errorMessage(error)}` ); } } function isAudioProperties(obj) { return "bitrate" in obj && "sampleRate" in obj && ("length" in obj || "duration" in obj); } function isPicture(obj) { return "mimeType" in obj && "data" in obj; } function coercePictureData(obj) { if (obj.data && !(obj.data instanceof Uint8Array)) { obj.data = new Uint8Array(obj.data); } } function isTagLike(obj) { return "title" in obj || "artist" in obj || "album" in obj || "TITLE" in obj || "ARTIST" in obj || "ALBUM" in obj; } function isPropertyMap(obj) { const values = Object.values(obj); return values.length > 0 && values.every((value) => Array.isArray(value)); } function decodeMessagePackAuto(msgpackBuffer) { try { const decoded = decode(msgpackBuffer, MSGPACK_DECODE_OPTIONS); if (decoded && typeof decoded === "object") { const obj = decoded; if (isAudioProperties(obj)) { if ("length" in obj && !("duration" in obj)) { obj.duration = obj.length; delete obj.length; } return obj; } if (isPicture(obj)) { coercePictureData(obj); return obj; } if (isPropertyMap(obj)) return obj; if (isTagLike(obj)) { return remapKeysFromTagLib(obj); } } throw new MetadataError( "read", `Unexpected non-object MessagePack data: ${typeof decoded}` ); } catch (error) { throw new MetadataError( "read", `Failed to decode data with auto-detection: ${errorMessage(error)}` ); } } function isValidMessagePack(buffer) { try { decode(buffer, { ...MSGPACK_DECODE_OPTIONS, maxStrLength: 1e3, maxBinLength: 1e3, maxArrayLength: 100, maxMapLength: 100, maxExtLength: 1e3 }); return true; } catch { return false; } } function detectType(decoded) { if (Array.isArray(decoded)) return "array"; if (decoded instanceof Uint8Array) return "binary"; if (typeof decoded === "object" && decoded !== null) return "map"; if (typeof decoded === "string") return "string"; if (typeof decoded === "number") return "number"; if (typeof decoded === "boolean") return "boolean"; if (decoded === null) return "null"; return "unknown"; } function getMessagePackInfo(buffer) { const info = { isValid: false, approximateSize: buffer.length, type: "unknown" }; if (buffer.length === 0) return info; try { const decoded = decode(buffer, { ...MSGPACK_DECODE_OPTIONS, maxStrLength: 100, maxBinLength: 100, maxArrayLength: 10, maxMapLength: 10, maxExtLength: 100 }); info.isValid = true; info.type = detectType(decoded); } catch { } return info; } function decodeFastTagData(msgpackBuffer) { try { const decoded = decode(msgpackBuffer, { ...MSGPACK_DECODE_OPTIONS, maxStrLength: 1e4, maxArrayLength: 100, maxMapLength: 50 }); return { title: decoded.title, artist: decoded.artist, album: decoded.album, year: decoded.year, track: decoded.track }; } catch (error) { throw new MetadataError( "read", `Failed to decode fast tag data: ${errorMessage(error)}` ); } } export { decodeAudioProperties, decodeFastTagData, decodeMessagePack, decodeMessagePackAuto, decodePicture, decodePictureArray, decodePropertyMap, decodeTagData, getMessagePackInfo, isValidMessagePack };