@ndn/packet
Version:
NDNts: Network Layer Packets
161 lines (160 loc) • 5.39 kB
JavaScript
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_node.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); // eslint-disable-line etc/no-internal
}
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 = {}));