Comparing version 0.0.20230121 to 0.0.20240113
@@ -53,2 +53,8 @@ import { asDataView, fromUtf8 } from "@ndn/util"; | ||
input; | ||
constructor(input) { | ||
this.input = input; | ||
this.dv = asDataView(input); | ||
} | ||
dv; | ||
offset = 0; | ||
/** Determine whether end of input has been reached. */ | ||
@@ -58,7 +64,7 @@ get eof() { | ||
} | ||
dv; | ||
offset = 0; | ||
constructor(input) { | ||
this.input = input; | ||
this.dv = asDataView(input); | ||
/** Throw an error if EOF has not been reached. */ | ||
throwUnlessEof() { | ||
if (!this.eof) { | ||
throw new Error("junk after end of TLV"); | ||
} | ||
} | ||
@@ -86,3 +92,3 @@ /** Read TLV structure. */ | ||
switch (this.input[this.offset]) { | ||
case 0xFD: | ||
case 0xFD: { | ||
this.offset += 3; | ||
@@ -93,3 +99,4 @@ if (this.offset > this.input.length) { | ||
return this.dv.getUint16(this.offset - 2); | ||
case 0xFE: | ||
} | ||
case 0xFE: { | ||
this.offset += 5; | ||
@@ -100,10 +107,26 @@ if (this.offset > this.input.length) { | ||
return this.dv.getUint32(this.offset - 4); | ||
case 0xFF: | ||
} | ||
case 0xFF: { | ||
// JavaScript cannot reliably represent 64-bit integers | ||
return undefined; | ||
default: | ||
} | ||
default: { | ||
this.offset += 1; | ||
return this.input[this.offset - 1]; | ||
} | ||
} | ||
} | ||
} | ||
(function (Decoder) { | ||
/** | ||
* Decode a single object from Uint8Array. | ||
* The input is expected to contain no junk after the object. | ||
*/ | ||
function decode(input, d) { | ||
const decoder = new Decoder(input); | ||
const res = d.decodeFrom(decoder); | ||
decoder.throwUnlessEof(); | ||
return res; | ||
} | ||
Decoder.decode = decode; | ||
})(Decoder || (Decoder = {})); |
@@ -53,2 +53,8 @@ import { asDataView, fromUtf8 } from "@ndn/util"; | ||
input; | ||
constructor(input) { | ||
this.input = input; | ||
this.dv = asDataView(input); | ||
} | ||
dv; | ||
offset = 0; | ||
/** Determine whether end of input has been reached. */ | ||
@@ -58,7 +64,7 @@ get eof() { | ||
} | ||
dv; | ||
offset = 0; | ||
constructor(input) { | ||
this.input = input; | ||
this.dv = asDataView(input); | ||
/** Throw an error if EOF has not been reached. */ | ||
throwUnlessEof() { | ||
if (!this.eof) { | ||
throw new Error("junk after end of TLV"); | ||
} | ||
} | ||
@@ -86,3 +92,3 @@ /** Read TLV structure. */ | ||
switch (this.input[this.offset]) { | ||
case 0xFD: | ||
case 0xFD: { | ||
this.offset += 3; | ||
@@ -93,3 +99,4 @@ if (this.offset > this.input.length) { | ||
return this.dv.getUint16(this.offset - 2); | ||
case 0xFE: | ||
} | ||
case 0xFE: { | ||
this.offset += 5; | ||
@@ -100,10 +107,26 @@ if (this.offset > this.input.length) { | ||
return this.dv.getUint32(this.offset - 4); | ||
case 0xFF: | ||
} | ||
case 0xFF: { | ||
// JavaScript cannot reliably represent 64-bit integers | ||
return undefined; | ||
default: | ||
} | ||
default: { | ||
this.offset += 1; | ||
return this.input[this.offset - 1]; | ||
} | ||
} | ||
} | ||
} | ||
(function (Decoder) { | ||
/** | ||
* Decode a single object from Uint8Array. | ||
* The input is expected to contain no junk after the object. | ||
*/ | ||
function decode(input, d) { | ||
const decoder = new Decoder(input); | ||
const res = d.decodeFrom(decoder); | ||
decoder.throwUnlessEof(); | ||
return res; | ||
} | ||
Decoder.decode = decode; | ||
})(Decoder || (Decoder = {})); |
@@ -7,7 +7,9 @@ export interface Decodable<R> { | ||
private readonly input; | ||
constructor(input: Uint8Array); | ||
private readonly dv; | ||
private offset; | ||
/** Determine whether end of input has been reached. */ | ||
get eof(): boolean; | ||
private readonly dv; | ||
private offset; | ||
constructor(input: Uint8Array); | ||
/** Throw an error if EOF has not been reached. */ | ||
throwUnlessEof(): void; | ||
/** Read TLV structure. */ | ||
@@ -47,2 +49,7 @@ read(): Decoder.Tlv; | ||
} | ||
/** | ||
* Decode a single object from Uint8Array. | ||
* The input is expected to contain no junk after the object. | ||
*/ | ||
function decode<R>(input: Uint8Array, d: Decodable<R>): R; | ||
} |
@@ -32,2 +32,5 @@ import { assert } from "@ndn/util"; | ||
} | ||
applyDefaultsToRuleOptions({ order = (this.nextOrder += AUTO_ORDER_SKIP), required = false, repeat = false, } = {}) { | ||
return { order, required, repeat }; | ||
} | ||
/** | ||
@@ -37,13 +40,12 @@ * Add a decoding rule. | ||
* @param cb callback or nested EvDecoder to handle element TLV. | ||
* @param options additional rule options. | ||
* @param opts additional rule options. | ||
*/ | ||
add(tt, cb, { order = (this.nextOrder += AUTO_ORDER_SKIP), required = false, repeat = false, } = {}) { | ||
add(tt, cb, opts = {}) { | ||
const ro = this.applyDefaultsToRuleOptions(opts); | ||
assert(!this.rules.has(tt), "duplicate rule for same TLV-TYPE"); | ||
this.rules.set(tt, { | ||
...ro, | ||
cb: cb instanceof EvDecoder ? nest(cb) : cb, | ||
order, | ||
required, | ||
repeat, | ||
}); | ||
if (required) { | ||
if (ro.required) { | ||
this.requiredTT.add(tt); | ||
@@ -119,1 +121,8 @@ } | ||
} | ||
(function (EvDecoder) { | ||
/** | ||
* IsCritical callback that always returns false. | ||
* This means unrecognized or out-of-order TLV elements are ignored. | ||
*/ | ||
EvDecoder.neverCritical = () => false; | ||
})(EvDecoder || (EvDecoder = {})); |
@@ -32,2 +32,5 @@ import { assert } from "@ndn/util"; | ||
} | ||
applyDefaultsToRuleOptions({ order = (this.nextOrder += AUTO_ORDER_SKIP), required = false, repeat = false, } = {}) { | ||
return { order, required, repeat }; | ||
} | ||
/** | ||
@@ -37,13 +40,12 @@ * Add a decoding rule. | ||
* @param cb callback or nested EvDecoder to handle element TLV. | ||
* @param options additional rule options. | ||
* @param opts additional rule options. | ||
*/ | ||
add(tt, cb, { order = (this.nextOrder += AUTO_ORDER_SKIP), required = false, repeat = false, } = {}) { | ||
add(tt, cb, opts = {}) { | ||
const ro = this.applyDefaultsToRuleOptions(opts); | ||
assert(!this.rules.has(tt), "duplicate rule for same TLV-TYPE"); | ||
this.rules.set(tt, { | ||
...ro, | ||
cb: cb instanceof EvDecoder ? nest(cb) : cb, | ||
order, | ||
required, | ||
repeat, | ||
}); | ||
if (required) { | ||
if (ro.required) { | ||
this.requiredTT.add(tt); | ||
@@ -119,1 +121,8 @@ } | ||
} | ||
(function (EvDecoder) { | ||
/** | ||
* IsCritical callback that always returns false. | ||
* This means unrecognized or out-of-order TLV elements are ignored. | ||
*/ | ||
EvDecoder.neverCritical = () => false; | ||
})(EvDecoder || (EvDecoder = {})); |
@@ -21,2 +21,3 @@ import type { Decoder } from "./decoder.js"; | ||
constructor(typeName: string, topTT?: number | readonly number[]); | ||
applyDefaultsToRuleOptions({ order, required, repeat, }?: Partial<EvDecoder.RuleOptions>): EvDecoder.RuleOptions; | ||
/** | ||
@@ -26,5 +27,5 @@ * Add a decoding rule. | ||
* @param cb callback or nested EvDecoder to handle element TLV. | ||
* @param options additional rule options. | ||
* @param opts additional rule options. | ||
*/ | ||
add(tt: number, cb: EvDecoder.ElementDecoder<T> | EvDecoder<T>, { order, required, repeat, }?: Partial<EvDecoder.RuleOptions>): this; | ||
add(tt: number, cb: EvDecoder.ElementDecoder<T> | EvDecoder<T>, opts?: Partial<EvDecoder.RuleOptions>): this; | ||
/** Set callback to determine whether TLV-TYPE is critical. */ | ||
@@ -74,2 +75,7 @@ setIsCritical(cb: EvDecoder.IsCritical): this; | ||
/** | ||
* IsCritical callback that always returns false. | ||
* This means unrecognized or out-of-order TLV elements are ignored. | ||
*/ | ||
const neverCritical: IsCritical; | ||
/** | ||
* Callback before or after decoding TLV-VALUE. | ||
@@ -76,0 +82,0 @@ * @param target target object. |
@@ -12,2 +12,26 @@ import { __importDefault, __importStar } from "tslib"; | ||
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 = {})); | ||
@@ -45,2 +69,3 @@ export var Extension; | ||
decodeUnknown = (target, tlv, order) => { | ||
void order; | ||
const { type: tt } = tlv; | ||
@@ -47,0 +72,0 @@ const ext = this.table.get(tt); |
@@ -12,2 +12,26 @@ import { __importDefault, __importStar } from "tslib"; | ||
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 = {})); | ||
@@ -45,2 +69,3 @@ export var Extension; | ||
decodeUnknown = (target, tlv, order) => { | ||
void order; | ||
const { type: tt } = tlv; | ||
@@ -47,0 +72,0 @@ const ext = this.table.get(tt); |
@@ -11,2 +11,8 @@ import type { Decoder } from "./decoder.js"; | ||
function cloneRecord(dst: Extensible, src: Extensible): void; | ||
/** | ||
* 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<T extends Extensible>(typ: new () => T, exts: Record<string, number>): void; | ||
} | ||
@@ -13,0 +19,0 @@ /** |
@@ -7,1 +7,2 @@ export * from "./decoder_browser.js"; | ||
export * from "./string_browser.js"; | ||
export * from "./struct-builder_browser.js"; |
@@ -7,1 +7,2 @@ export * from "./decoder_node.js"; | ||
export * from "./string_node.js"; | ||
export * from "./struct-builder_node.js"; |
@@ -7,1 +7,2 @@ export * from "./decoder.js"; | ||
export * from "./string.js"; | ||
export * from "./struct-builder.js"; |
@@ -51,8 +51,11 @@ import { asDataView, toHex } from "@ndn/util"; | ||
switch (dv.byteLength) { | ||
case 1: | ||
case 1: { | ||
return dv.getUint8(0); | ||
case 2: | ||
} | ||
case 2: { | ||
return dv.getUint16(0); | ||
case 4: | ||
} | ||
case 4: { | ||
return dv.getUint32(0); | ||
} | ||
} | ||
@@ -77,24 +80,33 @@ throw new Error("incorrect TLV-LENGTH of NNI"); | ||
switch (true) { | ||
case n < 0x100000000n: | ||
case n < 0x100000000n: { | ||
n = Number(n); | ||
break; | ||
case n <= 0xffffffffffffffffn: | ||
} | ||
case n <= 0xffffffffffffffffn: { | ||
return new Nni8Big(n); | ||
default: | ||
} | ||
default: { | ||
throw new RangeError("NNI is too large"); | ||
} | ||
} | ||
} | ||
switch (true) { | ||
case n < 0: | ||
case n < 0: { | ||
throw new RangeError("NNI cannot be negative"); | ||
case n < 0x100: | ||
} | ||
case n < 0x100: { | ||
return new Nni1(n); | ||
case n < 0x10000: | ||
} | ||
case n < 0x10000: { | ||
return new Nni2(n); | ||
case n < 0x100000000: | ||
} | ||
case n < 0x100000000: { | ||
return new Nni4(n); | ||
case n <= (unsafe ? 0xFFFFFFFFFFFFFFFF : Number.MAX_SAFE_INTEGER): // eslint-disable-line @typescript-eslint/no-loss-of-precision | ||
} | ||
case n <= (unsafe ? 0xFFFFFFFFFFFFFFFF : Number.MAX_SAFE_INTEGER): { // eslint-disable-line @typescript-eslint/no-loss-of-precision | ||
return new Nni8Number(n); | ||
default: | ||
} | ||
default: { | ||
throw new RangeError("NNI is too large"); | ||
} | ||
} | ||
@@ -126,10 +138,2 @@ } | ||
NNI.decode = decode; | ||
function constrain(n, typeName, limit0, limit1) { | ||
const [min = 0, max = Number.MAX_SAFE_INTEGER] = typeof limit1 === "number" ? [limit0, limit1] : [0, limit0]; | ||
if (!(n >= min && n <= max)) { | ||
throw new RangeError(`${n} is out of ${typeName} valid range`); | ||
} | ||
return Math.trunc(n); | ||
} | ||
NNI.constrain = constrain; | ||
})(NNI || (NNI = {})); |
@@ -51,8 +51,11 @@ import { asDataView, toHex } from "@ndn/util"; | ||
switch (dv.byteLength) { | ||
case 1: | ||
case 1: { | ||
return dv.getUint8(0); | ||
case 2: | ||
} | ||
case 2: { | ||
return dv.getUint16(0); | ||
case 4: | ||
} | ||
case 4: { | ||
return dv.getUint32(0); | ||
} | ||
} | ||
@@ -77,24 +80,33 @@ throw new Error("incorrect TLV-LENGTH of NNI"); | ||
switch (true) { | ||
case n < 0x100000000n: | ||
case n < 0x100000000n: { | ||
n = Number(n); | ||
break; | ||
case n <= 0xffffffffffffffffn: | ||
} | ||
case n <= 0xffffffffffffffffn: { | ||
return new Nni8Big(n); | ||
default: | ||
} | ||
default: { | ||
throw new RangeError("NNI is too large"); | ||
} | ||
} | ||
} | ||
switch (true) { | ||
case n < 0: | ||
case n < 0: { | ||
throw new RangeError("NNI cannot be negative"); | ||
case n < 0x100: | ||
} | ||
case n < 0x100: { | ||
return new Nni1(n); | ||
case n < 0x10000: | ||
} | ||
case n < 0x10000: { | ||
return new Nni2(n); | ||
case n < 0x100000000: | ||
} | ||
case n < 0x100000000: { | ||
return new Nni4(n); | ||
case n <= (unsafe ? 0xFFFFFFFFFFFFFFFF : Number.MAX_SAFE_INTEGER): // eslint-disable-line @typescript-eslint/no-loss-of-precision | ||
} | ||
case n <= (unsafe ? 0xFFFFFFFFFFFFFFFF : Number.MAX_SAFE_INTEGER): { // eslint-disable-line @typescript-eslint/no-loss-of-precision | ||
return new Nni8Number(n); | ||
default: | ||
} | ||
default: { | ||
throw new RangeError("NNI is too large"); | ||
} | ||
} | ||
@@ -126,10 +138,2 @@ } | ||
NNI.decode = decode; | ||
function constrain(n, typeName, limit0, limit1) { | ||
const [min = 0, max = Number.MAX_SAFE_INTEGER] = typeof limit1 === "number" ? [limit0, limit1] : [0, limit0]; | ||
if (!(n >= min && n <= max)) { | ||
throw new RangeError(`${n} is out of ${typeName} valid range`); | ||
} | ||
return Math.trunc(n); | ||
} | ||
NNI.constrain = constrain; | ||
})(NNI || (NNI = {})); |
@@ -22,9 +22,3 @@ import type { Encodable } from "./encoder.js"; | ||
}): bigint; | ||
/** Error if n exceeds [0,MAX_SAFE_INTEGER] range. */ | ||
function constrain(n: number, typeName: string): number; | ||
/** Error if n exceeds [0,max] range. */ | ||
function constrain(n: number, typeName: string, max: number): number; | ||
/** Error if n exceeds [min,max] range. */ | ||
function constrain(n: number, typeName: string, min: number, max: number): number; | ||
} | ||
export {}; |
{ | ||
"name": "@ndn/tlv", | ||
"version": "0.0.20230121", | ||
"version": "0.0.20240113", | ||
"description": "NDNts: TLV", | ||
@@ -25,7 +25,8 @@ "keywords": [ | ||
"dependencies": { | ||
"@ndn/util": "0.0.20230121", | ||
"mnemonist": "^0.39.5", | ||
"tslib": "^2.4.1" | ||
"@ndn/util": "0.0.20240113", | ||
"mnemonist": "^0.39.7", | ||
"tslib": "^2.6.2", | ||
"type-fest": "^4.9.0" | ||
}, | ||
"types": "lib/mod.d.ts" | ||
} |
@@ -5,11 +5,11 @@ # @ndn/tlv | ||
This package implements Type-Length-Value structure encoder and decoder as specified in [NDN Packet Format v0.3](https://named-data.net/doc/NDN-packet-spec/0.3/tlv.html). | ||
This package implements Type-Length-Value structure encoder and decoder as specified in [NDN Packet Format v0.3](https://docs.named-data.net/NDN-packet-spec/0.3/tlv.html). | ||
It has full support for TLV evolvability guidelines. | ||
```ts | ||
import { Encoder, Decoder, EvDecoder, NNI } from "@ndn/tlv"; | ||
import { Encoder, Decoder, EvDecoder, NNI, StructBuilder, StructFieldNNI, StructFieldText } from "@ndn/tlv"; | ||
// other imports for examples | ||
import { Name, TT as nameTT } from "@ndn/packet"; | ||
import { strict as assert } from "node:assert"; | ||
import { Name, TT as l3TT, StructFieldName } from "@ndn/packet"; | ||
import assert from "node:assert/strict"; | ||
``` | ||
@@ -73,3 +73,3 @@ | ||
Suppose we want to decode [NLSR's LSDB Dataset](https://redmine.named-data.net/projects/nlsr/wiki/LSDB_DataSet/11): | ||
Suppose we want to decode `Adjacency` type in [NLSR's LSDB Dataset](https://redmine.named-data.net/projects/nlsr/wiki/LSDB_DataSet/13): | ||
@@ -99,7 +99,7 @@ ```abnf | ||
const TT = { | ||
...nameTT, | ||
...l3TT, | ||
Adjacency: 0x84, | ||
Cost: 0x8C, | ||
Uri: 0x8D, | ||
}; | ||
} as const; | ||
@@ -126,6 +126,5 @@ // Create the decoder. | ||
); | ||
const adjacencyDecoder = new Decoder(adjacencyWire); | ||
// We can decode it with the EVD. | ||
const adjacency = EVD.decode(new Adjacency(), adjacencyDecoder); | ||
const adjacency = EVD.decode(new Adjacency(), new Decoder(adjacencyWire)); | ||
assert.equal(adjacency.name.toString(), "/8=A"); | ||
@@ -135,1 +134,53 @@ assert.equal(adjacency.uri, "B"); | ||
``` | ||
## StructBuilder | ||
The **StructBuilder** is a helper for defining a class that represents a TLV structure. | ||
It allows you to define the typing, constructor, encoder, and decoder, while writing each field only once. | ||
```ts | ||
// Create a StructBuilder and add the fields. | ||
const buildAdj = new StructBuilder("Adjacency", TT.Adjacency) | ||
.add(TT.Name, "name", StructFieldName, { required: true }) | ||
.add(TT.Uri, "uri", StructFieldText, { required: true }) | ||
.add(TT.Cost, "cost", StructFieldNNI, { required: true }); | ||
// You should call .add() on each successive return value, and save the last return value into the | ||
// builder variable. This gradually builds up the typing of the TLV class. | ||
// WRONG EXAMPLE: | ||
// const builder = new StructBuilder(); | ||
// builder.add(...); | ||
// builder.add(...); | ||
// In the wrong example, typing information is not saved into the builder variable. | ||
// Declare a class to represent the Adjacency type, inheriting from a base class supplied by the builder. | ||
class Adj extends buildAdj.baseClass<Adj>() {} | ||
// Assign the subclass to the builder (otherwise the decoding function will not work). | ||
buildAdj.subclass = Adj; | ||
// We can construct an instance and encode it. | ||
const adj0 = new Adj(); | ||
adj0.name = new Name("/A"); | ||
adj0.uri = "B"; | ||
adj0.cost = 128; | ||
const adj0Wire = Encoder.encode(adj0); | ||
assert.deepEqual(adj0Wire, Uint8Array.of( | ||
0x84, 0x0B, | ||
0x07, 0x03, 0x08, 0x01, 0x41, // Name | ||
0x8D, 0x01, 0x42, // Uri | ||
0x8C, 0x01, 0x80, // Cost | ||
)); | ||
// We can decode the wire encoding. | ||
const adj1 = Decoder.decode(adjacencyWire, Adj); | ||
assert.equal(adj1.name.toString(), "/8=A"); | ||
assert.equal(adj1.uri, "B"); | ||
assert.equal(adj1.cost, 128); | ||
``` | ||
**StructBuilder** enables rapid development of TLV based structures, but is less flexible than writing code with Encoder, Decoder, and EvDecoder. | ||
Some limitations are: | ||
* You cannot write JSDoc for individual fields. | ||
* You cannot decode multiple TLV-TYPE numbers into the same field (counterexample: `Name` with typed name components). | ||
* You cannot encode the structure with different TLV-TYPE numbers (counterexample: `SigInfo` encoded as either ISigInfo or DSigInfo). |
@@ -1,6 +0,6 @@ | ||
import { Encoder, Decoder, EvDecoder, NNI } from "@ndn/tlv"; | ||
import { Encoder, Decoder, EvDecoder, NNI, StructBuilder, StructFieldNNI, StructFieldText } from "@ndn/tlv"; | ||
// other imports for examples | ||
import { Name, TT as nameTT } from "@ndn/packet"; | ||
import { strict as assert } from "node:assert"; | ||
import { Name, TT as l3TT, StructFieldName } from "@ndn/packet"; | ||
import assert from "node:assert/strict"; | ||
@@ -54,7 +54,7 @@ // Encode TLV object that implements EncodableObj interface: | ||
const TT = { | ||
...nameTT, | ||
...l3TT, | ||
Adjacency: 0x84, | ||
Cost: 0x8C, | ||
Uri: 0x8D, | ||
}; | ||
} as const; | ||
@@ -81,8 +81,45 @@ // Create the decoder. | ||
); | ||
const adjacencyDecoder = new Decoder(adjacencyWire); | ||
// We can decode it with the EVD. | ||
const adjacency = EVD.decode(new Adjacency(), adjacencyDecoder); | ||
const adjacency = EVD.decode(new Adjacency(), new Decoder(adjacencyWire)); | ||
assert.equal(adjacency.name.toString(), "/8=A"); | ||
assert.equal(adjacency.uri, "B"); | ||
assert.equal(adjacency.cost, 128); | ||
// Create a StructBuilder and add the fields. | ||
const buildAdj = new StructBuilder("Adjacency", TT.Adjacency) | ||
.add(TT.Name, "name", StructFieldName, { required: true }) | ||
.add(TT.Uri, "uri", StructFieldText, { required: true }) | ||
.add(TT.Cost, "cost", StructFieldNNI, { required: true }); | ||
// You should call .add() on each successive return value, and save the last return value into the | ||
// builder variable. This gradually builds up the typing of the TLV class. | ||
// WRONG EXAMPLE: | ||
// const builder = new StructBuilder(); | ||
// builder.add(...); | ||
// builder.add(...); | ||
// In the wrong example, typing information is not saved into the builder variable. | ||
// Declare a class to represent the Adjacency type, inheriting from a base class supplied by the builder. | ||
class Adj extends buildAdj.baseClass<Adj>() {} | ||
// Assign the subclass to the builder (otherwise the decoding function will not work). | ||
buildAdj.subclass = Adj; | ||
// We can construct an instance and encode it. | ||
const adj0 = new Adj(); | ||
adj0.name = new Name("/A"); | ||
adj0.uri = "B"; | ||
adj0.cost = 128; | ||
const adj0Wire = Encoder.encode(adj0); | ||
assert.deepEqual(adj0Wire, Uint8Array.of( | ||
0x84, 0x0B, | ||
0x07, 0x03, 0x08, 0x01, 0x41, // Name | ||
0x8D, 0x01, 0x42, // Uri | ||
0x8C, 0x01, 0x80, // Cost | ||
)); | ||
// We can decode the wire encoding. | ||
const adj1 = Decoder.decode(adjacencyWire, Adj); | ||
assert.equal(adj1.name.toString(), "/8=A"); | ||
assert.equal(adj1.uri, "B"); | ||
assert.equal(adj1.cost, 128); |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
85042
28
2289
182
4
+ Addedtype-fest@^4.9.0
+ Added@ndn/util@0.0.20240113(transitive)
+ Addedstreaming-iterables@8.0.1(transitive)
+ Addedtype-fest@4.29.0(transitive)
- Removed@ndn/util@0.0.20230121(transitive)
Updated@ndn/util@0.0.20240113
Updatedmnemonist@^0.39.7
Updatedtslib@^2.6.2