@ndn/tlv
Version:
NDNts: TLV
94 lines (93 loc) • 3.14 kB
JavaScript
import { getOrInsert } from "@ndn/util";
import { EvDecoder } from "./ev-decoder_node.js";
import { encodeFields, makeField, sortFields } from "./impl-field_node.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);
}
}