UNPKG

@ndn/packet

Version:

NDNts: Network Layer Packets

161 lines (160 loc) 5.36 kB
import { __importDefault, __importStar } from "tslib"; import { Decoder, Encoder } from "@ndn/tlv"; import { assert, constrain, fromHex, fromUtf8, toHex, toUtf8 } from "@ndn/util"; import _cjsDefaultImport0 from "buffer-compare"; const bufferCompare = __importDefault(_cjsDefaultImport0).default; import { TT } from "../an_browser.js"; function assertType(t) { return constrain(t, "Component TLV-TYPE", 0x01, 0xFFFF); } const CHAR_ENCODE = {}; for (let b = 0x00; b <= 0xFF; ++b) { const s = String.fromCodePoint(b); CHAR_ENCODE[b] = /[\w.~-]/i.test(s) ? s : `%${toHex.TABLE[b]}`; } const CODEPOINT_PERCENT = "%".codePointAt(0); const CODEPOINT_PERIOD = ".".codePointAt(0); const encoderHeadroom = 10; /** * Name component. * * @remarks * This type is immutable. */ export class Component { static decodeFrom(decoder) { const { tlv } = decoder.read(); return new Component(tlv); } /** Parse from URI representation, or return existing Component. */ static from(input) { if (input instanceof Component) { return input; } let type = TT.GenericNameComponent; let posValue = 0; const posEqual = input.indexOf("="); if (posEqual >= 1) { try { type = assertType(Number.parseInt(input, 10)); posValue = posEqual + 1; } catch { } } const maxLength = input.length - posValue; const encoder = new Encoder(encoderHeadroom + maxLength); const value = encoder.prependRoom(maxLength); let length = 0; let hasNonPeriods = false; for (let i = posValue; i < input.length;) { let b = input.codePointAt(i); hasNonPeriods ||= b !== CODEPOINT_PERIOD; if (b === CODEPOINT_PERCENT) { b = (fromHex.TABLE[input[i + 1]] << 4) | fromHex.TABLE[input[i + 2]]; i += 3; } else { ++i; } value[length++] = b; } if (!hasNonPeriods && length >= 3) { length -= 3; } return new Component(type, encoder, length); } constructor(arg1 = TT.GenericNameComponent, arg2, length) { if (arg1 instanceof Uint8Array) { this.tlv = arg1; const decoder = new Decoder(arg1); ({ type: this.type, value: this.value } = decoder.read()); decoder.throwUnlessEof(); } else { this.type = arg1; let encoder; let tailroom = 0; if (arg2 instanceof Encoder) { encoder = arg2; tailroom = encoder.size - length; } else { const value = typeof arg2 === "string" ? toUtf8(arg2) : arg2; length = value?.length ?? 0; encoder = new Encoder(encoderHeadroom + length); encoder.encode(value); } encoder.prependTypeLength(this.type, length); this.tlv = encoder.output; if (tailroom !== 0) { this.tlv = this.tlv.subarray(0, -tailroom); } this.value = this.tlv.subarray(this.tlv.length - length); } assertType(this.type); } /** Whole TLV. */ tlv; /** TLV-TYPE. */ type; /** TLV-VALUE. */ value; /** TLV-LENGTH. */ get length() { return this.value.length; } /** TLV-VALUE interpreted as UTF-8 string. */ get text() { return fromUtf8(this.value); } /** Get URI string. */ toString() { let s = `${this.type}=`; let hasNonPeriods = false; for (const b of this.value) { hasNonPeriods ||= b !== CODEPOINT_PERIOD; s += CHAR_ENCODE[b]; } if (!hasNonPeriods) { s += "..."; } return s; } encodeTo(encoder) { encoder.encode(this.tlv); } /** Determine if component follows a naming convention. */ is(convention) { return convention.match(this); } /** Convert with naming convention. */ as(convention) { assert(convention.match(this), "component does not follow convention"); return convention.parse(this); } /** Compare this component with other. */ compare(other) { return Component.compare(this, Component.from(other)); } /** Determine if this component equals other. */ equals(other) { return this.compare(other) === Component.CompareResult.EQUAL; } } (function (Component) { /** Component compare result. */ let CompareResult; (function (CompareResult) { /** lhs is less than rhs */ CompareResult[CompareResult["LT"] = -2] = "LT"; /** lhs and rhs are equal */ CompareResult[CompareResult["EQUAL"] = 0] = "EQUAL"; /** lhs is greater than rhs */ CompareResult[CompareResult["GT"] = 2] = "GT"; })(CompareResult = Component.CompareResult || (Component.CompareResult = {})); /** Compare two components. */ function compare(lhs, rhs) { return 2 * Math.sign(lhs.type - rhs.type || lhs.length - rhs.length || bufferCompare(lhs.value, rhs.value)); } Component.compare = compare; })(Component || (Component = {}));