source: trip-planner-front/node_modules/hpack.js/lib/hpack/decoder.js@ 76712b2

Last change on this file since 76712b2 was 6a3a178, checked in by Ema <ema_spirova@…>, 3 years ago

initial commit

  • Property mode set to 100644
File size: 3.8 KB
RevLine 
[6a3a178]1var hpack = require('../hpack');
2var utils = hpack.utils;
3var huffman = hpack.huffman.decode;
4var assert = utils.assert;
5
6var OffsetBuffer = require('obuf');
7
8function Decoder() {
9 this.buffer = new OffsetBuffer();
10 this.bitOffset = 0;
11
12 // Used internally in decodeStr
13 this._huffmanNode = null;
14}
15module.exports = Decoder;
16
17Decoder.create = function create() {
18 return new Decoder();
19};
20
21Decoder.prototype.isEmpty = function isEmpty() {
22 return this.buffer.isEmpty();
23};
24
25Decoder.prototype.push = function push(chunk) {
26 this.buffer.push(chunk);
27};
28
29Decoder.prototype.decodeBit = function decodeBit() {
30 // Need at least one octet
31 assert(this.buffer.has(1), 'Buffer too small for an int');
32
33 var octet;
34 var offset = this.bitOffset;
35
36 if (++this.bitOffset === 8) {
37 octet = this.buffer.readUInt8();
38 this.bitOffset = 0;
39 } else {
40 octet = this.buffer.peekUInt8();
41 }
42 return (octet >>> (7 - offset)) & 1;
43};
44
45// Just for testing
46Decoder.prototype.skipBits = function skipBits(n) {
47 this.bitOffset += n;
48 this.buffer.skip(this.bitOffset >> 3);
49 this.bitOffset &= 0x7;
50};
51
52Decoder.prototype.decodeInt = function decodeInt() {
53 // Need at least one octet
54 assert(this.buffer.has(1), 'Buffer too small for an int');
55
56 var prefix = 8 - this.bitOffset;
57
58 // We are going to end up octet-aligned
59 this.bitOffset = 0;
60
61 var max = (1 << prefix) - 1;
62 var octet = this.buffer.readUInt8() & max;
63
64 // Fast case - int fits into the prefix
65 if (octet !== max)
66 return octet;
67
68 // TODO(indutny): what about > 32bit numbers?
69 var res = 0;
70 var isLast = false;
71 var len = 0;
72 do {
73 octet = this.buffer.readUInt8();
74 isLast = (octet & 0x80) === 0;
75
76 res <<= 7;
77 res |= octet & 0x7f;
78 len++;
79 } while (!isLast);
80 assert(isLast, 'Incomplete data for multi-octet integer');
81 assert(len <= 4, 'Integer does not fit into 32 bits');
82
83 // Reverse bits
84 res = (res >>> 21) |
85 (((res >> 14) & 0x7f) << 7) |
86 (((res >> 7) & 0x7f) << 14) |
87 ((res & 0x7f) << 21);
88 res >>= (4 - len) * 7;
89
90 // Append prefix max
91 res += max;
92
93 return res;
94};
95
96Decoder.prototype.decodeHuffmanWord = function decodeHuffmanWord(input,
97 inputBits,
98 out) {
99 var root = huffman;
100 var node = this._huffmanNode;
101 var word = input;
102 var bits = inputBits;
103
104 for (; bits > 0; word &= (1 << bits) - 1) {
105 // Nudge the word bit length to match it
106 for (var i = Math.max(0, bits - 8); i < bits; i++) {
107 var subnode = node[word >>> i];
108 if (typeof subnode !== 'number') {
109 node = subnode;
110 bits = i;
111 break;
112 }
113
114 if (subnode === 0)
115 continue;
116
117 // Word bit length should match
118 if ((subnode >>> 9) !== bits - i) {
119 subnode = 0;
120 continue;
121 }
122
123 var octet = subnode & 0x1ff;
124 assert(octet !== 256, 'EOS in encoding');
125 out.push(octet);
126 node = root;
127
128 bits = i;
129 break;
130 }
131 if (subnode === 0)
132 break;
133 }
134 this._huffmanNode = node;
135
136 return bits;
137};
138
139Decoder.prototype.decodeStr = function decodeStr() {
140 var isHuffman = this.decodeBit();
141 var len = this.decodeInt();
142 assert(this.buffer.has(len), 'Not enough octets for string');
143
144 if (!isHuffman)
145 return this.buffer.take(len);
146
147 this._huffmanNode = huffman;
148
149 var out = [];
150
151 var word = 0;
152 var bits = 0;
153 var lastKey = 0;
154 for (var i = 0; i < len; i++) {
155 word <<= 8;
156 word |= this.buffer.readUInt8();
157 bits += 8;
158
159 bits = this.decodeHuffmanWord(word, bits, out);
160 lastKey = word >> bits;
161 word &= (1 << bits) - 1;
162 }
163 assert(this._huffmanNode === huffman, '8-bit EOS');
164 assert(word + 1 === (1 << bits), 'Final sequence is not EOS');
165
166 this._huffmanNode = null;
167
168 return out;
169};
Note: See TracBrowser for help on using the repository browser.