UNPKG

@ndn/tlv

Version:
138 lines (137 loc) 4.06 kB
import { toHex, toUtf8 } from "@ndn/util"; import { Decoder } from "./decoder_browser.js"; import { Encoder } from "./encoder_browser.js"; import { NNI } from "./nni_browser.js"; export var StructFieldType; (function (StructFieldType) { /** * Turn a TLV class into a field type, where the TLV directly appears as the field. * * @example * Given this structure: * ```abnf * Outer = OUTER-TYPE TLV-LENGTH Inner * Inner = INNER-TYPE TLV-LENGTH INNER-VALUE * ``` * * You can define the `Outer` builder: * ```ts * const buildOuter = new StructBuilder("Outer", TT.Outer) * .add(TT.Inner, "inner", StructFieldType.wrap(Inner)); * ``` * * `Inner` type must encode itself as a TLV, and its TLV-TYPE must equal field TLV-TYPE. */ function wrap(F, overrides = {}) { return { newValue: () => new F(), encode: (value) => { const d = new Decoder(Encoder.encode(value)); return d.read().value; }, decode: ({ decoder }) => decoder.decode(F), asString: (value) => value.toString(), ...overrides, }; } StructFieldType.wrap = wrap; /** * Turn a TLV class into a field type, where the TLV is nested inside the field. * * @example * Given this structure: * ```abnf * Outer = OUTER-TYPE TLV-LENGTH Middle * Middle = MIDDLE-TYPE TLV-LENGTH Inner * Inner = INNER-TYPE TLV-LENGTH INNER-VALUE * ``` * * You can define the `Outer` builder: * ```ts * const buildOuter = new StructBuilder("Outer", TT.Outer) * .add(TT.Middle, "inner", StructFieldType.nest(Inner)); * ``` * * `Inner` type does not have to encode itself as a TLV. Its encoding result appears as * the TLV-VALUE of the "middle" field TLV. */ function nest(F, overrides = {}) { return { newValue: () => new F(), encode: (value) => value, decode: ({ vd }) => vd.decode(F), asString: (value) => value.toString(), ...overrides, }; } StructFieldType.nest = nest; })(StructFieldType || (StructFieldType = {})); export const StructFieldBool = { newValue: () => false, encode: (value) => value ? new Uint8Array(0) : Encoder.OmitEmpty, decode: () => true, }; /** * StructBuilder field type of non-negative integer. * * @remarks * The field is defined as number. * If the field is required, it is initialized as zero. */ export const StructFieldNNI = { newValue: () => 0, encode: NNI, decode: ({ nni }) => nni, }; /** * StructBuilder field type of non-negative integer. * * @remarks * The field is defined as bigint. * If the field is required, it is initialized as zero. */ export const StructFieldNNIBig = { newValue: () => 0n, encode: NNI, decode: ({ nniBig }) => nniBig, }; /** * Declare a StructBuilder field type of non-negative integer from an enum. * @param Enum - A flat (not OR'ed flags) enum type. * * @remarks * The field is defined as a flat enum type. * If the field is required, it is initialized as zero. */ export function StructFieldEnum(Enum) { return { ...StructFieldNNI, asString: (value) => `${value}(${Enum[value] ?? "unknown"})`, }; } /** * StructBuilder field type of UTF-8 text. * * @remarks * The field is defined as string. * If the field is required, it is initialized as an empty string. */ export const StructFieldText = { newValue: () => "", encode: toUtf8, decode: ({ text }) => text, asString: (value) => JSON.stringify(value), }; /** * StructBuilder field type of raw bytes. * * @remarks * The field is defined as Uint8Array. * If the field is required, it is initialized as an empty Uint8Array. */ export const StructFieldBytes = { newValue: () => new Uint8Array(), encode: (value) => value, decode: ({ value }) => value, asString: (value) => toHex(value), };