var hpack = require('../hpack'); var utils = hpack.utils; var decoder = hpack.decoder; var table = hpack.table; var assert = utils.assert; var inherits = require('inherits'); var Duplex = require('readable-stream').Duplex; function Decompressor(options) { Duplex.call(this, { readableObjectMode: true }); this._decoder = decoder.create(); this._table = table.create(options.table); } inherits(Decompressor, Duplex); module.exports = Decompressor; Decompressor.create = function create(options) { return new Decompressor(options); }; Decompressor.prototype._read = function _read() { // We only push! }; Decompressor.prototype._write = function _write(data, enc, cb) { this._decoder.push(data); cb(null); }; Decompressor.prototype.execute = function execute(cb) { while (!this._decoder.isEmpty()) { try { this._execute(); } catch (err) { if (cb) return done(err); else return this.emit('error', err); } } if (cb) done(null); function done(err) { process.nextTick(function() { cb(err); }); } }; Decompressor.prototype.updateTableSize = function updateTableSize(size) { this._table.updateSize(size); }; Decompressor.prototype._execute = function _execute() { var isIndexed = this._decoder.decodeBit(); if (isIndexed) return this._processIndexed(); var isIncremental = this._decoder.decodeBit(); var neverIndex = 0; if (!isIncremental) { var isUpdate = this._decoder.decodeBit(); if (isUpdate) return this._processUpdate(); neverIndex = this._decoder.decodeBit(); } this._processLiteral(isIncremental, neverIndex); }; Decompressor.prototype._processIndexed = function _processIndexed() { var index = this._decoder.decodeInt(); var lookup = this._table.lookup(index); this.push({ name: lookup.name, value: lookup.value, neverIndex: false }); }; Decompressor.prototype._processLiteral = function _processLiteral(inc, never) { var index = this._decoder.decodeInt(); var name; var nameSize; // Literal header-name too if (index === 0) { name = this._decoder.decodeStr(); nameSize = name.length; name = utils.stringify(name); } else { var lookup = this._table.lookup(index); nameSize = lookup.nameSize; name = lookup.name; } var value = this._decoder.decodeStr(); var valueSize = value.length; value = utils.stringify(value); if (inc) this._table.add(name, value, nameSize, valueSize); this.push({ name: name, value: value, neverIndex: never !== 0}); }; Decompressor.prototype._processUpdate = function _processUpdate() { var size = this._decoder.decodeInt(); this.updateTableSize(size); };