UNPKG

@ndn/tlv

Version:
94 lines (93 loc) 3.15 kB
import { getOrInsert } from "@ndn/util"; import { EvDecoder } from "./ev-decoder_browser.js"; import { encodeFields, makeField, sortFields } from "./impl-field_browser.js"; const RECORDS = new WeakMap(); function getOrCreateRecord(obj) { return getOrInsert(RECORDS, obj, () => ({})); } export var Extensible; (function (Extensible) { Extensible.TAG = Symbol("@ndn/tlv#Extensible"); /** Clone extension fields of src to dst. */ function cloneRecord(dst, src) { const record = RECORDS.get(src); if (record !== undefined) { RECORDS.set(dst, record); } } Extensible.cloneRecord = cloneRecord; /** * Define simple getters and setters. * @param typ - Extensible subclass constructor. * @param exts - Extensions, each key is a property name and each value is the TLV-TYPE number. */ function defineGettersSetters(typ, exts) { for (const [prop, tt] of Object.entries(exts)) { Object.defineProperty(typ.prototype, prop, { enumerable: true, get() { return Extension.get(this, tt); }, set(value) { if (value === undefined) { Extension.clear(this, tt); } else { Extension.set(this, tt, value); } }, }); } } Extensible.defineGettersSetters = defineGettersSetters; })(Extensible || (Extensible = {})); export var Extension; (function (Extension) { /** Retrieve value of an extension field. */ function get(obj, tt) { return RECORDS.get(obj)?.[`ext_${tt}`]; } Extension.get = get; /** Assign value of an extension field. */ function set(obj, tt, value) { getOrCreateRecord(obj)[`ext_${tt}`] = value; } Extension.set = set; /** Clear value of an extension field. */ function clear(obj, tt) { delete RECORDS.get(obj)?.[`ext_${tt}`]; } Extension.clear = clear; })(Extension || (Extension = {})); /** Registry of known extension fields of a parent TLV element. */ export class ExtensionRegistry { hasUnrecognized = false; evd = new EvDecoder("ExtensionRegistry") .setUnknown(() => { this.hasUnrecognized = true; return false; }) .setIsCritical(EvDecoder.neverCritical); fields = []; /** Add an extension. */ register = (tt, type, opts = {}) => { opts.order ??= tt; this.fields.push(makeField(tt, `ext_${tt}`, type, opts, this.evd)); sortFields(this.fields); }; /** UnknownElementCallback for EvDecoder. */ decodeUnknown = (target, tlv) => { const record = getOrCreateRecord(target); this.hasUnrecognized = false; this.evd.decodeValue(record, tlv.decoder); return !this.hasUnrecognized; }; /** Encode extension fields. */ encode(source) { const record = RECORDS.get(source); if (!record) { return []; } return encodeFields(this.fields, record); } }