| var hpack = require('../hpack'); |
| var utils = hpack.utils; |
| var assert = utils.assert; |
| |
| function Table(options) { |
| this['static'] = hpack['static-table']; |
| this.dynamic = []; |
| this.size = 0; |
| this.maxSize = 0; |
| this.length = this['static'].table.length; |
| this.protocolMaxSize = options.maxSize; |
| this.maxSize = this.protocolMaxSize; |
| this.lookupDepth = options.lookupDepth || 32; |
| } |
| module.exports = Table; |
| |
| Table.create = function create(options) { |
| return new Table(options); |
| }; |
| |
| Table.prototype.lookup = function lookup(index) { |
| assert(index !== 0, 'Zero indexed field'); |
| assert(index <= this.length, 'Indexed field OOB') |
| |
| if (index <= this['static'].table.length) |
| return this['static'].table[index - 1]; |
| else |
| return this.dynamic[this.length - index]; |
| }; |
| |
| Table.prototype.reverseLookup = function reverseLookup(name, value) { |
| var staticEntry = this['static'].map[name]; |
| if (staticEntry && staticEntry.values[value]) |
| return staticEntry.values[value]; |
| |
| // Reverse search dynamic table (new items are at the end of it) |
| var limit = Math.max(0, this.dynamic.length - this.lookupDepth); |
| for (var i = this.dynamic.length - 1; i >= limit; i--) { |
| var entry = this.dynamic[i]; |
| if (entry.name === name && entry.value === value) |
| return this.length - i; |
| |
| if (entry.name === name) { |
| // Prefer smaller index |
| if (staticEntry) |
| break; |
| return -(this.length - i); |
| } |
| } |
| |
| if (staticEntry) |
| return -staticEntry.index; |
| |
| return 0; |
| }; |
| |
| Table.prototype.add = function add(name, value, nameSize, valueSize) { |
| var totalSize = nameSize + valueSize + 32; |
| |
| this.dynamic.push({ |
| name: name, |
| value: value, |
| nameSize: nameSize, |
| totalSize: totalSize |
| }); |
| this.size += totalSize; |
| this.length++; |
| |
| this.evict(); |
| }; |
| |
| Table.prototype.evict = function evict() { |
| while (this.size > this.maxSize) { |
| var entry = this.dynamic.shift(); |
| this.size -= entry.totalSize; |
| this.length--; |
| } |
| assert(this.size >= 0, 'Table size sanity check failed'); |
| }; |
| |
| Table.prototype.updateSize = function updateSize(size) { |
| assert(size <= this.protocolMaxSize, 'Table size bigger than maximum'); |
| this.maxSize = size; |
| this.evict(); |
| }; |