UNPKG

m3u8parse

Version:

Structural parsing of Apple HTTP Live Streaming .m3u8 format

99 lines (98 loc) 3.2 kB
import deserialize from './attr-deserialize.js'; import serialize from './attr-serialize.js'; import { Attr } from './attr-types.js'; export { Attr as AttrType }; const tokenify = function (attr) { if (typeof attr !== 'string') { throw new TypeError('Attributes must be a "string"'); } return attr.toLowerCase(); }; // AttrList's are handled without any implicit knowledge of key/type mapping // eslint-disable-next-line @typescript-eslint/ban-types export class AttrList extends Map { constructor(attrs) { super(); const set = (key, value, format) => { if (value !== null && value !== undefined) { super.set(key, format ? format(value) : value); } }; if (attrs instanceof AttrList) { for (const [key, value] of attrs) { set(key, value); } } else if (typeof attrs === 'string') { // TODO: handle newline escapes in quoted-string's const re = /(.+?)=((?:\".*?\")|.*?)(?:,|$)/g; let match; while ((match = re.exec(attrs)) !== null) { const attr = tokenify(match[1]); if (super.has(attr)) { throw new Error('Duplicate attribute key: ' + attr); } set(tokenify(attr), match[2]); } } else if (!(attrs instanceof Map) && !Array.isArray(attrs)) { for (const attr in attrs) { set(tokenify(attr), attrs[attr], (val) => `${val || ''}`); } } else { for (const [key, value] of attrs) { set(tokenify(key), value, (val) => `${val}`); } } } get(attr, type = Attr.Enum) { attr = tokenify(attr); const stringValue = super.get(attr); if (stringValue !== undefined) { const formatter = deserialize[type]; if (!formatter) { throw new TypeError('Invalid type: ' + type); } return formatter(stringValue); } return stringValue; } set(attr, value, type = Attr.Enum) { attr = tokenify(attr); if (value === undefined || value === null) { super.delete(attr); return this; } const formatter = serialize[type]; if (!formatter) { throw new TypeError('Invalid type: ' + type); } const stringValue = formatter(value); super.set(attr, stringValue); return this; } has(attr) { return super.has(tokenify(attr)); } delete(attr) { return super.delete(tokenify(attr)); } toString() { let res = ''; for (const [key, value] of this) { const comma = (res.length !== 0) ? ',' : ''; res += `${comma}${key.toUpperCase()}=${value}`; } return res; } // eslint-disable-next-line @typescript-eslint/ban-types toJSON() { const obj = Object.create(null); for (const [key, value] of this) { obj[key] = value; } return obj; } } AttrList.Types = Attr;