Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@ndn/tlv

Package Overview
Dependencies
Maintainers
1
Versions
9
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@ndn/tlv - npm Package Compare versions

Comparing version 0.0.20191223-beta.1 to 0.0.20200606

4

lib/decoder.d.ts
export interface Decodable<R> {
decodeFrom(decoder: Decoder): R;
decodeFrom: (decoder: Decoder) => R;
}

@@ -45,2 +45,4 @@ /** TLV decoder. */

readonly nni: number;
/** TLV-VALUE as UTF-8 string */
readonly text: string;
/** siblings before this TLV */

@@ -47,0 +49,0 @@ readonly before: Uint8Array;

@@ -1,2 +0,3 @@

import { NNI } from "./mod.js";
import { NNI } from "./nni.js";
import { fromUtf8 } from "./string.js";
class DecodedTlv {

@@ -31,2 +32,5 @@ constructor(type, buf, offsetT, offsetV, offsetE) {

}
get text() {
return fromUtf8(this.value);
}
get before() {

@@ -33,0 +37,0 @@ return this.buf.subarray(0, this.offsetT);

@@ -5,3 +5,3 @@ /**

export interface EncodableObj {
encodeTo(encoder: Encoder): void;
encodeTo: (encoder: Encoder) => void;
}

@@ -49,3 +49,3 @@ /**

/** Prepend an Encodable object. */
encode(obj: Encodable | ReadonlyArray<Encodable>): void;
encode(obj: Encodable | readonly Encodable[]): void;
private grow;

@@ -56,5 +56,5 @@ }

const OmitEmpty: unique symbol;
function encode(obj: Encodable | ReadonlyArray<Encodable>, initBufSize?: number): Uint8Array;
function encode(obj: Encodable | readonly Encodable[], initBufSize?: number): Uint8Array;
/** Extract the encoding output of an element while writing to a larger encoder. */
function extract(obj: Encodable | ReadonlyArray<Encodable>, cb: (output: Uint8Array) => void): Encodable;
function extract(obj: Encodable | readonly Encodable[], cb: (output: Uint8Array) => void): Encodable;
}

@@ -103,4 +103,3 @@ function sizeofVarNum(n) {

if (obj instanceof Uint8Array) {
const dst = this.prependRoom(obj.byteLength);
dst.set(obj);
this.prependRoom(obj.byteLength).set(obj);
}

@@ -107,0 +106,0 @@ else if (typeof obj === "object" && typeof obj.encodeTo === "function") {

@@ -1,2 +0,2 @@

import { Decoder } from "./mod";
import { Decoder } from "./decoder";
/** Invoked when a matching TLV element is found. */

@@ -11,2 +11,4 @@ declare type ElementCallback<T> = (target: T, tlv: Decoder.Tlv) => void;

order: number;
/** Whether TLV element must appear at least once. */
required: boolean;
/** Whether TLV element may appear more than once. */

@@ -29,2 +31,3 @@ repeat: boolean;

private rules;
private requiredTlvTypes;
private nextOrder;

@@ -39,3 +42,3 @@ private isCriticalCb;

*/
constructor(typeName: string, topTT?: number | ReadonlyArray<number>);
constructor(typeName: string, topTT?: number | readonly number[]);
/**

@@ -54,6 +57,8 @@ * Add a decoding rule.

setTop(cb: TopElementCallback<T>): this;
/** Decode to target object. */
/** Decode TLV to target object. */
decode<R extends T = T>(target: R, decoder: Decoder): R;
/** Decode TLV-VALUE to target object. */
decodeValue<R extends T = T>(target: R, vd: Decoder): R;
private handleUnrecognized;
}
export {};

@@ -1,2 +0,2 @@

import { printTT } from "./mod.js";
import { printTT } from "./string.js";
const AUTO_ORDER_SKIP = 100;

@@ -18,5 +18,7 @@ function nest(evd) {

this.typeName = typeName;
this.rules = {};
this.rules = new Map();
this.requiredTlvTypes = new Set();
this.nextOrder = AUTO_ORDER_SKIP;
this.isCriticalCb = isCritical;
// eslint-disable-next-line no-negated-condition
this.topTT = !topTT ? [] : Array.isArray(topTT) ? topTT : [topTT];

@@ -33,10 +35,17 @@ this.unknownCb = () => false;

add(tt, cb, options) {
if (typeof this.rules[tt] !== "undefined") {
if (this.rules.has(tt)) {
throw new Error(`TLV-TYPE ${printTT(tt)} already has a rule`);
}
if (cb instanceof EvDecoder) {
cb = nest(cb);
const rule = {
cb: cb instanceof EvDecoder ? nest(cb) : cb,
order: this.nextOrder,
required: false,
repeat: false,
...options,
};
this.nextOrder += AUTO_ORDER_SKIP;
this.rules.set(tt, rule);
if (rule.required) {
this.requiredTlvTypes.add(tt);
}
this.rules[tt] = { cb, order: this.nextOrder, repeat: false, ...options };
this.nextOrder += AUTO_ORDER_SKIP;
return this;

@@ -59,16 +68,22 @@ }

}
/** Decode to target object. */
/** Decode TLV to target object. */
decode(target, decoder) {
const topTlv = decoder.read();
const { type, vd } = topTlv;
if (this.topTT.length && !this.topTT.includes(type)) {
if (this.topTT.length > 0 && !this.topTT.includes(type)) {
throw new Error(`TLV-TYPE ${printTT(type)} is not ${this.typeName}`);
}
this.topCb(target, topTlv);
return this.decodeValue(target, vd);
}
/** Decode TLV-VALUE to target object. */
decodeValue(target, vd) {
let currentOrder = 0;
let currentCount = 0;
const missingTlvTypes = new Set(this.requiredTlvTypes);
while (!vd.eof) {
const tlv = vd.read();
const tt = tlv.type;
const rule = this.rules[tt];
missingTlvTypes.delete(tt);
const rule = this.rules.get(tt);
if (typeof rule === "undefined") {

@@ -94,2 +109,5 @@ if (!this.unknownCb(target, tlv, currentOrder)) {

}
if (missingTlvTypes.size > 0) {
throw new Error(`TLV-TYPE ${Array.from(missingTlvTypes).map(printTT).join(",")} ${missingTlvTypes.size === 1 ? "is" : "are"} missing in ${this.typeName}`);
}
return target;

@@ -96,0 +114,0 @@ }

@@ -1,2 +0,3 @@

import { Decoder, Encodable } from "./mod";
import { Decoder } from "./decoder";
import { Encodable } from "./encoder";
/** An TLV element that allows extension sub element. */

@@ -27,3 +28,3 @@ export interface Extensible {

*/
decode(obj: T, tlv: Decoder.Tlv, accumulator?: R): R;
decode: (obj: T, tlv: Decoder.Tlv, accumulator?: R) => R;
/**

@@ -35,3 +36,3 @@ * Encode extension element.

*/
encode(obj: T, value: R): Encodable;
encode: (obj: T, value: R) => Encodable;
}

@@ -38,0 +39,0 @@ export declare namespace Extension {

@@ -53,5 +53,5 @@ export var Extensible;

})
.sort(({ tt: ttA, ext: { order: orderA } }, { tt: ttB, ext: { order: orderB } }) => ((orderA !== null && orderA !== void 0 ? orderA : ttA)) - ((orderB !== null && orderB !== void 0 ? orderB : ttB)))
.sort(({ tt: ttA, ext: { order: orderA } }, { tt: ttB, ext: { order: orderB } }) => (orderA !== null && orderA !== void 0 ? orderA : ttA) - (orderB !== null && orderB !== void 0 ? orderB : ttB))
.map(({ tt, value, ext }) => ext.encode(source, value));
}
}

@@ -1,6 +0,6 @@

export * from "./string";
export * from "./decoder";
export * from "./encoder";
export * from "./ev-decoder";
export * from "./extensible";
export * from "./nni";
export * from "./decoder";
export * from "./extensible";
export * from "./ev-decoder";
export * from "./string";

@@ -1,6 +0,6 @@

export * from "./string.js";
export * from "./decoder.js";
export * from "./encoder.js";
export * from "./ev-decoder.js";
export * from "./extensible.js";
export * from "./nni.js";
export * from "./decoder.js";
export * from "./extensible.js";
export * from "./ev-decoder.js";
export * from "./string.js";

@@ -1,8 +0,40 @@

import { Encodable } from "./mod";
declare type Len = 1 | 4;
import { Encodable, Encoder } from "./encoder";
declare class Nni1 {
private readonly n;
constructor(n: number);
encodeTo(encoder: Encoder): void;
}
declare class Nni2 {
private readonly n;
constructor(n: number);
encodeTo(encoder: Encoder): void;
}
declare class Nni4 {
private readonly n;
constructor(n: number);
encodeTo(encoder: Encoder): void;
}
declare type Len = 1 | 2 | 4 | 8;
interface Options<LenT = Len> {
/** If set, use/enforce specific TLV-LENGTH. */
len?: LenT;
/** If true, allow approximate integers. */
unsafe?: boolean;
}
declare const EncodeNniClass: {
1: typeof Nni1;
2: typeof Nni2;
4: typeof Nni4;
};
/** Create Encodable from non-negative integer. */
export declare function NNI(n: number, len?: Len): Encodable;
export declare function NNI(n: number | bigint, { len, unsafe, }?: Options<Extract<Len, keyof typeof EncodeNniClass>>): Encodable;
export declare namespace NNI {
/** Decode non-negative integer. */
function decode(value: Uint8Array, len?: Len): number;
/** Decode non-negative integer as number. */
function decode(value: Uint8Array, opts?: Options & {
big?: false;
}): number;
/** Decode non-negative integer as bigint. */
function decode(value: Uint8Array, opts: Options & {
big: true;
}): bigint;
/** Error if n exceeds [min,max] range. */

@@ -9,0 +41,0 @@ function constrain(n: number, typeName: string, max?: number, min?: number): number;

@@ -1,86 +0,135 @@

import { Encoder } from "./mod.js";
class NNI0 {
import { Encoder } from "./encoder.js";
import { toHex } from "./string.js";
class Nni1 {
constructor(n) {
this.n = n;
}
static decode(value) {
const dv = Encoder.asDataView(value);
switch (dv.byteLength) {
case 1:
return dv.getUint8(0);
case 2:
return dv.getUint16(0);
case 4:
return dv.getUint32(0);
case 8: {
const n = dv.getUint32(0) * 0x100000000 + dv.getUint32(4);
if (!Number.isSafeInteger(n)) {
throw new Error("integer is too large");
}
return n;
}
}
throw new Error("invalid TLV-LENGTH");
encodeTo(encoder) {
encoder.prependRoom(1)[0] = this.n;
}
}
class Nni2 {
constructor(n) {
this.n = n;
}
encodeTo(encoder) {
if (this.n <= 0xFF) {
encoder.prependRoom(1)[0] = this.n;
}
else if (this.n <= 0xFFFF) {
Encoder.asDataView(encoder.prependRoom(2)).setUint16(0, this.n);
}
else if (this.n <= 0xFFFFFFFF) {
Encoder.asDataView(encoder.prependRoom(4)).setUint32(0, this.n);
}
else if (Number.isSafeInteger(this.n)) {
const dv = Encoder.asDataView(encoder.prependRoom(8));
dv.setUint32(0, this.n / 0x100000000);
dv.setUint32(4, this.n % 0x100000000);
}
else {
throw new Error("integer is too large");
}
Encoder.asDataView(encoder.prependRoom(2)).setUint16(0, this.n);
}
}
class NNI1 {
class Nni4 {
constructor(n) {
this.n = n;
}
static decode(value) {
if (value.byteLength !== 1) {
throw new Error("invalid TLV-LENGTH");
}
return value[0];
encodeTo(encoder) {
Encoder.asDataView(encoder.prependRoom(4)).setUint32(0, this.n);
}
}
class Nni8Number {
constructor(n) {
this.n = n;
}
encodeTo(encoder) {
encoder.prependRoom(1)[0] = this.n;
const dv = Encoder.asDataView(encoder.prependRoom(8));
dv.setUint32(0, this.n / 0x100000000);
dv.setUint32(4, this.n % 0x100000000);
}
}
class NNI4 {
class Nni8Big {
constructor(n) {
this.n = n;
}
static decode(value) {
if (value.byteLength !== 4) {
throw new Error("invalid TLV-LENGTH");
}
return Encoder.asDataView(value).getUint32(0);
}
encodeTo(encoder) {
Encoder.asDataView(encoder.prependRoom(4)).setUint32(0, this.n);
Encoder.asDataView(encoder.prependRoom(8)).setBigUint64(0, this.n);
}
}
const NniClass = {
0: NNI0,
1: NNI1,
4: NNI4,
const supportsBigInt = !!(DataView.prototype.getBigUint64 && DataView.prototype.setBigUint64);
const [BIG_ZERO, BIGUINT8_MAX, BIGUINT16_MAX, BIGUINT32_MAX, BIGUINT64_MAX,] = supportsBigInt ?
[
BigInt(0),
BigInt("0xFF"),
BigInt("0xFFFF"),
BigInt("0xFFFFFFFF"),
BigInt("0xFFFFFFFFFFFFFFFF"),
] :
/* istanbul ignore next */
[Number.NaN, Number.NaN, Number.NaN, Number.NaN, Number.NaN];
function decode32(dv) {
switch (dv.byteLength) {
case 1:
return dv.getUint8(0);
case 2:
return dv.getUint16(0);
case 4:
return dv.getUint32(0);
}
throw new Error("incorrect TLV-LENGTH of NNI");
}
const decodeBig = supportsBigInt ?
(dv) => {
if (dv.byteLength === 8) {
return dv.getBigUint64(0);
}
return BigInt(decode32(dv));
} :
/* istanbul ignore next */
() => Number.NaN;
const EncodeNniClass = {
1: Nni1,
2: Nni2,
4: Nni4,
};
/** Create Encodable from non-negative integer. */
export function NNI(n, len) {
return new NniClass[(len !== null && len !== void 0 ? len : 0)](n);
export function NNI(n, { len, unsafe = false, } = {}) {
if (len) {
return new EncodeNniClass[len](Number(n));
}
if (typeof n === "number") {
switch (true) {
case n < 0:
throw new RangeError("NNI cannot be negative");
case n < 0x100:
return new Nni1(n);
case n < 0x10000:
return new Nni2(n);
case n < 0x100000000:
return new Nni4(n);
case unsafe:
case Number.isSafeInteger(n):
return new Nni8Number(n);
default:
throw new RangeError("NNI is too large");
}
}
switch (true) {
case n < BIG_ZERO:
throw new RangeError("NNI cannot be negative");
case n <= BIGUINT8_MAX:
return new Nni1(Number(n));
case n <= BIGUINT16_MAX:
return new Nni2(Number(n));
case n <= BIGUINT32_MAX:
return new Nni4(Number(n));
case n <= BIGUINT64_MAX:
return new Nni8Big(n);
default:
throw new RangeError("NNI is too large");
}
}
(function (NNI) {
/** Decode non-negative integer. */
function decode(value, len) {
return NniClass[(len !== null && len !== void 0 ? len : 0)].decode(value);
function decode(value, { len, big = false, unsafe = false, } = {}) {
if (len && value.byteLength !== len) {
throw new Error(`incorrect TLV-LENGTH of NNI${len}`);
}
const dv = Encoder.asDataView(value);
if (big) {
return decodeBig(dv);
}
if (dv.byteLength === 8) {
const n = dv.getUint32(0) * 0x100000000 + dv.getUint32(4);
if (!unsafe && !Number.isSafeInteger(n)) {
throw new RangeError(`NNI is too large ${toHex(value)}`);
}
return n;
}
return decode32(dv);
}

@@ -87,0 +136,0 @@ NNI.decode = decode;

/** Pretty-print TLV-TYPE number. */
export declare function printTT(tlvType: number): string;
/** Convert byte array to hexadecimal string. */
/** Convert byte array to upper-case hexadecimal string. */
export declare function toHex(buf: Uint8Array): string;

@@ -8,4 +8,6 @@ /**

*
* This function does not have error handling. Use on trusted input only.
* This function lacks error handling. Use on trusted input only.
*/
export declare function fromHex(s: string): Uint8Array;
export declare function toUtf8(s: string): Uint8Array;
export declare function fromUtf8(buf: Uint8Array): string;

@@ -22,8 +22,8 @@ /** Pretty-print TLV-TYPE number. */

}
/** Convert byte array to hexadecimal string. */
/** Convert byte array to upper-case hexadecimal string. */
export function toHex(buf) {
const table = getHexTable();
const a = new Array(buf.length);
for (let i = 0; i < buf.length; ++i) {
a[i] = table[buf[i]];
for (const [i, element] of buf.entries()) {
a[i] = table[element];
}

@@ -35,3 +35,3 @@ return a.join("");

*
* This function does not have error handling. Use on trusted input only.
* This function lacks error handling. Use on trusted input only.
*/

@@ -41,5 +41,13 @@ export function fromHex(s) {

for (let i = 0; i < b.length; ++i) {
b[i] = parseInt(s.substr(i * 2, 2), 16);
b[i] = Number.parseInt(s.slice(i * 2, (i + 1) * 2), 16);
}
return b;
}
const textEncoder = new TextEncoder();
const textDecoder = new TextDecoder();
export function toUtf8(s) {
return textEncoder.encode(s);
}
export function fromUtf8(buf) {
return textDecoder.decode(buf);
}
{
"name": "@ndn/tlv",
"version": "0.0.20191223-beta.1",
"version": "0.0.20200606",
"description": "NDNts: TLV",

@@ -5,0 +5,0 @@ "keywords": [

@@ -42,3 +42,3 @@ # @ndn/tlv

assert.deepEqual(encoder.output,
Uint8Array.of(0xB0, 0x07, 0xC0, 0xC1, 0x07, 0x03, 0x08, 0x01, 0x41));
Uint8Array.of(0xB0, 0x07, 0xC0, 0xC1, 0x07, 0x03, 0x08, 0x01, 0x41));
```

@@ -65,3 +65,3 @@

assert(name instanceof Name);
assert.equal(name.toString(), "/A");
assert.equal(name.toString(), "/8=A");
```

@@ -92,5 +92,5 @@

class Adjacency {
public name: Name = new Name();
public uri: string = "";
public cost: number = 0;
public name = new Name();
public uri = "";
public cost = 0;
}

@@ -108,5 +108,5 @@

const EVD = new EvDecoder<Adjacency>("Adjacency", TT.Adjacency)
.add(TT.Name, (t, { decoder }) => t.name = decoder.decode(Name))
.add(TT.Uri, (t, { value }) => t.uri = new TextDecoder().decode(value))
.add(TT.Cost, (t, { nni }) => t.cost = nni);
.add(TT.Name, (t, { decoder }) => t.name = decoder.decode(Name), { required: true })
.add(TT.Uri, (t, { text }) => t.uri = text, { required: true })
.add(TT.Cost, (t, { nni }) => t.cost = nni, { required: true });
// Each rule declares a possible sub TLV.

@@ -131,8 +131,5 @@ // They are added in the order of expected appearance.

const adjacency = EVD.decode(new Adjacency(), adjacencyDecoder);
assert.equal(adjacency.name.toString(), "/A");
assert.equal(adjacency.name.toString(), "/8=A");
assert.equal(adjacency.uri, "B");
assert.equal(adjacency.cost, 128);
// Currently, EvDecoder itself cannot enforce a certain sub TLV is present.
// Pull Requests are welcome to add 'options.required' argument.
```
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc