UNPKG

ndn-js

Version:

A JavaScript client library for Named Data Networking

245 lines (227 loc) 8.76 kB
/** * Copyright (C) 2014-2019 Regents of the University of California. * @author: Jeff Thompson <jefft0@remap.ucla.edu> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. * A copy of the GNU Lesser General Public License is in the file COPYING. */ /** @ignore */ var DynamicBuffer = require('../../util/dynamic-buffer.js').DynamicBuffer; /** @ignore */ var Tlv = require('./tlv.js').Tlv; /** * Create a new TlvEncoder with an initialCapacity for the encoding buffer. * @constructor * @param {number} initialCapacity (optional) The initial capacity of the * encoding buffer. If omitted, use a default value. */ var TlvEncoder = function TlvEncoder(initialCapacity) { initialCapacity = initialCapacity || 16; this.output = new DynamicBuffer(initialCapacity); // length is the number of bytes that have been written to the back of // this.output.array. this.length = 0; }; exports.TlvEncoder = TlvEncoder; /** * Get the number of bytes that have been written to the output. You can * save this number, write sub TLVs, then subtract the new length from this * to get the total length of the sub TLVs. * @return {number} The number of bytes that have been written to the output. */ TlvEncoder.prototype.getLength = function() { return this.length; }; /** * Encode varNumber as a VAR-NUMBER in NDN-TLV and write it to this.output just * before this.length from the back. Advance this.length. * @param {number} varNumber The non-negative number to encode. */ TlvEncoder.prototype.writeVarNumber = function(varNumber) { if (varNumber < 253) { this.length += 1; this.output.ensureLengthFromBack(this.length); this.output.array[this.output.array.length - this.length] = varNumber & 0xff; } else if (varNumber <= 0xffff) { this.length += 3; this.output.ensureLengthFromBack(this.length); var offset = this.output.array.length - this.length; this.output.array[offset] = 253; this.output.array[offset + 1] = (varNumber >> 8) & 0xff; this.output.array[offset + 2] = varNumber & 0xff; } else if (varNumber <= 0xffffffff) { this.length += 5; this.output.ensureLengthFromBack(this.length); var offset = this.output.array.length - this.length; this.output.array[offset] = 254; this.output.array[offset + 1] = (varNumber >> 24) & 0xff; this.output.array[offset + 2] = (varNumber >> 16) & 0xff; this.output.array[offset + 3] = (varNumber >> 8) & 0xff; this.output.array[offset + 4] = varNumber & 0xff; } else { this.length += 9; this.output.ensureLengthFromBack(this.length); var offset = this.output.array.length - this.length; this.output.array[offset] = 255; var highBytes = Tlv.getHighBytes(varNumber); this.output.array[offset + 1] = (highBytes >> 24) & 0xff; this.output.array[offset + 2] = (highBytes >> 16) & 0xff; this.output.array[offset + 3] = (highBytes >> 8) & 0xff; this.output.array[offset + 4] = (highBytes) & 0xff; this.output.array[offset + 5] = (varNumber >> 24) & 0xff; this.output.array[offset + 6] = (varNumber >> 16) & 0xff; this.output.array[offset + 7] = (varNumber >> 8) & 0xff; this.output.array[offset + 8] = varNumber & 0xff; } }; /** * Encode the type and length as VAR-NUMBER and write to this.output just before * this.length from the back. Advance this.length. * @param {number} type The type of the TLV. * @param {number} length The non-negative length of the TLV. */ TlvEncoder.prototype.writeTypeAndLength = function(type, length) { // Write backwards. this.writeVarNumber(length); this.writeVarNumber(type); }; /** * Write value as a non-negative integer and write it to this.output just before * this.length from the back. Advance this.length. * @param {number} value The non-negative integer to encode. */ TlvEncoder.prototype.writeNonNegativeInteger = function(value) { if (value < 0) throw new Error("TLV integer value may not be negative"); // JavaScript doesn't distinguish int from float, so round. value = Math.round(value); if (value <= 0xff) { this.length += 1; this.output.ensureLengthFromBack(this.length); this.output.array[this.output.array.length - this.length] = value & 0xff; } else if (value <= 0xffff) { this.length += 2; this.output.ensureLengthFromBack(this.length); var offset = this.output.array.length - this.length; this.output.array[offset] = (value >> 8) & 0xff; this.output.array[offset + 1] = value & 0xff; } else if (value <= 0xffffffff) { this.length += 4; this.output.ensureLengthFromBack(this.length); var offset = this.output.array.length - this.length; this.output.array[offset] = (value >> 24) & 0xff; this.output.array[offset + 1] = (value >> 16) & 0xff; this.output.array[offset + 2] = (value >> 8) & 0xff; this.output.array[offset + 3] = value & 0xff; } else { this.length += 8; this.output.ensureLengthFromBack(this.length); var offset = this.output.array.length - this.length; var highBytes = Tlv.getHighBytes(value); this.output.array[offset] = (highBytes >> 24) & 0xff; this.output.array[offset + 1] = (highBytes >> 16) & 0xff; this.output.array[offset + 2] = (highBytes >> 8) & 0xff; this.output.array[offset + 3] = (highBytes) & 0xff; this.output.array[offset + 4] = (value >> 24) & 0xff; this.output.array[offset + 5] = (value >> 16) & 0xff; this.output.array[offset + 6] = (value >> 8) & 0xff; this.output.array[offset + 7] = value & 0xff; } }; /** * Write the type, then the length of the encoded value then encode value as a * non-negative integer and write it to this.output just before this.length from * the back. Advance this.length. * @param {number} type The type of the TLV. * @param {number} value The non-negative integer to encode. */ TlvEncoder.prototype.writeNonNegativeIntegerTlv = function(type, value) { // Write backwards. var saveNBytes = this.length; this.writeNonNegativeInteger(value); this.writeTypeAndLength(type, this.length - saveNBytes); }; /** * If value is negative or null then do nothing, otherwise call * writeNonNegativeIntegerTlv. * @param {number} type The type of the TLV. * @param {number} value If negative or null do nothing, otherwise the integer * to encode. */ TlvEncoder.prototype.writeOptionalNonNegativeIntegerTlv = function(type, value) { if (value != null && value >= 0) this.writeNonNegativeIntegerTlv(type, value); }; /** * Write the buffer value to this.output just before this.length from the back. * Advance this.length. * @param {Buffer} buffer The byte array with the bytes to write. If value is * null, then do nothing. */ TlvEncoder.prototype.writeBuffer = function(buffer) { if (buffer == null) return; this.length += buffer.length; this.output.copyFromBack(buffer, this.length); }; /** * Write the type, then the length of the buffer then the buffer value to * this.output just before this.length from the back. Advance this.length. * @param {number} type The type of the TLV. * @param {Buffer} value The byte array with the bytes of the blob. If value is null, then just write the type and length 0. */ TlvEncoder.prototype.writeBlobTlv = function(type, value) { if (value == null) { this.writeTypeAndLength(type, 0); return; } // Write backwards, starting with the blob array. this.writeBuffer(value); this.writeTypeAndLength(type, value.length); }; /** * If the byte array is null or zero length then do nothing, otherwise call * writeBlobTlv. * @param {number} type The type of the TLV. * @param {Buffer} value If null or zero length do nothing, otherwise the byte * array with the bytes of the blob. */ TlvEncoder.prototype.writeOptionalBlobTlv = function(type, value) { if (value != null && value.length > 0) this.writeBlobTlv(type, value); }; /** * Get a slice of the encoded bytes. * @return {Buffer} A slice backed by the encoding Buffer. */ TlvEncoder.prototype.getOutput = function() { return this.output.array.slice(this.output.array.length - this.length); };