taglib-wasm
Version:
TagLib for TypeScript platforms: Deno, Node.js, Bun, Electron, browsers, and Cloudflare Workers
191 lines (190 loc) • 5.29 kB
JavaScript
import { decode } from "@msgpack/msgpack";
const MSGPACK_DECODE_OPTIONS = {
// Use integers instead of BigInt for performance
useBigInt64: false,
// Enable extension types for custom data
extensionCodec: void 0,
// Will be set up below if needed
// Maximum decode iterations for safety
maxStrLength: 1e6,
// 1MB max string
maxBinLength: 5e7,
// 50MB max binary (for large album art)
maxArrayLength: 1e4,
// Reasonable array limit
maxMapLength: 1e3,
// Reasonable object limit
maxExtLength: 5e7
// 50MB max extension
};
function decodeTagData(msgpackBuffer) {
try {
const decoded = decode(msgpackBuffer, MSGPACK_DECODE_OPTIONS);
return decoded;
} catch (error) {
throw new Error(`Failed to decode MessagePack tag data: ${error}`);
}
}
function decodeAudioProperties(msgpackBuffer) {
try {
const decoded = decode(msgpackBuffer, MSGPACK_DECODE_OPTIONS);
return decoded;
} catch (error) {
throw new Error(`Failed to decode MessagePack audio properties: ${error}`);
}
}
function decodePropertyMap(msgpackBuffer) {
try {
const decoded = decode(msgpackBuffer, MSGPACK_DECODE_OPTIONS);
return decoded;
} catch (error) {
throw new Error(`Failed to decode MessagePack property map: ${error}`);
}
}
function decodePicture(msgpackBuffer) {
try {
const decoded = decode(msgpackBuffer, MSGPACK_DECODE_OPTIONS);
const picture = decoded;
if (picture.data && !(picture.data instanceof Uint8Array)) {
picture.data = new Uint8Array(picture.data);
}
return picture;
} catch (error) {
throw new Error(`Failed to decode MessagePack picture data: ${error}`);
}
}
function decodePictureArray(msgpackBuffer) {
try {
const decoded = decode(msgpackBuffer, MSGPACK_DECODE_OPTIONS);
const pictures = decoded;
return pictures.map((picture) => {
if (picture.data && !(picture.data instanceof Uint8Array)) {
picture.data = new Uint8Array(picture.data);
}
return picture;
});
} catch (error) {
throw new Error(`Failed to decode MessagePack picture array: ${error}`);
}
}
function decodeMessagePack(msgpackBuffer, options = {}) {
try {
const mergedOptions = { ...MSGPACK_DECODE_OPTIONS, ...options };
const decoded = decode(msgpackBuffer, mergedOptions);
return decoded;
} catch (error) {
throw new Error(`Failed to decode MessagePack data: ${error}`);
}
}
function decodeMessagePackAuto(msgpackBuffer) {
try {
const decoded = decode(msgpackBuffer, MSGPACK_DECODE_OPTIONS);
if (decoded && typeof decoded === "object") {
if ("bitrate" in decoded && "sampleRate" in decoded && "length" in decoded) {
return decoded;
}
if ("mimeType" in decoded && "data" in decoded) {
if (decoded.data && !(decoded.data instanceof Uint8Array)) {
decoded.data = new Uint8Array(decoded.data);
}
return decoded;
}
if ("title" in decoded || "artist" in decoded || "album" in decoded) {
return decoded;
}
if (Object.values(decoded).every((value) => Array.isArray(value))) {
return decoded;
}
}
return decoded;
} catch (error) {
throw new Error(
`Failed to decode MessagePack data with auto-detection: ${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 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;
if (Array.isArray(decoded)) {
info.type = "array";
} else if (decoded instanceof Uint8Array) {
info.type = "binary";
} else if (typeof decoded === "object" && decoded !== null) {
info.type = "map";
} else if (typeof decoded === "string") {
info.type = "string";
} else if (typeof decoded === "number") {
info.type = "number";
} else if (typeof decoded === "boolean") {
info.type = "boolean";
} else if (decoded === null) {
info.type = "null";
}
} catch {
}
return info;
}
function decodeFastTagData(msgpackBuffer) {
try {
const decoded = decode(msgpackBuffer, {
...MSGPACK_DECODE_OPTIONS,
// Smaller limits for faster processing
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 Error(`Failed to decode fast tag data: ${error}`);
}
}
export {
decodeAudioProperties,
decodeFastTagData,
decodeMessagePack,
decodeMessagePackAuto,
decodePicture,
decodePictureArray,
decodePropertyMap,
decodeTagData,
getMessagePackInfo,
isValidMessagePack
};