UNPKG

@ndn/packet

Version:

NDNts: Network Layer Packets

201 lines (200 loc) 6.45 kB
import { Decoder, Encoder } from "@ndn/tlv"; import { toHex } from "@ndn/util"; import { TT } from "../an_node.js"; import { Component } from "./component_node.js"; /** * Name. * * @remarks * This type is immutable. */ export class Name { static decodeFrom(decoder) { const { value } = decoder.read(); return new Name(value); } /** * Create Name from Name or Name URI. * * @remarks * This is more efficient than `new Name(input)` if input is already a Name. */ static from(input) { return input instanceof Name ? input : new Name(input); } constructor(arg1, parseComponent = Component.from) { if (arg1 === undefined) { this.valueEncoderBufSize = 0; } else if (arg1 instanceof Name) { this.comps = arg1.comps; this.value_ = arg1.value_; this.uri_ = arg1.uri_; this.hex_ = arg1.hex_; } else if (typeof arg1 === "string") { for (const comp of arg1.replace(/^(?:ndn:)?\/*/, "").split("/")) { if (comp !== "") { this.comps.push(parseComponent(comp)); } } this.valueEncoderBufSize = arg1.length + 4 * this.comps.length; } else if (Array.isArray(arg1)) { this.comps = Array.from(arg1, Component.from); } else if (arg1 instanceof Uint8Array) { this.value_ = arg1; const decoder = new Decoder(this.value_); while (!decoder.eof) { this.comps.push(decoder.decode(Component)); } } } /** List of name components. */ comps = []; valueEncoderBufSize; value_; uri_; hex_; /** Number of name components. */ get length() { return this.comps.length; } /** Name TLV-VALUE. */ get value() { this.value_ ??= Encoder.encode(this.comps, this.valueEncoderBufSize ?? 256); return this.value_; } /** Name TLV-VALUE hexadecimal representation, good for map keys. */ get valueHex() { this.hex_ ??= toHex(this.value); return this.hex_; } /** * Retrieve i-th component. * @param i - Component index. Negative number counts from the end. * @returns i-th component, or `undefined` if it does not exist. */ get(i) { return this.comps.at(i); } /** * Retrieve i-th component. * @param i - Component index. Negative number counts from the end. * @returns i-th component. * * @throws RangeError * Thrown if i-th component does not exist. */ at(i) { const comp = this.get(i); if (!comp) { throw new RangeError(`component ${i} out of range`); } return comp; } /** Get URI string. */ toString() { this.uri_ ??= `/${this.comps.map((comp) => comp.toString()).join("/")}`; return this.uri_; } /** Get sub name `[begin,end)`. */ slice(begin, end) { return new Name(this.comps.slice(begin, end)); } /** Get prefix of `n` components. */ getPrefix(n) { return this.slice(0, n); } append(...args) { let suffix; if (args.length === 2 && typeof args[0].create === "function") { suffix = [args[0].create(args[1])]; } else { suffix = args; } return new Name([...this.comps, ...suffix]); } /** Return a copy of Name with i-th component replaced with `comp`. */ replaceAt(i, comp) { return new Name(this.comps.toSpliced(i, 1, comp)); } /** Compare with other name. */ compare(other) { return Name.compare(this, Name.from(other)); } /** Determine if this name equals other. */ equals(other) { other = Name.from(other); if (this.hex_ !== undefined && other.hex_ !== undefined) { return this.hex_ === other.hex_; } return this.length === other.length && comparePrefix(this, other, this.length) === Name.CompareResult.EQUAL; } /** Determine if this name is a prefix of other. */ isPrefixOf(other) { other = Name.from(other); if (this.hex_ !== undefined && other.hex_ !== undefined) { return other.hex_.startsWith(this.hex_); } return this.length <= other.length && comparePrefix(this, other, this.length) === Name.CompareResult.EQUAL; } encodeTo(encoder) { if (this.value_) { encoder.prependTlv(TT.Name, this.value_); } else { encoder.prependTlv(TT.Name, ...this.comps); } } } (function (Name) { /** Determine if obj is Name or Name URI. */ function isNameLike(obj) { return obj instanceof Name || typeof obj === "string"; } Name.isNameLike = isNameLike; /** Name compare result. */ let CompareResult; (function (CompareResult) { /** lhs is less than, but not a prefix of rhs */ CompareResult[CompareResult["LT"] = -2] = "LT"; /** lhs is a prefix of rhs */ CompareResult[CompareResult["LPREFIX"] = -1] = "LPREFIX"; /** lhs and rhs are equal */ CompareResult[CompareResult["EQUAL"] = 0] = "EQUAL"; /** rhs is a prefix of lhs */ CompareResult[CompareResult["RPREFIX"] = 1] = "RPREFIX"; /** rhs is less than, but not a prefix of lhs */ CompareResult[CompareResult["GT"] = 2] = "GT"; })(CompareResult = Name.CompareResult || (Name.CompareResult = {})); /** Compare two names. */ function compare(lhs, rhs) { const commonSize = Math.min(lhs.length, rhs.length); const cmp = comparePrefix(lhs, rhs, commonSize); if (cmp !== CompareResult.EQUAL) { return cmp; } if (lhs.length > commonSize) { return CompareResult.RPREFIX; } if (rhs.length > commonSize) { return CompareResult.LPREFIX; } return CompareResult.EQUAL; } Name.compare = compare; })(Name || (Name = {})); /** Compare first n components between two names. */ function comparePrefix(lhs, rhs, n) { for (let i = 0; i < n; ++i) { const cmp = lhs.comps[i].compare(rhs.comps[i]); if (cmp !== Component.CompareResult.EQUAL) { return cmp; } } return Name.CompareResult.EQUAL; }