/*! * staticwriter.js - buffer writer for bcoin * Copyright (c) 2014-2017, Christopher Jeffrey (MIT License). * https://github.com/bcoin-org/bcoin */ 'use strict'; const assert = require('assert'); const encoding = require('./encoding'); const digest = require('../crypto/digest'); const EMPTY_BUFFER = Buffer.alloc(0); /** * Statically allocated buffer writer. * @alias module:utils.StaticWriter * @constructor * @param {Number} size */ function StaticWriter(size) { if (!(this instanceof StaticWriter)) return new StaticWriter(size); this.data = Buffer.allocUnsafe(size); this.offset = 0; } /** * Allocate and render the final buffer. * @param {Boolean?} keep - Do not destroy the writer. * @returns {Buffer} Rendered buffer. */ StaticWriter.prototype.render = function render(keep) { const data = this.data; assert(this.offset === data.length); if (!keep) this.destroy(); return data; }; /** * Get size of data written so far. * @returns {Number} */ StaticWriter.prototype.getSize = function getSize() { return this.offset; }; /** * Seek to relative offset. * @param {Number} offset */ StaticWriter.prototype.seek = function seek(offset) { this.offset += offset; }; /** * Destroy the buffer writer. */ StaticWriter.prototype.destroy = function destroy() { this.data = EMPTY_BUFFER; this.offset = 0; }; /** * Write uint8. * @param {Number} value */ StaticWriter.prototype.writeU8 = function writeU8(value) { this.offset = this.data.writeUInt8(value, this.offset, true); }; /** * Write uint16le. * @param {Number} value */ StaticWriter.prototype.writeU16 = function writeU16(value) { this.offset = this.data.writeUInt16LE(value, this.offset, true); }; /** * Write uint16be. * @param {Number} value */ StaticWriter.prototype.writeU16BE = function writeU16BE(value) { this.offset = this.data.writeUInt16BE(value, this.offset, true); }; /** * Write uint32le. * @param {Number} value */ StaticWriter.prototype.writeU32 = function writeU32(value) { this.offset = this.data.writeUInt32LE(value, this.offset, true); }; /** * Write uint32be. * @param {Number} value */ StaticWriter.prototype.writeU32BE = function writeU32BE(value) { this.offset = this.data.writeUInt32BE(value, this.offset, true); }; /** * Write uint64le. * @param {Number} value */ StaticWriter.prototype.writeU64 = function writeU64(value) { this.offset = encoding.writeU64(this.data, value, this.offset); }; /** * Write uint64be. * @param {Number} value */ StaticWriter.prototype.writeU64BE = function writeU64BE(value) { this.offset = encoding.writeU64BE(this.data, value, this.offset); }; /** * Write uint64le. * @param {U64} value */ StaticWriter.prototype.writeU64N = function writeU64N(value) { this.offset = encoding.writeU64N(this.data, value, this.offset); }; /** * Write uint64be. * @param {U64} value */ StaticWriter.prototype.writeU64BEN = function writeU64BEN(value) { this.offset = encoding.writeU64BEN(this.data, value, this.offset); }; /** * Write int8. * @param {Number} value */ StaticWriter.prototype.writeI8 = function writeI8(value) { this.offset = this.data.writeInt8(value, this.offset, true); }; /** * Write int16le. * @param {Number} value */ StaticWriter.prototype.writeI16 = function writeI16(value) { this.offset = this.data.writeInt16LE(value, this.offset, true); }; /** * Write int16be. * @param {Number} value */ StaticWriter.prototype.writeI16BE = function writeI16BE(value) { this.offset = this.data.writeInt16BE(value, this.offset, true); }; /** * Write int32le. * @param {Number} value */ StaticWriter.prototype.writeI32 = function writeI32(value) { this.offset = this.data.writeInt32LE(value, this.offset, true); }; /** * Write int32be. * @param {Number} value */ StaticWriter.prototype.writeI32BE = function writeI32BE(value) { this.offset = this.data.writeInt32BE(value, this.offset, true); }; /** * Write int64le. * @param {Number} value */ StaticWriter.prototype.writeI64 = function writeI64(value) { this.offset = encoding.writeI64(this.data, value, this.offset); }; /** * Write int64be. * @param {Number} value */ StaticWriter.prototype.writeI64BE = function writeI64BE(value) { this.offset = encoding.writeI64BE(this.data, value, this.offset); }; /** * Write int64le. * @param {I64} value */ StaticWriter.prototype.writeI64N = function writeI64N(value) { this.offset = encoding.writeI64N(this.data, value, this.offset); }; /** * Write int64be. * @param {I64} value */ StaticWriter.prototype.writeI64BEN = function writeI64BEN(value) { this.offset = encoding.writeI64BEN(this.data, value, this.offset); }; /** * Write float le. * @param {Number} value */ StaticWriter.prototype.writeFloat = function writeFloat(value) { this.offset = this.data.writeFloatLE(value, this.offset, true); }; /** * Write float be. * @param {Number} value */ StaticWriter.prototype.writeFloatBE = function writeFloatBE(value) { this.offset = this.data.writeFloatBE(value, this.offset, true); }; /** * Write double le. * @param {Number} value */ StaticWriter.prototype.writeDouble = function writeDouble(value) { this.offset = this.data.writeDoubleLE(value, this.offset, true); }; /** * Write double be. * @param {Number} value */ StaticWriter.prototype.writeDoubleBE = function writeDoubleBE(value) { this.offset = this.data.writeDoubleBE(value, this.offset, true); }; /** * Write a varint. * @param {Number} value */ StaticWriter.prototype.writeVarint = function writeVarint(value) { this.offset = encoding.writeVarint(this.data, value, this.offset); }; /** * Write a varint. * @param {U64} value */ StaticWriter.prototype.writeVarintN = function writeVarintN(value) { this.offset = encoding.writeVarintN(this.data, value, this.offset); }; /** * Write a varint (type 2). * @param {Number} value */ StaticWriter.prototype.writeVarint2 = function writeVarint2(value) { this.offset = encoding.writeVarint2(this.data, value, this.offset); }; /** * Write a varint (type 2). * @param {U64} value */ StaticWriter.prototype.writeVarint2N = function writeVarint2N(value) { this.offset = encoding.writeVarint2N(this.data, value, this.offset); }; /** * Write bytes. * @param {Buffer} value */ StaticWriter.prototype.writeBytes = function writeBytes(value) { if (value.length === 0) return; value.copy(this.data, this.offset); this.offset += value.length; }; /** * Write bytes with a varint length before them. * @param {Buffer} value */ StaticWriter.prototype.writeVarBytes = function writeVarBytes(value) { this.writeVarint(value.length); this.writeBytes(value); }; /** * Copy bytes. * @param {Buffer} value * @param {Number} start * @param {Number} end */ StaticWriter.prototype.copy = function copy(value, start, end) { const len = end - start; if (len === 0) return; value.copy(this.data, this.offset, start, end); this.offset += len; }; /** * Write string to buffer. * @param {String} value * @param {String?} enc - Any buffer-supported encoding. */ StaticWriter.prototype.writeString = function writeString(value, enc) { if (value.length === 0) return; const size = Buffer.byteLength(value, enc); this.data.write(value, this.offset, enc); this.offset += size; }; /** * Write a 32 byte hash. * @param {Hash} value */ StaticWriter.prototype.writeHash = function writeHash(value) { if (typeof value !== 'string') { assert(value.length === 32); this.writeBytes(value); return; } assert(value.length === 64); this.data.write(value, this.offset, 'hex'); this.offset += 32; }; /** * Write a string with a varint length before it. * @param {String} * @param {String?} enc - Any buffer-supported encoding. */ StaticWriter.prototype.writeVarString = function writeVarString(value, enc) { if (value.length === 0) { this.writeVarint(0); return; } const size = Buffer.byteLength(value, enc); this.writeVarint(size); this.data.write(value, this.offset, enc); this.offset += size; }; /** * Write a null-terminated string. * @param {String|Buffer} * @param {String?} enc - Any buffer-supported encoding. */ StaticWriter.prototype.writeNullString = function writeNullString(value, enc) { this.writeString(value, enc); this.writeU8(0); }; /** * Calculate and write a checksum for the data written so far. */ StaticWriter.prototype.writeChecksum = function writeChecksum() { const data = this.data.slice(0, this.offset); const hash = digest.hash256(data); hash.copy(this.data, this.offset, 0, 4); this.offset += 4; }; /** * Fill N bytes with value. * @param {Number} value * @param {Number} size */ StaticWriter.prototype.fill = function fill(value, size) { assert(size >= 0); if (size === 0) return; this.data.fill(value, this.offset, this.offset + size); this.offset += size; }; /* * Expose */ module.exports = StaticWriter;