@ndn/packet
Advanced tools
Comparing version
import { Encoder, EvDecoder, NNI } from "@ndn/tlv"; | ||
import { sha256 } from "@ndn/util"; | ||
import { TT } from "./an_browser.js"; | ||
import { Component, ImplicitDigest, Name } from "./name/mod_browser.js"; | ||
import { sha256 } from "./security/helper_browser.js"; | ||
import { LLSign, LLVerify } from "./security/signing_browser.js"; | ||
@@ -19,3 +19,3 @@ import { SigInfo } from "./sig-info_browser.js"; | ||
if (Name.isNameLike(arg)) { | ||
this.name = new Name(arg); | ||
this.name = Name.from(arg); | ||
} | ||
@@ -75,3 +75,3 @@ else if (arg instanceof Uint8Array) { | ||
}, { required: true }); | ||
EVD.beforeTopCallbacks.push((t, { tlv }) => t.topTlv = tlv); | ||
EVD.beforeObservers.push((t, tlv) => t.topTlv = tlv.tlv); | ||
/** Data packet. */ | ||
@@ -201,3 +201,3 @@ export class Data { | ||
} | ||
const ctorAssign = Symbol("Interest.ctorAssign"); | ||
const ctorAssign = Symbol("Data.ctorAssign"); | ||
(function (Data) { | ||
@@ -219,3 +219,3 @@ /** Constructor argument to set ContentType field. */ | ||
/** Constructor argument to set the current packet as FinalBlock. */ | ||
Data.FinalBlock = Symbol("FinalBlock"); | ||
Data.FinalBlock = Symbol("Data.FinalBlock"); | ||
})(Data || (Data = {})); |
import { Encoder, EvDecoder, NNI } from "@ndn/tlv"; | ||
import { sha256 } from "@ndn/util"; | ||
import { TT } from "./an_node.js"; | ||
import { Component, ImplicitDigest, Name } from "./name/mod_node.js"; | ||
import { sha256 } from "./security/helper_node.js"; | ||
import { LLSign, LLVerify } from "./security/signing_node.js"; | ||
@@ -19,3 +19,3 @@ import { SigInfo } from "./sig-info_node.js"; | ||
if (Name.isNameLike(arg)) { | ||
this.name = new Name(arg); | ||
this.name = Name.from(arg); | ||
} | ||
@@ -75,3 +75,3 @@ else if (arg instanceof Uint8Array) { | ||
}, { required: true }); | ||
EVD.beforeTopCallbacks.push((t, { tlv }) => t.topTlv = tlv); | ||
EVD.beforeObservers.push((t, tlv) => t.topTlv = tlv.tlv); | ||
/** Data packet. */ | ||
@@ -201,3 +201,3 @@ export class Data { | ||
} | ||
const ctorAssign = Symbol("Interest.ctorAssign"); | ||
const ctorAssign = Symbol("Data.ctorAssign"); | ||
(function (Data) { | ||
@@ -219,3 +219,3 @@ /** Constructor argument to set ContentType field. */ | ||
/** Constructor argument to set the current packet as FinalBlock. */ | ||
Data.FinalBlock = Symbol("FinalBlock"); | ||
Data.FinalBlock = Symbol("Data.FinalBlock"); | ||
})(Data || (Data = {})); |
@@ -1,5 +0,5 @@ | ||
import { Decoder, Encoder } from "@ndn/tlv"; | ||
import { type Decoder, Encoder } from "@ndn/tlv"; | ||
import type { Interest } from "./interest"; | ||
import { Component, Name, NameLike } from "./name/mod"; | ||
import { LLSign, LLVerify, Signer, Verifier } from "./security/signing"; | ||
import { type NameLike, Component, Name } from "./name/mod"; | ||
import { type Signer, type Verifier, LLSign, LLVerify } from "./security/signing"; | ||
import { SigInfo } from "./sig-info"; | ||
@@ -6,0 +6,0 @@ declare const FIELDS: unique symbol; |
@@ -1,53 +0,55 @@ | ||
import { Decoder, Encoder, EvDecoder, NNI, toHex } from "@ndn/tlv"; | ||
import { Encoder, EvDecoder, NNI } from "@ndn/tlv"; | ||
import { TT } from "./an_browser.js"; | ||
import { Name } from "./name/mod_browser.js"; | ||
const DelEVD = new EvDecoder("Delegation", TT.Delegation) | ||
.add(TT.Preference, (t, { nni }) => t.preference = nni) | ||
.add(TT.Name, (t, { decoder }) => t.name = decoder.decode(Name)); | ||
.add(TT.Preference, () => undefined) | ||
.add(TT.Name, (t, { decoder }) => t.name = decoder.decode(Name), { required: true }); | ||
const DelsEVD = new EvDecoder("FwHint") | ||
.add(TT.Delegation, (t, { decoder }) => t.push(decoder.decode(FwHint.Delegation)), { repeat: true }); | ||
.add(TT.Name, (t, { decoder }) => t.push(decoder.decode(Name)), { order: 1, repeat: true }) | ||
.add(TT.Delegation, (t, { decoder }) => t.push(DelEVD.decode({}, decoder).name), { order: 1, repeat: true }); | ||
/** ForwardingHint in Interest. */ | ||
export class FwHint { | ||
constructor(arg) { | ||
this.m = new Map(); | ||
this.delegations = []; | ||
if (Array.isArray(arg)) { | ||
for (const del of arg) { | ||
this.add(del); | ||
for (const name of arg) { | ||
this.delegations.push(Name.from(name)); | ||
} | ||
} | ||
else if (arg instanceof FwHint) { | ||
this.m = new Map(arg.m); | ||
this.delegations = [...arg.delegations]; | ||
} | ||
else if (Name.isNameLike(arg)) { | ||
this.add(new FwHint.Delegation(arg)); | ||
this.delegations = [Name.from(arg)]; | ||
} | ||
} | ||
static decodeValue(value) { | ||
return new FwHint(DelsEVD.decodeValue([], new Decoder(value))); | ||
static decodeValue(vd) { | ||
const t = new FwHint(); | ||
DelsEVD.decodeValue(t.delegations, vd); | ||
return t; | ||
} | ||
add(del) { | ||
this.m.set(toHex(del.name.value), del); | ||
} | ||
get delegations() { | ||
return Array.from(this.m.values()).sort((a, b) => a.preference - b.preference); | ||
} | ||
encodeTo(encoder) { | ||
encoder.prependTlv(TT.ForwardingHint, Encoder.OmitEmpty, ...this.delegations); | ||
switch (FwHint.encodeFormat) { | ||
case 2017: | ||
encoder.prependTlv(TT.ForwardingHint, Encoder.OmitEmpty, ...this.delegations.map((name, i) => [TT.Delegation, [TT.Preference, NNI(i)], name])); | ||
break; | ||
case 2021: | ||
encoder.prependTlv(TT.ForwardingHint, Encoder.OmitEmpty, ...this.delegations); | ||
break; | ||
} | ||
} | ||
} | ||
(function (FwHint) { | ||
/** Delegation in ForwardingHint. */ | ||
class Delegation { | ||
constructor(name = "", preference = 0) { | ||
this.preference = preference; | ||
this.name = new Name(name); | ||
FwHint.encodeFormat = 2017; | ||
function withEncodeFormat(format, cb) { | ||
const prevFmt = FwHint.encodeFormat; | ||
FwHint.encodeFormat = format; | ||
try { | ||
cb(); | ||
} | ||
static decodeFrom(decoder) { | ||
return DelEVD.decode(new Delegation(), decoder); | ||
finally { | ||
FwHint.encodeFormat = prevFmt; | ||
} | ||
encodeTo(encoder) { | ||
encoder.prependTlv(TT.Delegation, [TT.Preference, NNI(this.preference)], this.name); | ||
} | ||
} | ||
FwHint.Delegation = Delegation; | ||
FwHint.withEncodeFormat = withEncodeFormat; | ||
})(FwHint || (FwHint = {})); |
@@ -1,53 +0,55 @@ | ||
import { Decoder, Encoder, EvDecoder, NNI, toHex } from "@ndn/tlv"; | ||
import { Encoder, EvDecoder, NNI } from "@ndn/tlv"; | ||
import { TT } from "./an_node.js"; | ||
import { Name } from "./name/mod_node.js"; | ||
const DelEVD = new EvDecoder("Delegation", TT.Delegation) | ||
.add(TT.Preference, (t, { nni }) => t.preference = nni) | ||
.add(TT.Name, (t, { decoder }) => t.name = decoder.decode(Name)); | ||
.add(TT.Preference, () => undefined) | ||
.add(TT.Name, (t, { decoder }) => t.name = decoder.decode(Name), { required: true }); | ||
const DelsEVD = new EvDecoder("FwHint") | ||
.add(TT.Delegation, (t, { decoder }) => t.push(decoder.decode(FwHint.Delegation)), { repeat: true }); | ||
.add(TT.Name, (t, { decoder }) => t.push(decoder.decode(Name)), { order: 1, repeat: true }) | ||
.add(TT.Delegation, (t, { decoder }) => t.push(DelEVD.decode({}, decoder).name), { order: 1, repeat: true }); | ||
/** ForwardingHint in Interest. */ | ||
export class FwHint { | ||
constructor(arg) { | ||
this.m = new Map(); | ||
this.delegations = []; | ||
if (Array.isArray(arg)) { | ||
for (const del of arg) { | ||
this.add(del); | ||
for (const name of arg) { | ||
this.delegations.push(Name.from(name)); | ||
} | ||
} | ||
else if (arg instanceof FwHint) { | ||
this.m = new Map(arg.m); | ||
this.delegations = [...arg.delegations]; | ||
} | ||
else if (Name.isNameLike(arg)) { | ||
this.add(new FwHint.Delegation(arg)); | ||
this.delegations = [Name.from(arg)]; | ||
} | ||
} | ||
static decodeValue(value) { | ||
return new FwHint(DelsEVD.decodeValue([], new Decoder(value))); | ||
static decodeValue(vd) { | ||
const t = new FwHint(); | ||
DelsEVD.decodeValue(t.delegations, vd); | ||
return t; | ||
} | ||
add(del) { | ||
this.m.set(toHex(del.name.value), del); | ||
} | ||
get delegations() { | ||
return Array.from(this.m.values()).sort((a, b) => a.preference - b.preference); | ||
} | ||
encodeTo(encoder) { | ||
encoder.prependTlv(TT.ForwardingHint, Encoder.OmitEmpty, ...this.delegations); | ||
switch (FwHint.encodeFormat) { | ||
case 2017: | ||
encoder.prependTlv(TT.ForwardingHint, Encoder.OmitEmpty, ...this.delegations.map((name, i) => [TT.Delegation, [TT.Preference, NNI(i)], name])); | ||
break; | ||
case 2021: | ||
encoder.prependTlv(TT.ForwardingHint, Encoder.OmitEmpty, ...this.delegations); | ||
break; | ||
} | ||
} | ||
} | ||
(function (FwHint) { | ||
/** Delegation in ForwardingHint. */ | ||
class Delegation { | ||
constructor(name = "", preference = 0) { | ||
this.preference = preference; | ||
this.name = new Name(name); | ||
FwHint.encodeFormat = 2017; | ||
function withEncodeFormat(format, cb) { | ||
const prevFmt = FwHint.encodeFormat; | ||
FwHint.encodeFormat = format; | ||
try { | ||
cb(); | ||
} | ||
static decodeFrom(decoder) { | ||
return DelEVD.decode(new Delegation(), decoder); | ||
finally { | ||
FwHint.encodeFormat = prevFmt; | ||
} | ||
encodeTo(encoder) { | ||
encoder.prependTlv(TT.Delegation, [TT.Preference, NNI(this.preference)], this.name); | ||
} | ||
} | ||
FwHint.Delegation = Delegation; | ||
FwHint.withEncodeFormat = withEncodeFormat; | ||
})(FwHint || (FwHint = {})); |
@@ -1,23 +0,21 @@ | ||
import { Decoder, Encoder } from "@ndn/tlv"; | ||
import { Name, NameLike } from "./name/mod"; | ||
import { type Decoder, Encoder } from "@ndn/tlv"; | ||
import { type NameLike, Name } from "./name/mod"; | ||
/** ForwardingHint in Interest. */ | ||
export declare class FwHint { | ||
static decodeValue(value: Uint8Array): FwHint; | ||
static decodeValue(vd: Decoder): FwHint; | ||
constructor(copy?: FwHint); | ||
constructor(name: NameLike); | ||
constructor(delegations: readonly FwHint.Delegation[]); | ||
private add; | ||
get delegations(): readonly FwHint.Delegation[]; | ||
private readonly m; | ||
constructor(delegations: readonly NameLike[]); | ||
delegations: Name[]; | ||
encodeTo(encoder: Encoder): void; | ||
} | ||
export declare namespace FwHint { | ||
/** Delegation in ForwardingHint. */ | ||
class Delegation { | ||
preference: number; | ||
static decodeFrom(decoder: Decoder): Delegation; | ||
constructor(name?: NameLike, preference?: number); | ||
name: Name; | ||
encodeTo(encoder: Encoder): void; | ||
} | ||
/** | ||
* ForwardingHint encoding format. | ||
* 2017: ForwardingHint = T L 1*Delegation, Delegation = T L Preference Name | ||
* 2021: ForwardingHint = T L 1*Name | ||
*/ | ||
type EncodeFormat = 2017 | 2021; | ||
let encodeFormat: FwHint.EncodeFormat; | ||
function withEncodeFormat(format: EncodeFormat, cb: () => void): void; | ||
} |
@@ -1,8 +0,6 @@ | ||
import { __importDefault, __importStar } from "tslib"; | ||
import { Encoder, EvDecoder, NNI } from "@ndn/tlv"; | ||
import _cjsDefaultImport0 from "minimalistic-assert"; const assert = __importDefault(_cjsDefaultImport0).default; | ||
import { assert, sha256 } from "@ndn/util"; | ||
import { TT } from "./an_browser.js"; | ||
import { FwHint } from "./fwhint_browser.js"; | ||
import { Name, ParamsDigest } from "./name/mod_browser.js"; | ||
import { sha256 } from "./security/helper_browser.js"; | ||
import { LLSign, LLVerify } from "./security/signing_browser.js"; | ||
@@ -22,10 +20,4 @@ import { SigInfo } from "./sig-info_browser.js"; | ||
if (Name.isNameLike(arg)) { | ||
this.name = new Name(arg); | ||
this.name = Name.from(arg); | ||
} | ||
else if (arg === Interest.CanBePrefix) { | ||
this.canBePrefix = true; | ||
} | ||
else if (arg === Interest.MustBeFresh) { | ||
this.mustBeFresh = true; | ||
} | ||
else if (arg instanceof FwHint) { | ||
@@ -55,5 +47,14 @@ this.fwHint = new FwHint(arg); | ||
} | ||
const FIELD_LIST = ["name", "canBePrefix", "mustBeFresh", "fwHint", "nonce", "lifetime", "hopLimit", "appParameters", "sigInfo", "sigValue"]; | ||
const FIELD_SIGNED_LIST = new Set(["name", "appParameters", "sigInfo"]); | ||
const FIELD_PARAMS_LIST = new Set(["appParameters", "sigInfo", "sigValue"]); | ||
const FIELD_LIST = { | ||
name: ["signedPortion"], | ||
canBePrefix: [], | ||
mustBeFresh: [], | ||
fwHint: [], | ||
nonce: [], | ||
lifetime: [], | ||
hopLimit: [], | ||
appParameters: ["signedPortion", "paramsPortion"], | ||
sigInfo: ["signedPortion", "paramsPortion"], | ||
sigValue: ["paramsPortion"], | ||
}; | ||
const EVD = new EvDecoder("Interest", TT.Interest) | ||
@@ -63,3 +64,3 @@ .add(TT.Name, (t, { decoder }) => t.name = decoder.decode(Name), { required: true }) | ||
.add(TT.MustBeFresh, (t) => t.mustBeFresh = true) | ||
.add(TT.ForwardingHint, (t, { value }) => t.fwHint = FwHint.decodeValue(value)) | ||
.add(TT.ForwardingHint, (t, { vd }) => t.fwHint = FwHint.decodeValue(vd)) | ||
.add(TT.Nonce, (t, { value }) => t.nonce = NNI.decode(value, { len: 4 })) | ||
@@ -104,2 +105,3 @@ .add(TT.InterestLifetime, (t, { nni }) => t.lifetime = nni) | ||
* - Interest.MustBeFresh | ||
* - FwHint | ||
* - Interest.Nonce(v) | ||
@@ -201,3 +203,3 @@ * - Interest.Lifetime(v) | ||
} | ||
for (const field of FIELD_LIST) { | ||
for (const [field, clearing] of Object.entries(FIELD_LIST)) { | ||
Object.defineProperty(Interest.prototype, field, { | ||
@@ -209,8 +211,5 @@ enumerable: true, | ||
f[field] = v; | ||
if (FIELD_SIGNED_LIST.has(field)) { | ||
f.signedPortion = undefined; | ||
for (const c of clearing) { | ||
f[c] = undefined; | ||
} | ||
if (FIELD_PARAMS_LIST.has(field)) { | ||
f.paramsPortion = undefined; | ||
} | ||
}, | ||
@@ -221,7 +220,5 @@ }); | ||
(function (Interest) { | ||
/** Signer that calculates ParamsDigest. */ | ||
Interest.Parameterize = () => Promise.resolve(new Uint8Array()); | ||
/** Generate a random nonce. */ | ||
function generateNonce() { | ||
return Math.floor(Math.random() * 0x100000000); | ||
return Math.trunc(Math.random() * 0x100000000); | ||
} | ||
@@ -232,5 +229,9 @@ Interest.generateNonce = generateNonce; | ||
/** Constructor argument to set CanBePrefix flag. */ | ||
Interest.CanBePrefix = Symbol("Interest.CanBePrefix"); | ||
Interest.CanBePrefix = { | ||
[ctorAssign](f) { f.canBePrefix = true; }, | ||
}; | ||
/** Constructor argument to set MustBeFresh flag. */ | ||
Interest.MustBeFresh = Symbol("Interest.MustBeFresh"); | ||
Interest.MustBeFresh = { | ||
[ctorAssign](f) { f.mustBeFresh = true; }, | ||
}; | ||
/** Constructor argument to set Nonce field. */ | ||
@@ -259,25 +260,16 @@ function Nonce(v = generateNonce()) { | ||
function makeModifyFunc(input) { | ||
switch (typeof input) { | ||
case "function": | ||
return input; | ||
case "undefined": | ||
return () => undefined; | ||
if (!input) { | ||
return () => undefined; | ||
} | ||
const { canBePrefix, mustBeFresh, fwHint, lifetime, hopLimit, } = input; | ||
if (typeof input === "function") { | ||
return input; | ||
} | ||
const patch = {}; | ||
for (const key of ["canBePrefix", "mustBeFresh", "fwHint", "lifetime", "hopLimit"]) { | ||
if (input[key] !== undefined) { | ||
patch[key] = input[key]; | ||
} | ||
} | ||
return (interest) => { | ||
if (canBePrefix !== undefined) { | ||
interest.canBePrefix = canBePrefix; | ||
} | ||
if (mustBeFresh !== undefined) { | ||
interest.mustBeFresh = mustBeFresh; | ||
} | ||
if (fwHint !== undefined) { | ||
interest.fwHint = fwHint; | ||
} | ||
if (lifetime !== undefined) { | ||
interest.lifetime = lifetime; | ||
} | ||
if (hopLimit !== undefined) { | ||
interest.hopLimit = hopLimit; | ||
} | ||
Object.assign(interest, patch); | ||
}; | ||
@@ -284,0 +276,0 @@ } |
@@ -1,8 +0,6 @@ | ||
import { __importDefault, __importStar } from "tslib"; | ||
import { Encoder, EvDecoder, NNI } from "@ndn/tlv"; | ||
import _cjsDefaultImport0 from "minimalistic-assert"; const assert = __importDefault(_cjsDefaultImport0).default; | ||
import { assert, sha256 } from "@ndn/util"; | ||
import { TT } from "./an_node.js"; | ||
import { FwHint } from "./fwhint_node.js"; | ||
import { Name, ParamsDigest } from "./name/mod_node.js"; | ||
import { sha256 } from "./security/helper_node.js"; | ||
import { LLSign, LLVerify } from "./security/signing_node.js"; | ||
@@ -22,10 +20,4 @@ import { SigInfo } from "./sig-info_node.js"; | ||
if (Name.isNameLike(arg)) { | ||
this.name = new Name(arg); | ||
this.name = Name.from(arg); | ||
} | ||
else if (arg === Interest.CanBePrefix) { | ||
this.canBePrefix = true; | ||
} | ||
else if (arg === Interest.MustBeFresh) { | ||
this.mustBeFresh = true; | ||
} | ||
else if (arg instanceof FwHint) { | ||
@@ -55,5 +47,14 @@ this.fwHint = new FwHint(arg); | ||
} | ||
const FIELD_LIST = ["name", "canBePrefix", "mustBeFresh", "fwHint", "nonce", "lifetime", "hopLimit", "appParameters", "sigInfo", "sigValue"]; | ||
const FIELD_SIGNED_LIST = new Set(["name", "appParameters", "sigInfo"]); | ||
const FIELD_PARAMS_LIST = new Set(["appParameters", "sigInfo", "sigValue"]); | ||
const FIELD_LIST = { | ||
name: ["signedPortion"], | ||
canBePrefix: [], | ||
mustBeFresh: [], | ||
fwHint: [], | ||
nonce: [], | ||
lifetime: [], | ||
hopLimit: [], | ||
appParameters: ["signedPortion", "paramsPortion"], | ||
sigInfo: ["signedPortion", "paramsPortion"], | ||
sigValue: ["paramsPortion"], | ||
}; | ||
const EVD = new EvDecoder("Interest", TT.Interest) | ||
@@ -63,3 +64,3 @@ .add(TT.Name, (t, { decoder }) => t.name = decoder.decode(Name), { required: true }) | ||
.add(TT.MustBeFresh, (t) => t.mustBeFresh = true) | ||
.add(TT.ForwardingHint, (t, { value }) => t.fwHint = FwHint.decodeValue(value)) | ||
.add(TT.ForwardingHint, (t, { vd }) => t.fwHint = FwHint.decodeValue(vd)) | ||
.add(TT.Nonce, (t, { value }) => t.nonce = NNI.decode(value, { len: 4 })) | ||
@@ -104,2 +105,3 @@ .add(TT.InterestLifetime, (t, { nni }) => t.lifetime = nni) | ||
* - Interest.MustBeFresh | ||
* - FwHint | ||
* - Interest.Nonce(v) | ||
@@ -201,3 +203,3 @@ * - Interest.Lifetime(v) | ||
} | ||
for (const field of FIELD_LIST) { | ||
for (const [field, clearing] of Object.entries(FIELD_LIST)) { | ||
Object.defineProperty(Interest.prototype, field, { | ||
@@ -209,8 +211,5 @@ enumerable: true, | ||
f[field] = v; | ||
if (FIELD_SIGNED_LIST.has(field)) { | ||
f.signedPortion = undefined; | ||
for (const c of clearing) { | ||
f[c] = undefined; | ||
} | ||
if (FIELD_PARAMS_LIST.has(field)) { | ||
f.paramsPortion = undefined; | ||
} | ||
}, | ||
@@ -221,7 +220,5 @@ }); | ||
(function (Interest) { | ||
/** Signer that calculates ParamsDigest. */ | ||
Interest.Parameterize = () => Promise.resolve(new Uint8Array()); | ||
/** Generate a random nonce. */ | ||
function generateNonce() { | ||
return Math.floor(Math.random() * 0x100000000); | ||
return Math.trunc(Math.random() * 0x100000000); | ||
} | ||
@@ -232,5 +229,9 @@ Interest.generateNonce = generateNonce; | ||
/** Constructor argument to set CanBePrefix flag. */ | ||
Interest.CanBePrefix = Symbol("Interest.CanBePrefix"); | ||
Interest.CanBePrefix = { | ||
[ctorAssign](f) { f.canBePrefix = true; }, | ||
}; | ||
/** Constructor argument to set MustBeFresh flag. */ | ||
Interest.MustBeFresh = Symbol("Interest.MustBeFresh"); | ||
Interest.MustBeFresh = { | ||
[ctorAssign](f) { f.mustBeFresh = true; }, | ||
}; | ||
/** Constructor argument to set Nonce field. */ | ||
@@ -259,25 +260,16 @@ function Nonce(v = generateNonce()) { | ||
function makeModifyFunc(input) { | ||
switch (typeof input) { | ||
case "function": | ||
return input; | ||
case "undefined": | ||
return () => undefined; | ||
if (!input) { | ||
return () => undefined; | ||
} | ||
const { canBePrefix, mustBeFresh, fwHint, lifetime, hopLimit, } = input; | ||
if (typeof input === "function") { | ||
return input; | ||
} | ||
const patch = {}; | ||
for (const key of ["canBePrefix", "mustBeFresh", "fwHint", "lifetime", "hopLimit"]) { | ||
if (input[key] !== undefined) { | ||
patch[key] = input[key]; | ||
} | ||
} | ||
return (interest) => { | ||
if (canBePrefix !== undefined) { | ||
interest.canBePrefix = canBePrefix; | ||
} | ||
if (mustBeFresh !== undefined) { | ||
interest.mustBeFresh = mustBeFresh; | ||
} | ||
if (fwHint !== undefined) { | ||
interest.fwHint = fwHint; | ||
} | ||
if (lifetime !== undefined) { | ||
interest.lifetime = lifetime; | ||
} | ||
if (hopLimit !== undefined) { | ||
interest.hopLimit = hopLimit; | ||
} | ||
Object.assign(interest, patch); | ||
}; | ||
@@ -284,0 +276,0 @@ } |
@@ -1,4 +0,4 @@ | ||
import { Decoder, Encoder } from "@ndn/tlv"; | ||
import { type Decoder, Encoder } from "@ndn/tlv"; | ||
import { FwHint } from "./fwhint"; | ||
import { Name, NameLike } from "./name/mod"; | ||
import { type NameLike, Name } from "./name/mod"; | ||
import { LLSign, LLVerify, Signer, Verifier } from "./security/signing"; | ||
@@ -38,2 +38,3 @@ import { SigInfo } from "./sig-info"; | ||
* - Interest.MustBeFresh | ||
* - FwHint | ||
* - Interest.Nonce(v) | ||
@@ -62,4 +63,2 @@ * - Interest.Lifetime(v) | ||
export declare namespace Interest { | ||
/** Signer that calculates ParamsDigest. */ | ||
const Parameterize: LLSign; | ||
/** Generate a random nonce. */ | ||
@@ -70,5 +69,5 @@ function generateNonce(): number; | ||
/** Constructor argument to set CanBePrefix flag. */ | ||
const CanBePrefix: unique symbol; | ||
const CanBePrefix: CtorTag; | ||
/** Constructor argument to set MustBeFresh flag. */ | ||
const MustBeFresh: unique symbol; | ||
const MustBeFresh: CtorTag; | ||
/** Constructor argument to set Nonce field. */ | ||
@@ -81,13 +80,7 @@ function Nonce(v?: number): CtorTag; | ||
/** Constructor argument. */ | ||
type CtorArg = NameLike | typeof CanBePrefix | typeof MustBeFresh | FwHint | CtorTag | Uint8Array; | ||
type CtorArg = NameLike | FwHint | CtorTag | Uint8Array; | ||
/** A function to modify an existing Interest. */ | ||
type ModifyFunc = (interest: Interest) => void; | ||
/** Common fields to assign onto an existing Interest. */ | ||
interface ModifyFields { | ||
canBePrefix?: boolean; | ||
mustBeFresh?: boolean; | ||
fwHint?: FwHint; | ||
lifetime?: number; | ||
hopLimit?: number; | ||
} | ||
type ModifyFields = Partial<Pick<Fields, "canBePrefix" | "mustBeFresh" | "fwHint" | "lifetime" | "hopLimit">>; | ||
/** A structure to modify an existing Interest. */ | ||
@@ -94,0 +87,0 @@ type Modify = ModifyFunc | ModifyFields; |
@@ -12,3 +12,3 @@ import { Encoder, EvDecoder } from "@ndn/tlv"; | ||
if (Name.isNameLike(arg)) { | ||
this.name = new Name(arg); | ||
this.name = Name.from(arg); | ||
} | ||
@@ -38,11 +38,13 @@ else if (arg instanceof Uint8Array) { | ||
KeyLocator.isCtorArg = isCtorArg; | ||
/** Throw if KeyLocator is missing or does not have Name. */ | ||
/** | ||
* Extract KeyLocator name. | ||
* @throws KeyLocator is missing or does not have Name. | ||
*/ | ||
function mustGetName(kl) { | ||
const name = kl?.name; | ||
if (!name) { | ||
if (!kl || !kl.name) { | ||
throw new Error("KeyLocator does not have name"); | ||
} | ||
return name; | ||
return kl.name; | ||
} | ||
KeyLocator.mustGetName = mustGetName; | ||
})(KeyLocator || (KeyLocator = {})); |
@@ -12,3 +12,3 @@ import { Encoder, EvDecoder } from "@ndn/tlv"; | ||
if (Name.isNameLike(arg)) { | ||
this.name = new Name(arg); | ||
this.name = Name.from(arg); | ||
} | ||
@@ -38,11 +38,13 @@ else if (arg instanceof Uint8Array) { | ||
KeyLocator.isCtorArg = isCtorArg; | ||
/** Throw if KeyLocator is missing or does not have Name. */ | ||
/** | ||
* Extract KeyLocator name. | ||
* @throws KeyLocator is missing or does not have Name. | ||
*/ | ||
function mustGetName(kl) { | ||
const name = kl?.name; | ||
if (!name) { | ||
if (!kl || !kl.name) { | ||
throw new Error("KeyLocator does not have name"); | ||
} | ||
return name; | ||
return kl.name; | ||
} | ||
KeyLocator.mustGetName = mustGetName; | ||
})(KeyLocator || (KeyLocator = {})); |
@@ -1,3 +0,3 @@ | ||
import { Decoder, Encoder } from "@ndn/tlv"; | ||
import { Name, NameLike } from "./name/mod"; | ||
import { type Decoder, Encoder } from "@ndn/tlv"; | ||
import { type NameLike, Name } from "./name/mod"; | ||
/** KeyLocator in SigInfo. */ | ||
@@ -14,4 +14,7 @@ export declare class KeyLocator { | ||
function isCtorArg(arg: unknown): arg is CtorArg; | ||
/** Throw if KeyLocator is missing or does not have Name. */ | ||
/** | ||
* Extract KeyLocator name. | ||
* @throws KeyLocator is missing or does not have Name. | ||
*/ | ||
function mustGetName(kl?: KeyLocator): Name; | ||
} |
@@ -1,2 +0,2 @@ | ||
import { Encoder, EvDecoder, NNI } from "@ndn/tlv"; | ||
import { EvDecoder, NNI } from "@ndn/tlv"; | ||
import { NackReason, TT } from "./an_browser.js"; | ||
@@ -17,4 +17,3 @@ const EVD = new EvDecoder("NackHeader", TT.Nack) | ||
encodeTo(encoder) { | ||
encoder.prependTlv(TT.Nack, [TT.NackReason, Encoder.OmitEmpty, | ||
this.reason_ > 0 ? NNI(this.reason_) : undefined]); | ||
encoder.prependTlv(TT.Nack, this.reason_ > 0 ? [TT.NackReason, NNI(this.reason_)] : undefined); | ||
} | ||
@@ -21,0 +20,0 @@ } |
@@ -1,2 +0,2 @@ | ||
import { Encoder, EvDecoder, NNI } from "@ndn/tlv"; | ||
import { EvDecoder, NNI } from "@ndn/tlv"; | ||
import { NackReason, TT } from "./an_node.js"; | ||
@@ -17,4 +17,3 @@ const EVD = new EvDecoder("NackHeader", TT.Nack) | ||
encodeTo(encoder) { | ||
encoder.prependTlv(TT.Nack, [TT.NackReason, Encoder.OmitEmpty, | ||
this.reason_ > 0 ? NNI(this.reason_) : undefined]); | ||
encoder.prependTlv(TT.Nack, this.reason_ > 0 ? [TT.NackReason, NNI(this.reason_)] : undefined); | ||
} | ||
@@ -21,0 +20,0 @@ } |
@@ -1,2 +0,2 @@ | ||
import { Decoder, Encoder } from "@ndn/tlv"; | ||
import { type Decoder, Encoder } from "@ndn/tlv"; | ||
import type { Interest } from "./interest"; | ||
@@ -3,0 +3,0 @@ /** Nack header. */ |
@@ -1,2 +0,2 @@ | ||
import { toHex } from "@ndn/tlv"; | ||
import { toHex } from "@ndn/util"; | ||
/** | ||
@@ -3,0 +3,0 @@ * Name longest prefix match algorithm. |
@@ -1,2 +0,2 @@ | ||
import { toHex } from "@ndn/tlv"; | ||
import { toHex } from "@ndn/util"; | ||
/** | ||
@@ -3,0 +3,0 @@ * Name longest prefix match algorithm. |
@@ -20,11 +20,11 @@ import { Component } from "./component"; | ||
/** Print component in alternate URI syntax */ | ||
ofComponent: (comp: Component) => string; | ||
readonly ofComponent: (comp: Component) => string; | ||
/** Print name in alternate URI syntax. */ | ||
ofName: (name: Name) => string; | ||
readonly ofName: (name: Name) => string; | ||
/** Parse component from alternate URI syntax */ | ||
parseComponent: (input: string) => Component; | ||
readonly parseComponent: (input: string) => Component; | ||
/** Parse name from alternate URI syntax. */ | ||
parseName: (input: string) => Name; | ||
readonly parseName: (input: string) => Name; | ||
} | ||
/** Print Generic, ImplicitDigest, ParamsDigest in alternate URI syntax. */ | ||
export declare const AltUri: AltUriConverter; |
import { __importDefault, __importStar } from "tslib"; | ||
import { Decoder, Encoder, fromUtf8, toUtf8 } from "@ndn/tlv"; | ||
import { Decoder, Encoder } from "@ndn/tlv"; | ||
import { fromHex, fromUtf8, toHex, toUtf8 } from "@ndn/util"; | ||
import _cjsDefaultImport0 from "buffer-compare"; const bufferCompare = __importDefault(_cjsDefaultImport0).default; | ||
import { TT } from "../an_browser.js"; | ||
function checkType(t) { | ||
return Number.isFinite(t) && t >= 0x01 && t <= 0xFFFF; | ||
return Number.isInteger(t) && t >= 0x01 && t <= 0xFFFF; | ||
} | ||
@@ -13,13 +14,9 @@ function assertType(t) { | ||
} | ||
const CHAR_ENCODE = (() => { | ||
const UNESCAPED = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~"; | ||
const a = []; | ||
for (let ch = 0x00; ch <= 0xFF; ++ch) { | ||
const s = String.fromCharCode(ch); | ||
a.push(UNESCAPED.includes(s) ? s : `%${ch.toString(16).padStart(2, "0").toUpperCase()}`); | ||
} | ||
return a; | ||
})(); | ||
const CHARCODE_PERCENT = "%".charCodeAt(0); | ||
const CHARCODE_PERIOD = ".".charCodeAt(0); | ||
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); | ||
/** | ||
@@ -30,32 +27,16 @@ * Name component. | ||
export class Component { | ||
constructor(arg1, arg2) { | ||
switch (typeof arg1) { | ||
case "object": { | ||
this.tlv = arg1; | ||
const decoder = new Decoder(arg1); | ||
({ type: this.type, value: this.value } = decoder.read()); | ||
assertType(this.type); | ||
return; | ||
} | ||
case "undefined": | ||
this.type = TT.GenericNameComponent; | ||
break; | ||
case "number": | ||
this.type = arg1; | ||
assertType(this.type); | ||
break; | ||
constructor(arg1 = TT.GenericNameComponent, value = new Uint8Array()) { | ||
if (arg1 instanceof Uint8Array) { | ||
this.tlv = arg1; | ||
const decoder = new Decoder(arg1); | ||
({ type: this.type, value: this.value } = decoder.read()); | ||
assertType(this.type); | ||
return; | ||
} | ||
switch (typeof arg2) { | ||
case "undefined": | ||
this.value = new Uint8Array(); | ||
break; | ||
case "string": | ||
this.value = toUtf8(arg2); | ||
break; | ||
case "object": | ||
this.value = arg2; | ||
break; | ||
} | ||
this.type = arg1; | ||
assertType(this.type); | ||
this.value = typeof value === "string" ? toUtf8(value) : value; | ||
this.tlv = Encoder.encode([this.type, this.value], 10 + this.value.length); | ||
} | ||
/** TLV-LENGTH. */ | ||
get length() { | ||
@@ -77,24 +58,20 @@ return this.value.length; | ||
} | ||
let [sType, sValue] = input.split("=", 2); | ||
let type = TT.GenericNameComponent; | ||
let iType; | ||
if (sValue === undefined) { | ||
[sType, sValue] = ["", sType]; | ||
let posValue = 0; | ||
const posEqual = input.indexOf("="); | ||
if (posEqual >= 1) { | ||
const iType = Number.parseInt(input, 10); | ||
if (checkType(iType)) { | ||
type = iType; | ||
posValue = posEqual + 1; | ||
} | ||
} | ||
else if (checkType(iType = Number.parseInt(sType, 10))) { | ||
type = iType; | ||
} | ||
else { | ||
[sType, sValue] = ["", input]; | ||
} | ||
if (/^\.*$/.test(sValue)) { | ||
sValue = sValue.slice(3); | ||
} | ||
const value = new Uint8Array(sValue.length); | ||
const value = new Uint8Array(input.length - posValue); | ||
let length = 0; | ||
for (let i = 0; i < sValue.length;) { | ||
let ch = sValue.charCodeAt(i); | ||
let hex; | ||
if (ch === CHARCODE_PERCENT && /^[\da-f]{2}$/i.test(hex = sValue.slice(i + 1, i + 3))) { | ||
ch = Number.parseInt(hex, 16); | ||
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; | ||
@@ -105,4 +82,7 @@ } | ||
} | ||
value[length++] = ch; | ||
value[length++] = b; | ||
} | ||
if (!hasNonPeriods && length >= 3) { | ||
length -= 3; | ||
} | ||
return new Component(type, value.subarray(0, length)); | ||
@@ -112,12 +92,12 @@ } | ||
toString() { | ||
let b = `${this.type}=`; | ||
let s = `${this.type}=`; | ||
let hasNonPeriods = false; | ||
for (const ch of this.value) { | ||
hasNonPeriods || (hasNonPeriods = ch !== CHARCODE_PERIOD); | ||
b += CHAR_ENCODE[ch]; | ||
for (const b of this.value) { | ||
hasNonPeriods ||= b !== CODEPOINT_PERIOD; | ||
s += CHAR_ENCODE[b]; | ||
} | ||
if (!hasNonPeriods) { | ||
b += "..."; | ||
s += "..."; | ||
} | ||
return b; | ||
return s; | ||
} | ||
@@ -140,3 +120,5 @@ encodeTo(encoder) { | ||
compare(other) { | ||
return Component.compare(this, other); | ||
const rhs = Component.from(other); | ||
return 2 * Math.sign(this.type - rhs.type || this.length - rhs.length || | ||
bufferCompare(this.value, rhs.value)); | ||
} | ||
@@ -159,15 +141,2 @@ /** Determine if this component equals other. */ | ||
})(CompareResult = Component.CompareResult || (Component.CompareResult = {})); | ||
function toCompareResult(diff) { | ||
return diff === 0 ? CompareResult.EQUAL : | ||
diff < 0 ? CompareResult.LT : CompareResult.GT; | ||
} | ||
/** Compare two components. */ | ||
function compare(lhs, rhs) { | ||
const l = Component.from(lhs); | ||
const r = Component.from(rhs); | ||
return toCompareResult(l.type - r.type) || | ||
toCompareResult(l.length - r.length) || | ||
toCompareResult(bufferCompare(l.value, r.value)); | ||
} | ||
Component.compare = compare; | ||
})(Component || (Component = {})); |
import { __importDefault, __importStar } from "tslib"; | ||
import { Decoder, Encoder, fromUtf8, toUtf8 } from "@ndn/tlv"; | ||
import { Decoder, Encoder } from "@ndn/tlv"; | ||
import { fromHex, fromUtf8, toHex, toUtf8 } from "@ndn/util"; | ||
import _cjsDefaultImport0 from "buffer-compare"; const bufferCompare = __importDefault(_cjsDefaultImport0).default; | ||
import { TT } from "../an_node.js"; | ||
function checkType(t) { | ||
return Number.isFinite(t) && t >= 0x01 && t <= 0xFFFF; | ||
return Number.isInteger(t) && t >= 0x01 && t <= 0xFFFF; | ||
} | ||
@@ -13,13 +14,9 @@ function assertType(t) { | ||
} | ||
const CHAR_ENCODE = (() => { | ||
const UNESCAPED = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~"; | ||
const a = []; | ||
for (let ch = 0x00; ch <= 0xFF; ++ch) { | ||
const s = String.fromCharCode(ch); | ||
a.push(UNESCAPED.includes(s) ? s : `%${ch.toString(16).padStart(2, "0").toUpperCase()}`); | ||
} | ||
return a; | ||
})(); | ||
const CHARCODE_PERCENT = "%".charCodeAt(0); | ||
const CHARCODE_PERIOD = ".".charCodeAt(0); | ||
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); | ||
/** | ||
@@ -30,32 +27,16 @@ * Name component. | ||
export class Component { | ||
constructor(arg1, arg2) { | ||
switch (typeof arg1) { | ||
case "object": { | ||
this.tlv = arg1; | ||
const decoder = new Decoder(arg1); | ||
({ type: this.type, value: this.value } = decoder.read()); | ||
assertType(this.type); | ||
return; | ||
} | ||
case "undefined": | ||
this.type = TT.GenericNameComponent; | ||
break; | ||
case "number": | ||
this.type = arg1; | ||
assertType(this.type); | ||
break; | ||
constructor(arg1 = TT.GenericNameComponent, value = new Uint8Array()) { | ||
if (arg1 instanceof Uint8Array) { | ||
this.tlv = arg1; | ||
const decoder = new Decoder(arg1); | ||
({ type: this.type, value: this.value } = decoder.read()); | ||
assertType(this.type); | ||
return; | ||
} | ||
switch (typeof arg2) { | ||
case "undefined": | ||
this.value = new Uint8Array(); | ||
break; | ||
case "string": | ||
this.value = toUtf8(arg2); | ||
break; | ||
case "object": | ||
this.value = arg2; | ||
break; | ||
} | ||
this.type = arg1; | ||
assertType(this.type); | ||
this.value = typeof value === "string" ? toUtf8(value) : value; | ||
this.tlv = Encoder.encode([this.type, this.value], 10 + this.value.length); | ||
} | ||
/** TLV-LENGTH. */ | ||
get length() { | ||
@@ -77,24 +58,20 @@ return this.value.length; | ||
} | ||
let [sType, sValue] = input.split("=", 2); | ||
let type = TT.GenericNameComponent; | ||
let iType; | ||
if (sValue === undefined) { | ||
[sType, sValue] = ["", sType]; | ||
let posValue = 0; | ||
const posEqual = input.indexOf("="); | ||
if (posEqual >= 1) { | ||
const iType = Number.parseInt(input, 10); | ||
if (checkType(iType)) { | ||
type = iType; | ||
posValue = posEqual + 1; | ||
} | ||
} | ||
else if (checkType(iType = Number.parseInt(sType, 10))) { | ||
type = iType; | ||
} | ||
else { | ||
[sType, sValue] = ["", input]; | ||
} | ||
if (/^\.*$/.test(sValue)) { | ||
sValue = sValue.slice(3); | ||
} | ||
const value = new Uint8Array(sValue.length); | ||
const value = new Uint8Array(input.length - posValue); | ||
let length = 0; | ||
for (let i = 0; i < sValue.length;) { | ||
let ch = sValue.charCodeAt(i); | ||
let hex; | ||
if (ch === CHARCODE_PERCENT && /^[\da-f]{2}$/i.test(hex = sValue.slice(i + 1, i + 3))) { | ||
ch = Number.parseInt(hex, 16); | ||
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; | ||
@@ -105,4 +82,7 @@ } | ||
} | ||
value[length++] = ch; | ||
value[length++] = b; | ||
} | ||
if (!hasNonPeriods && length >= 3) { | ||
length -= 3; | ||
} | ||
return new Component(type, value.subarray(0, length)); | ||
@@ -112,12 +92,12 @@ } | ||
toString() { | ||
let b = `${this.type}=`; | ||
let s = `${this.type}=`; | ||
let hasNonPeriods = false; | ||
for (const ch of this.value) { | ||
hasNonPeriods || (hasNonPeriods = ch !== CHARCODE_PERIOD); | ||
b += CHAR_ENCODE[ch]; | ||
for (const b of this.value) { | ||
hasNonPeriods ||= b !== CODEPOINT_PERIOD; | ||
s += CHAR_ENCODE[b]; | ||
} | ||
if (!hasNonPeriods) { | ||
b += "..."; | ||
s += "..."; | ||
} | ||
return b; | ||
return s; | ||
} | ||
@@ -140,3 +120,5 @@ encodeTo(encoder) { | ||
compare(other) { | ||
return Component.compare(this, other); | ||
const rhs = Component.from(other); | ||
return 2 * Math.sign(this.type - rhs.type || this.length - rhs.length || | ||
bufferCompare(this.value, rhs.value)); | ||
} | ||
@@ -159,15 +141,2 @@ /** Determine if this component equals other. */ | ||
})(CompareResult = Component.CompareResult || (Component.CompareResult = {})); | ||
function toCompareResult(diff) { | ||
return diff === 0 ? CompareResult.EQUAL : | ||
diff < 0 ? CompareResult.LT : CompareResult.GT; | ||
} | ||
/** Compare two components. */ | ||
function compare(lhs, rhs) { | ||
const l = Component.from(lhs); | ||
const r = Component.from(rhs); | ||
return toCompareResult(l.type - r.type) || | ||
toCompareResult(l.length - r.length) || | ||
toCompareResult(bufferCompare(l.value, r.value)); | ||
} | ||
Component.compare = compare; | ||
})(Component || (Component = {})); |
import { Decoder, Encoder } from "@ndn/tlv"; | ||
import type { NamingConvention } from "./convention"; | ||
/** Name component or component URI. */ | ||
export declare type ComponentLike = Component | string; | ||
@@ -9,2 +10,3 @@ /** | ||
export declare class Component { | ||
/** TLV-LENGTH. */ | ||
get length(): number; | ||
@@ -16,4 +18,7 @@ /** TLV-VALUE interpreted as UTF-8 string. */ | ||
static from(input: ComponentLike): Component; | ||
/** Whole TLV. */ | ||
readonly tlv: Uint8Array; | ||
/** TLV-TYPE. */ | ||
readonly type: number; | ||
/** TLV-VALUE. */ | ||
readonly value: Uint8Array; | ||
@@ -51,4 +56,2 @@ /** | ||
} | ||
/** Compare two components. */ | ||
function compare(lhs: ComponentLike, rhs: ComponentLike): CompareResult; | ||
} |
@@ -1,2 +0,2 @@ | ||
import { fromHex, toHex } from "@ndn/tlv"; | ||
import { fromHex, toHex } from "@ndn/util"; | ||
import { TT } from "../an_browser.js"; | ||
@@ -9,3 +9,3 @@ import { Component } from "./component_browser.js"; | ||
this.altUriPrefix = altUriPrefix; | ||
this.altUriRegex = new RegExp(`^${altUriPrefix}=([0-9a-fA-F]{64})$`); | ||
this.altUriRegex = new RegExp(`^${altUriPrefix}=([0-9a-fA-F]{${2 * DIGEST_LENGTH}})$`); | ||
} | ||
@@ -12,0 +12,0 @@ match(comp) { |
@@ -1,2 +0,2 @@ | ||
import { fromHex, toHex } from "@ndn/tlv"; | ||
import { fromHex, toHex } from "@ndn/util"; | ||
import { TT } from "../an_node.js"; | ||
@@ -9,3 +9,3 @@ import { Component } from "./component_node.js"; | ||
this.altUriPrefix = altUriPrefix; | ||
this.altUriRegex = new RegExp(`^${altUriPrefix}=([0-9a-fA-F]{64})$`); | ||
this.altUriRegex = new RegExp(`^${altUriPrefix}=([0-9a-fA-F]{${2 * DIGEST_LENGTH}})$`); | ||
} | ||
@@ -12,0 +12,0 @@ match(comp) { |
@@ -7,1 +7,2 @@ export * from "./algo_browser.js"; | ||
export * from "./name_browser.js"; | ||
export * from "./name-map_browser.js"; |
@@ -7,1 +7,2 @@ export * from "./algo_node.js"; | ||
export * from "./name_node.js"; | ||
export * from "./name-map_node.js"; |
@@ -7,1 +7,2 @@ export * from "./algo"; | ||
export * from "./name"; | ||
export * from "./name-map"; |
import { Decoder, Encoder } from "@ndn/tlv"; | ||
import { toHex } from "@ndn/util"; | ||
import { TT } from "../an_browser.js"; | ||
@@ -9,16 +10,15 @@ import { Component } from "./component_browser.js"; | ||
export class Name { | ||
constructor(arg1, parseComponentUri = Component.from) { | ||
let valueEncoderBufSize = 256; | ||
constructor(arg1, parseComponent = Component.from) { | ||
switch (true) { | ||
case arg1 instanceof Name: { | ||
const other = arg1; | ||
this.value = other.value; | ||
this.comps = other.comps; | ||
return; | ||
this.value_ = other.value_; | ||
break; | ||
} | ||
case typeof arg1 === "string": { | ||
const uri = arg1; | ||
this.comps = uri.replace(/^(?:ndn:)?\/?/, "").split("/") | ||
.filter((comp) => comp !== "").map(parseComponentUri); | ||
valueEncoderBufSize = uri.length + 4 * this.comps.length; | ||
this.comps = uri.replace(/^(?:ndn:)?\/*/, "").split("/") | ||
.filter((comp) => comp !== "").map(parseComponent); | ||
this.valueEncoderBufSize = uri.length + 4 * this.comps.length; | ||
break; | ||
@@ -30,5 +30,5 @@ } | ||
case arg1 instanceof Uint8Array: { | ||
this.value = arg1; | ||
this.value_ = arg1; | ||
const comps = []; | ||
const decoder = new Decoder(this.value); | ||
const decoder = new Decoder(this.value_); | ||
while (!decoder.eof) { | ||
@@ -38,10 +38,9 @@ comps.push(decoder.decode(Component)); | ||
this.comps = comps; | ||
return; | ||
break; | ||
} | ||
default: // undefined | ||
this.value = new Uint8Array(); | ||
this.comps = []; | ||
return; | ||
this.valueEncoderBufSize = 0; | ||
break; | ||
} | ||
this.value = Encoder.encode(this.comps, valueEncoderBufSize); | ||
} | ||
@@ -52,5 +51,18 @@ static decodeFrom(decoder) { | ||
} | ||
/** Number of name components. */ | ||
get length() { | ||
return this.comps.length; | ||
} | ||
/** Name TLV-VALUE. */ | ||
get value() { | ||
if (!this.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. */ | ||
@@ -74,3 +86,4 @@ get(i) { | ||
toString() { | ||
return `/${this.comps.map((comp) => comp.toString()).join("/")}`; | ||
this.uri_ ??= `/${this.comps.map((comp) => comp.toString()).join("/")}`; | ||
return this.uri_; | ||
} | ||
@@ -86,3 +99,3 @@ /** Get sub name [begin, end). */ | ||
append(...args) { | ||
if (args.length === 2 && typeof args[0] === "object" && | ||
if (args.length === 2 && | ||
typeof args[0].create === "function") { | ||
@@ -102,3 +115,3 @@ return this.append(args[0].create(args[1])); | ||
compare(other) { | ||
const rhs = new Name(other); | ||
const rhs = Name.from(other); | ||
const commonSize = Math.min(this.length, rhs.length); | ||
@@ -137,2 +150,6 @@ for (let i = 0; i < commonSize; ++i) { | ||
Name.isNameLike = isNameLike; | ||
function from(input) { | ||
return input instanceof Name ? input : new Name(input); | ||
} | ||
Name.from = from; | ||
/** Name compare result. */ | ||
@@ -139,0 +156,0 @@ let CompareResult; |
import { Decoder, Encoder } from "@ndn/tlv"; | ||
import { toHex } from "@ndn/util"; | ||
import { TT } from "../an_node.js"; | ||
@@ -9,16 +10,15 @@ import { Component } from "./component_node.js"; | ||
export class Name { | ||
constructor(arg1, parseComponentUri = Component.from) { | ||
let valueEncoderBufSize = 256; | ||
constructor(arg1, parseComponent = Component.from) { | ||
switch (true) { | ||
case arg1 instanceof Name: { | ||
const other = arg1; | ||
this.value = other.value; | ||
this.comps = other.comps; | ||
return; | ||
this.value_ = other.value_; | ||
break; | ||
} | ||
case typeof arg1 === "string": { | ||
const uri = arg1; | ||
this.comps = uri.replace(/^(?:ndn:)?\/?/, "").split("/") | ||
.filter((comp) => comp !== "").map(parseComponentUri); | ||
valueEncoderBufSize = uri.length + 4 * this.comps.length; | ||
this.comps = uri.replace(/^(?:ndn:)?\/*/, "").split("/") | ||
.filter((comp) => comp !== "").map(parseComponent); | ||
this.valueEncoderBufSize = uri.length + 4 * this.comps.length; | ||
break; | ||
@@ -30,5 +30,5 @@ } | ||
case arg1 instanceof Uint8Array: { | ||
this.value = arg1; | ||
this.value_ = arg1; | ||
const comps = []; | ||
const decoder = new Decoder(this.value); | ||
const decoder = new Decoder(this.value_); | ||
while (!decoder.eof) { | ||
@@ -38,10 +38,9 @@ comps.push(decoder.decode(Component)); | ||
this.comps = comps; | ||
return; | ||
break; | ||
} | ||
default: // undefined | ||
this.value = new Uint8Array(); | ||
this.comps = []; | ||
return; | ||
this.valueEncoderBufSize = 0; | ||
break; | ||
} | ||
this.value = Encoder.encode(this.comps, valueEncoderBufSize); | ||
} | ||
@@ -52,5 +51,18 @@ static decodeFrom(decoder) { | ||
} | ||
/** Number of name components. */ | ||
get length() { | ||
return this.comps.length; | ||
} | ||
/** Name TLV-VALUE. */ | ||
get value() { | ||
if (!this.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. */ | ||
@@ -74,3 +86,4 @@ get(i) { | ||
toString() { | ||
return `/${this.comps.map((comp) => comp.toString()).join("/")}`; | ||
this.uri_ ??= `/${this.comps.map((comp) => comp.toString()).join("/")}`; | ||
return this.uri_; | ||
} | ||
@@ -86,3 +99,3 @@ /** Get sub name [begin, end). */ | ||
append(...args) { | ||
if (args.length === 2 && typeof args[0] === "object" && | ||
if (args.length === 2 && | ||
typeof args[0].create === "function") { | ||
@@ -102,3 +115,3 @@ return this.append(args[0].create(args[1])); | ||
compare(other) { | ||
const rhs = new Name(other); | ||
const rhs = Name.from(other); | ||
const commonSize = Math.min(this.length, rhs.length); | ||
@@ -137,2 +150,6 @@ for (let i = 0; i < commonSize; ++i) { | ||
Name.isNameLike = isNameLike; | ||
function from(input) { | ||
return input instanceof Name ? input : new Name(input); | ||
} | ||
Name.from = from; | ||
/** Name compare result. */ | ||
@@ -139,0 +156,0 @@ let CompareResult; |
import { Decoder, Encoder } from "@ndn/tlv"; | ||
import { Component, ComponentLike } from "./component"; | ||
import { type ComponentLike, Component } from "./component"; | ||
import type { NamingConvention } from "./convention"; | ||
/** Name or Name URI. */ | ||
export declare type NameLike = Name | string; | ||
@@ -11,4 +12,2 @@ /** | ||
static decodeFrom(decoder: Decoder): Name; | ||
/** TLV-VALUE of the Name. */ | ||
readonly value: Uint8Array; | ||
/** List of name components. */ | ||
@@ -24,3 +23,12 @@ readonly comps: readonly Component[]; | ||
constructor(comps: readonly ComponentLike[]); | ||
private readonly valueEncoderBufSize?; | ||
private value_?; | ||
private uri_?; | ||
private hex_?; | ||
/** Number of name components. */ | ||
get length(): number; | ||
/** Name TLV-VALUE. */ | ||
get value(): Uint8Array; | ||
/** Name TLV-VALUE hexadecimal representation, good for map keys. */ | ||
get valueHex(): string; | ||
/** Retrieve i-th component. */ | ||
@@ -55,2 +63,3 @@ get(i: number): Component | undefined; | ||
function isNameLike(obj: any): obj is NameLike; | ||
function from(input: NameLike): Name; | ||
/** Name compare result. */ | ||
@@ -57,0 +66,0 @@ enum CompareResult { |
import { __importDefault, __importStar } from "tslib"; | ||
import { toHex } from "@ndn/tlv"; | ||
import _cjsDefaultImport0 from "minimalistic-assert"; const assert = __importDefault(_cjsDefaultImport0).default; | ||
import _cjsDefaultImport1 from "mnemonist/default-weak-map.js"; const DefaultWeakMap = __importDefault(_cjsDefaultImport1).default; | ||
import { assert, toHex } from "@ndn/util"; | ||
import _cjsDefaultImport0 from "mnemonist/default-weak-map.js"; const DefaultWeakMap = __importDefault(_cjsDefaultImport0).default; | ||
import { Interest } from "../interest_browser.js"; | ||
@@ -54,3 +53,3 @@ import { SigInfo } from "../sig-info_browser.js"; | ||
if (klName) { | ||
return `N:${toHex(klName.value)}`; | ||
return `N:${klName.valueHex}`; | ||
} | ||
@@ -163,3 +162,3 @@ const klDigest = sigInfo.keyLocator?.digest; | ||
recordNonce(state, nonceHex) { | ||
state.nonces ?? (state.nonces = new Set()); | ||
state.nonces ??= new Set(); | ||
state.nonces.add(nonceHex); | ||
@@ -214,3 +213,3 @@ evict(this.trackedNonces, state.nonces); | ||
update(si, state) { | ||
state.seqNum ?? (state.seqNum = this.beforeInitialSeqNum); | ||
state.seqNum ??= this.beforeInitialSeqNum; | ||
si.seqNum = ++state.seqNum; | ||
@@ -217,0 +216,0 @@ } |
import { __importDefault, __importStar } from "tslib"; | ||
import { toHex } from "@ndn/tlv"; | ||
import _cjsDefaultImport0 from "minimalistic-assert"; const assert = __importDefault(_cjsDefaultImport0).default; | ||
import _cjsDefaultImport1 from "mnemonist/default-weak-map.js"; const DefaultWeakMap = __importDefault(_cjsDefaultImport1).default; | ||
import { assert, toHex } from "@ndn/util"; | ||
import _cjsDefaultImport0 from "mnemonist/default-weak-map.js"; const DefaultWeakMap = __importDefault(_cjsDefaultImport0).default; | ||
import { Interest } from "../interest_node.js"; | ||
@@ -54,3 +53,3 @@ import { SigInfo } from "../sig-info_node.js"; | ||
if (klName) { | ||
return `N:${toHex(klName.value)}`; | ||
return `N:${klName.valueHex}`; | ||
} | ||
@@ -163,3 +162,3 @@ const klDigest = sigInfo.keyLocator?.digest; | ||
recordNonce(state, nonceHex) { | ||
state.nonces ?? (state.nonces = new Set()); | ||
state.nonces ??= new Set(); | ||
state.nonces.add(nonceHex); | ||
@@ -214,3 +213,3 @@ evict(this.trackedNonces, state.nonces); | ||
update(si, state) { | ||
state.seqNum ?? (state.seqNum = this.beforeInitialSeqNum); | ||
state.seqNum ??= this.beforeInitialSeqNum; | ||
si.seqNum = ++state.seqNum; | ||
@@ -217,0 +216,0 @@ } |
@@ -0,5 +1,5 @@ | ||
import { sha256, timingSafeEqual } from "@ndn/util"; | ||
import { SigType } from "../an_browser.js"; | ||
import { KeyLocator } from "../key-locator_browser.js"; | ||
import { SigInfo } from "../sig-info_browser.js"; | ||
import { sha256, timingSafeEqual as timingSafeEqual_ } from "./helper_browser.js"; | ||
export var LLSign; | ||
@@ -12,3 +12,2 @@ (function (LLSign) { | ||
LLVerify.OP = Symbol("LLVerify.OP"); | ||
LLVerify.timingSafeEqual = timingSafeEqual_; | ||
})(LLVerify || (LLVerify = {})); | ||
@@ -21,19 +20,15 @@ export var Signer; | ||
* @param sigType optionally set sigType. | ||
* @param keyLocator optionally set keyLocator; false to unset KeyLocator. | ||
* @param keyLocator optionally set keyLocator; false to delete KeyLocator. | ||
*/ | ||
function putSigInfo(pkt, sigType, keyLocator) { | ||
pkt.sigInfo ?? (pkt.sigInfo = new SigInfo()); | ||
pkt.sigInfo ??= new SigInfo(); | ||
if (sigType !== undefined) { | ||
pkt.sigInfo.type = sigType; | ||
} | ||
switch (typeof keyLocator) { | ||
case "undefined": | ||
break; | ||
case "boolean": | ||
pkt.sigInfo.keyLocator = undefined; | ||
break; | ||
default: | ||
pkt.sigInfo.keyLocator = new KeyLocator(keyLocator); | ||
break; | ||
if (keyLocator === false) { | ||
pkt.sigInfo.keyLocator = undefined; | ||
} | ||
else if (keyLocator !== undefined) { | ||
pkt.sigInfo.keyLocator = new KeyLocator(keyLocator); | ||
} | ||
return pkt.sigInfo; | ||
@@ -79,3 +74,3 @@ } | ||
const h = await sha256(input); | ||
const ok = LLVerify.timingSafeEqual(sig, h); | ||
const ok = timingSafeEqual(sig, h); | ||
Verifier.throwOnBadSig(ok); | ||
@@ -82,0 +77,0 @@ }); |
@@ -0,5 +1,5 @@ | ||
import { sha256, timingSafeEqual } from "@ndn/util"; | ||
import { SigType } from "../an_node.js"; | ||
import { KeyLocator } from "../key-locator_node.js"; | ||
import { SigInfo } from "../sig-info_node.js"; | ||
import { sha256, timingSafeEqual as timingSafeEqual_ } from "./helper_node.js"; | ||
export var LLSign; | ||
@@ -12,3 +12,2 @@ (function (LLSign) { | ||
LLVerify.OP = Symbol("LLVerify.OP"); | ||
LLVerify.timingSafeEqual = timingSafeEqual_; | ||
})(LLVerify || (LLVerify = {})); | ||
@@ -21,19 +20,15 @@ export var Signer; | ||
* @param sigType optionally set sigType. | ||
* @param keyLocator optionally set keyLocator; false to unset KeyLocator. | ||
* @param keyLocator optionally set keyLocator; false to delete KeyLocator. | ||
*/ | ||
function putSigInfo(pkt, sigType, keyLocator) { | ||
pkt.sigInfo ?? (pkt.sigInfo = new SigInfo()); | ||
pkt.sigInfo ??= new SigInfo(); | ||
if (sigType !== undefined) { | ||
pkt.sigInfo.type = sigType; | ||
} | ||
switch (typeof keyLocator) { | ||
case "undefined": | ||
break; | ||
case "boolean": | ||
pkt.sigInfo.keyLocator = undefined; | ||
break; | ||
default: | ||
pkt.sigInfo.keyLocator = new KeyLocator(keyLocator); | ||
break; | ||
if (keyLocator === false) { | ||
pkt.sigInfo.keyLocator = undefined; | ||
} | ||
else if (keyLocator !== undefined) { | ||
pkt.sigInfo.keyLocator = new KeyLocator(keyLocator); | ||
} | ||
return pkt.sigInfo; | ||
@@ -79,3 +74,3 @@ } | ||
const h = await sha256(input); | ||
const ok = LLVerify.timingSafeEqual(sig, h); | ||
const ok = timingSafeEqual(sig, h); | ||
Verifier.throwOnBadSig(ok); | ||
@@ -82,0 +77,0 @@ }); |
import { KeyLocator } from "../key-locator"; | ||
import type { Name } from "../name/mod"; | ||
import { SigInfo } from "../sig-info"; | ||
import { timingSafeEqual as timingSafeEqual_ } from "./helper_node"; | ||
/** | ||
@@ -27,3 +26,2 @@ * Low level signing function. | ||
} | ||
const timingSafeEqual: typeof timingSafeEqual_; | ||
} | ||
@@ -47,3 +45,3 @@ interface PacketWithSignature { | ||
* @param sigType optionally set sigType. | ||
* @param keyLocator optionally set keyLocator; false to unset KeyLocator. | ||
* @param keyLocator optionally set keyLocator; false to delete KeyLocator. | ||
*/ | ||
@@ -50,0 +48,0 @@ function putSigInfo(pkt: PacketWithSignature, sigType?: number, keyLocator?: KeyLocator.CtorArg | false): SigInfo; |
@@ -1,8 +0,6 @@ | ||
import { __importDefault, __importStar } from "tslib"; | ||
var _a; | ||
import { Encoder, EvDecoder, Extensible, ExtensionRegistry, NNI } from "@ndn/tlv"; | ||
import _cjsDefaultImport0 from "minimalistic-assert"; const assert = __importDefault(_cjsDefaultImport0).default; | ||
import { assert, crypto } from "@ndn/util"; | ||
import { SigType, TT } from "./an_browser.js"; | ||
import { KeyLocator } from "./key-locator_browser.js"; | ||
import { randBytes } from "./security/helper_browser.js"; | ||
const EXTENSIONS = new ExtensionRegistry(); | ||
@@ -77,11 +75,3 @@ const EVD = new EvDecoder("SigInfo", [TT.ISigInfo, TT.DSigInfo]) | ||
[ctorAssign](si) { | ||
switch (typeof v) { | ||
case "number": | ||
case "undefined": | ||
si.nonce = generateNonce(v); | ||
break; | ||
default: | ||
si.nonce = v; | ||
break; | ||
} | ||
si.nonce = v instanceof Uint8Array ? v : generateNonce(v); | ||
}, | ||
@@ -94,3 +84,3 @@ }; | ||
assert(size >= 1); | ||
return randBytes(size); | ||
return crypto.getRandomValues(new Uint8Array(size)); | ||
} | ||
@@ -97,0 +87,0 @@ SigInfo.generateNonce = generateNonce; |
@@ -1,8 +0,6 @@ | ||
import { __importDefault, __importStar } from "tslib"; | ||
var _a; | ||
import { Encoder, EvDecoder, Extensible, ExtensionRegistry, NNI } from "@ndn/tlv"; | ||
import _cjsDefaultImport0 from "minimalistic-assert"; const assert = __importDefault(_cjsDefaultImport0).default; | ||
import { assert, crypto } from "@ndn/util"; | ||
import { SigType, TT } from "./an_node.js"; | ||
import { KeyLocator } from "./key-locator_node.js"; | ||
import { randBytes } from "./security/helper_node.js"; | ||
const EXTENSIONS = new ExtensionRegistry(); | ||
@@ -77,11 +75,3 @@ const EVD = new EvDecoder("SigInfo", [TT.ISigInfo, TT.DSigInfo]) | ||
[ctorAssign](si) { | ||
switch (typeof v) { | ||
case "number": | ||
case "undefined": | ||
si.nonce = generateNonce(v); | ||
break; | ||
default: | ||
si.nonce = v; | ||
break; | ||
} | ||
si.nonce = v instanceof Uint8Array ? v : generateNonce(v); | ||
}, | ||
@@ -94,3 +84,3 @@ }; | ||
assert(size >= 1); | ||
return randBytes(size); | ||
return crypto.getRandomValues(new Uint8Array(size)); | ||
} | ||
@@ -97,0 +87,0 @@ SigInfo.generateNonce = generateNonce; |
@@ -1,2 +0,2 @@ | ||
import { Decoder, EncodableObj, Extensible, ExtensionRegistry } from "@ndn/tlv"; | ||
import { type Decoder, type EncodableObj, Extensible, ExtensionRegistry } from "@ndn/tlv"; | ||
import { KeyLocator } from "./key-locator"; | ||
@@ -3,0 +3,0 @@ /** SignatureInfo on Interest or Data. */ |
{ | ||
"name": "@ndn/packet", | ||
"version": "0.0.20210930", | ||
"version": "0.0.20220501", | ||
"description": "NDNts: Network Layer Packets", | ||
@@ -25,9 +25,10 @@ "keywords": [ | ||
"dependencies": { | ||
"@ndn/tlv": "0.0.20210930", | ||
"@ndn/tlv": "0.0.20220501", | ||
"@ndn/util": "0.0.20220501", | ||
"buffer-compare": "^1.1.1", | ||
"mnemonist": "^0.38.4", | ||
"minimalistic-assert": "^1.0.1", | ||
"tslib": "^2.3.1" | ||
"mnemonist": "^0.39.1", | ||
"tslib": "^2.4.0" | ||
}, | ||
"types": "lib/mod.d.ts" | ||
"types": "lib/mod.d.ts", | ||
"readme": "# @ndn/packet\n\nThis package is part of [NDNts](https://yoursunny.com/p/NDNts/), Named Data Networking libraries for the modern web.\n\nThis package implements **Name**, **Interest**, and **Data** types as specified in [NDN Packet Format v0.3](https://named-data.net/doc/NDN-packet-spec/0.3/).\n\n```ts\nimport { TT, Name, Component, ImplicitDigest, AltUri, Interest, Data, digestSigning } from \"@ndn/packet\";\n\n// other imports for examples\nimport { Decoder, Encoder } from \"@ndn/tlv\";\nimport { fromUtf8, toUtf8 } from \"@ndn/util\";\nimport { strict as assert } from \"node:assert\";\n```\n\n## Name Component\n\n```ts\n// Name components are immutable. Once it's created, you can never change it.\n// Construct a Component from its TLV-TYPE and TLV-VALUE.\nconst compA = new Component(TT.GenericNameComponent, Uint8Array.of(0x41));\n// Create a Component from URI representation.\nconst compB = Component.from(\"B\");\n// Typed components are supported, too.\nconst compMetadata = Component.from(\"32=metadata\");\n\n// We can retrieve TLV-TYPE, TLV-LENGTH, and TLV-VALUE.\nassert.equal(compA.type, TT.GenericNameComponent);\nassert.equal(compB.type, TT.GenericNameComponent);\nassert.equal(compMetadata.type, 0x20);\n\nassert.equal(compA.length, 1);\nassert.equal(compB.length, 1);\nassert.equal(compMetadata.length, 8);\n\nassert.deepEqual(compA.value, Uint8Array.of(0x41));\nassert.deepEqual(compB.value, Uint8Array.of(0x42));\nassert.deepEqual(compMetadata.value, Uint8Array.of(0x6D, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61));\n\n// For convenience, we can retrieve TLV-VALUE as text string, too.\nassert.equal(compA.text, \"A\");\nassert.equal(compB.text, \"B\");\nassert.equal(compMetadata.text, \"metadata\");\n\n// Components are comparable.\nassert.equal(compA.compare(compA), Component.CompareResult.EQUAL);\nassert.equal(compA.compare(compB), Component.CompareResult.LT);\nassert.equal(compB.compare(compA), Component.CompareResult.GT);\nassert.equal(compA.equals(compA), true);\nassert.equal(compA.equals(compB), false);\n```\n\n## Name\n\n```ts\n// Names, like components, are immutable.\n// Construct from URI.\nconst name1 = new Name(\"/localhost/2020=NDNts/rocks\");\n// Construct from a list of components, or strings to create components.\nconst name2 = new Name([compA, compB, \"C\", compMetadata]);\n// Name parsing functions expect URI in canonical format. They DO NOT recognize alternate/pretty\n// URI syntax other than allow omitting \"8=\" prefix of GenericNameComponent.\n\n// You can always convert a name back to its URI in canonical format.\nassert.equal(name1.toString(), \"/8=localhost/2020=NDNts/8=rocks\");\nassert.equal(name2.toString(), \"/8=A/8=B/8=C/32=metadata\");\n\n// AltUri.ofName() function allows printing a name as alternate/pretty URI syntax.\nassert.equal(AltUri.ofName(name1), \"/localhost/2020=NDNts/rocks\");\nassert.equal(AltUri.ofName(name2), \"/A/B/C/32=metadata\");\n// AltUri.ofName() from this package only recognizes 0x01, 0x02, and 0x08 types. If you are using\n// naming conventions from @ndn/naming-convention2 package, use the AltUri from that package.\n// This feature isn't in the regular name.toString(), so that it does not unnecessarily increase\n// browser bundle size in applications that do not need it.\n\n// It's crucial to know how many name components you have.\nassert.equal(name1.length, 3);\nassert.equal(name2.length, 4);\n\n// You can get an individual name component.\nconst name1comp1 = name1.get(1);\n// It would return 'undefined' if the component does not exist, so we have to check.\nif (name1comp1 === undefined) {\n assert.fail(); // This isn't supposed to happen for this name, though.\n} else {\n assert.equal(name1comp1.text, \"NDNts\");\n}\n\n// To save the 'undefined' check, use at(i). It throws if the component does not exist.\nassert.throws(() => name1.at(5));\nassert.equal(name1.at(1).text, \"NDNts\");\n\n// Slice the name to obtain part of it.\nconst name1sliced = name1.slice(1, 3);\nassert.equal(name1sliced.toString(), \"/2020=NDNts/8=rocks\");\n\n// Or, get the prefix.\nconst name2prefix = name2.getPrefix(3);\nassert.equal(name2prefix.toString(), \"/8=A/8=B/8=C\");\n\n// Indexing from the back is supported, too.\nassert.equal(name1.at(-1).text, \"rocks\");\nassert.equal(name1.slice(-2).toString(), \"/2020=NDNts/8=rocks\");\nassert.equal(name2.getPrefix(-1).toString(), \"/8=A/8=B/8=C\");\n\n// Names are comparable.\nconst nameAB = new Name(\"/A/B\");\nconst nameABB = new Name(\"/A/B/B\");\nconst nameABC = new Name(\"/A/B/C\");\nconst nameABD = new Name(\"/A/B/D\");\nconst nameABCD = new Name(\"/A/B/C/D\");\nassert.equal(nameABC.equals(nameABC), true);\nassert.equal(nameABC.equals(nameABD), false);\nassert.equal(nameABC.compare(nameABC), Name.CompareResult.EQUAL);\nassert.equal(nameABC.compare(nameABB), Name.CompareResult.GT);\nassert.equal(nameABC.compare(nameABD), Name.CompareResult.LT);\nassert.equal(nameABC.compare(nameABCD), Name.CompareResult.LPREFIX);\nassert.equal(nameABC.compare(nameAB), Name.CompareResult.RPREFIX);\n\n// LPREFIX means the first name is a strict prefix of the second name.\n// It implies the first name is less than the second name.\n// If you only care about the order, check if the result is less than zero.\nassert(nameABC.compare(nameABCD) < 0);\n\n// RPREFIX means the second name is a strict prefix of the first name.\n// It implies the first name is greater than the second name.\n// If you only care about the order, check if the result is greater than zero.\nassert(nameABC.compare(nameAB) > 0);\n\n// If you want to know whether a name is a prefix of another, it's EQUAL or LPREFIX.\n// But we got a faster way:\nassert.equal(nameABC.isPrefixOf(nameABC), true);\nassert.equal(nameABC.isPrefixOf(nameABCD), true);\nassert.equal(nameABC.isPrefixOf(nameAB), false);\n\n// I said names are immutable, but you can surely modify them to get a new Name.\nconst name1modified = name1.getPrefix(-1).append(\"is\", \"awesome\");\nassert(name1modified.toString(), \"/8=localhost/2020=NDNts/8=rocks/8=is/8=awesome\");\nassert(name1.toString(), \"/8=localhost/2020=NDNts/8=rocks\"); // unchanged\n```\n\n## Layer-3 Packet Types: Interest and Data\n\n```ts\n// We have an Interest type, of course.\n// You can set fields via constructor or setters.\nconst interest = new Interest(new Name(\"/A\"), Interest.CanBePrefix, Interest.MustBeFresh);\ninterest.canBePrefix = false;\ninterest.lifetime = 2000;\n\n// Encode and decode the Interest.\nconst interestWire = Encoder.encode(interest);\nconst interest2 = new Decoder(interestWire).decode(Interest);\nassert.equal(interest2.name.toString(), \"/8=A\");\n\n// We got a Data type, too.\n// You can set fields via constructor or setters.\nconst data = new Data(interest.name, Data.FreshnessPeriod(5000));\ndata.content = toUtf8(\"hello NDNts\");\n```\n\n## Signing and Verification\n\n```ts\n// Every NDN Data must be signed.\n// This package provides the low-level API, and an implementation of SHA256 digest signing.\n// Other signature types are in @ndn/keychain package.\n\n// Sign the Data. The API is asynchronous as required by WebCrypto.\nawait digestSigning.sign(data);\n\n// After signing, we can encode the Data.\nconst dataWire = Encoder.encode(data);\n\n// And then decode it.\nconst data2 = new Decoder(dataWire).decode(Data);\n\n// Data signature should be verified.\n// If the verify() function does not throw, it means the signature is good.\nawait digestSigning.verify(data);\n\n// It's very important that you do not modify the Data if you need to verify its signature.\n// Otherwise, you'll get errors or incorrect results.\n\n// After verifying, we can access the Content.\nassert.equal(fromUtf8(data2.content), \"hello NDNts\");\n```\n\n## Implicit Digest\n\n```ts\n// To obtain implicit digest, we'll have to await, because it internally uses WebCrypto, which is async.\nconst digest = await data.computeImplicitDigest();\nassert.equal(digest.length, 32);\n\n// Full names are available, too.\nconst fullName = await data2.computeFullName();\nassert.equal(fullName.length - 1, data2.name.length);\nassert(fullName.at(-1).is(ImplicitDigest));\n\n// After computation, implicit digest is cached on the Data instance,\n// so we can get them without await:\nconst digest2 = data.getImplicitDigest();\nconst fullName2 = data.getFullName();\nassert.equal(digest2, digest);\nassert(fullName2 !== undefined);\nassert.equal(fullName2.toString(), fullName.toString());\n\n// Note that you cannot modify the Data after encoding or decoding,\n// or you'll get incorrect implicit digest results.\n```\n\n## Interest-Data Matching\n\n```ts\n// data.canSatisfy(interest) determines whether a Data satisfy an Interest.\n// This is an async function because it potentially involves computing the implicit digest.\n\nassert.equal(await data.canSatisfy(interest), true);\nconst interest3 = new Interest(\"/B\");\nassert.equal(await data.canSatisfy(interest3), false);\nconst data3 = new Decoder(dataWire).decode(Data);\nconst interestWithFullName = new Interest(fullName);\nassert.equal(await data.canSatisfy(interestWithFullName), true);\n```\n" | ||
} |
@@ -11,6 +11,5 @@ # @ndn/packet | ||
// other imports for examples | ||
import { Decoder, Encoder, fromUtf8, toUtf8 } from "@ndn/tlv"; | ||
import { Decoder, Encoder } from "@ndn/tlv"; | ||
import { fromUtf8, toUtf8 } from "@ndn/util"; | ||
import { strict as assert } from "node:assert"; | ||
(async () => { | ||
``` | ||
@@ -182,8 +181,4 @@ | ||
// If the verify() function does not throw, it means the signature is good. | ||
try { | ||
await digestSigning.verify(data); | ||
} catch (err: unknown) { | ||
console.log(err); | ||
return; | ||
} | ||
await digestSigning.verify(data); | ||
// It's very important that you do not modify the Data if you need to verify its signature. | ||
@@ -233,5 +228,1 @@ // Otherwise, you'll get errors or incorrect results. | ||
``` | ||
```ts | ||
})(); | ||
``` |
171175
9.67%61
1.67%4280
3.31%226
-3.83%+ Added
+ Added
+ Added
+ Added
+ Added
- Removed
- Removed
- Removed
Updated
Updated
Updated