UNPKG

@aokiapp/tlv

Version:

Tag-Length-Value (TLV) parser and builder library with schema support. Provides both parsing and building APIs as submodules.

96 lines (95 loc) 3.56 kB
import { TagClass } from "../common/types.js"; export class BasicTLVParser { /** * Parse a buffer containing a single TLV structure. * @param buffer - The TLV data buffer to parse. * @returns The parsed result including tag, length, and value. */ static parse(buffer) { const view = new DataView(buffer); let offset = 0; const tagInfo = this.readTagInfo(view, offset); offset = tagInfo.newOffset; const lengthInfo = this.readLength(view, offset); offset = lengthInfo.newOffset; const valueInfo = this.readValue(buffer, offset, lengthInfo.length); offset = valueInfo.newOffset; return { tag: tagInfo.tag, length: lengthInfo.length, value: valueInfo.value, endOffset: offset, }; } /** * Read the tag portion from the DataView and update the offset. * @param view - The DataView representing the TLV buffer. * @param offset - The current read position within the buffer. * @returns An object containing the parsed tag information and the new offset. */ static readTagInfo(view, offset) { const firstByte = view.getUint8(offset++); const tagClassBits = (firstByte & 0xc0) >> 6; const tagClass = this.getTagClass(tagClassBits); const isConstructed = !!(firstByte & 0x20); let tagNumber = firstByte & 0x1f; if (tagNumber === 0x1f) { tagNumber = 0; let b; do { b = view.getUint8(offset++); tagNumber = (tagNumber << 7) | (b & 0x7f); } while (b & 0x80); } return { tag: { tagClass, constructed: isConstructed, tagNumber }, newOffset: offset, }; } /** * Convert tag class bits into a TagClass enum value. * @param {number} bits - The bits extracted from the tag byte. * @returns {TagClass} The corresponding TagClass. */ static getTagClass(bits) { switch (bits) { case 0: return TagClass.Universal; case 1: return TagClass.Application; case 2: return TagClass.ContextSpecific; case 3: return TagClass.Private; } throw new Error("Invalid tag class"); } /** * Read the length portion from the DataView and update the offset. * @param view - The DataView representing the TLV buffer. * @param offset - The current read position within the buffer. * @returns An object containing the parsed length and the new offset. */ static readLength(view, offset) { let length = view.getUint8(offset++); if (length & 0x80) { const numBytes = length & 0x7f; length = 0; for (let i = 0; i < numBytes; i++) { length = (length << 8) | view.getUint8(offset++); } } return { length, newOffset: offset }; } /** * Read the value portion from the buffer based on the specified length. * @param buffer - The original TLV data buffer. * @param offset - The current read position within the buffer. * @param length - The length of the TLV value. * @returns An object containing the raw value slice and the new offset. */ static readValue(buffer, offset, length) { const value = buffer.slice(offset, offset + length); return { value, newOffset: offset + length }; } }