| 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); | 
| }; |