UNPKG

6.42 kBJavaScriptView Raw
1// decoder.js
2
3exports.Decoder = Decoder;
4
5var BufferLite = require("./buffer-lite");
6var extdecoders = require("./ext").decoders;
7
8var IS_BUFFER_SHIM = ("TYPED_ARRAY_SUPPORT" in Buffer);
9var NO_ASSERT = true;
10
11function Decoder(opts) {
12 if (!(this instanceof Decoder)) return new Decoder(opts);
13 if (opts && opts.push) this.push = opts.push.bind(opts);
14}
15
16Decoder.prototype.decode = function(chunk, encoding, callback) {
17 if (!this.buffer) {
18 // first chunk
19 this.buffer = chunk;
20 } else {
21 // later chunk
22 var prev = this.offset ? this.buffer.slice(this.offset) : this.buffer;
23 this.buffer = Buffer.concat([prev, chunk]);
24 }
25
26 this.bufferLength = this.buffer.length;
27 this.offset = 0;
28
29 // try to decode
30 this.flush();
31
32 // stream.Transform.prototype._transform support
33 if (callback) callback();
34};
35
36Decoder.prototype.flush = function() {
37 if (!this.bufferLength) return;
38 var start = this.offset;
39 var value = decode(this);
40 if (value === BUFFER_SHORTAGE) {
41 this.offset = start;
42 return;
43 }
44 this.push(value);
45 return this.flush();
46};
47
48var token = [];
49var uint8 = read(1, Buffer.prototype.readUInt8);
50
51init();
52
53function init() {
54 var i;
55
56 var uint16 = read(2, Buffer.prototype.readUInt16BE);
57 var uint32 = read(4, Buffer.prototype.readUInt32BE);
58 var uint64 = read(8, readUInt64BE);
59 var int8 = read(1, Buffer.prototype.readInt8);
60 var int16 = read(2, Buffer.prototype.readInt16BE);
61 var int32 = read(4, Buffer.prototype.readInt32BE);
62 var int64 = read(8, readInt64BE);
63 var float32 = read(4, Buffer.prototype.readFloatBE);
64 var float64 = read(8, Buffer.prototype.readDoubleBE);
65
66 // positive fixint -- 0x00 - 0x7f
67 for (i = 0x00; i <= 0x7f; i++) {
68 token[i] = constant(i);
69 }
70
71 // fixmap -- 0x80 - 0x8f
72 for (i = 0x80; i <= 0x8f; i++) {
73 token[i] = fix(i - 0x80, map);
74 }
75
76 // fixarray -- 0x90 - 0x9f
77 for (i = 0x90; i <= 0x9f; i++) {
78 token[i] = fix(i - 0x90, array);
79 }
80
81 // fixstr -- 0xa0 - 0xbf
82 for (i = 0xa0; i <= 0xbf; i++) {
83 token[i] = fix(i - 0xa0, str);
84 }
85
86 // nil -- 0xc0
87 token[0xc0] = constant(null);
88
89 // (never used) -- 0xc1
90 token[0xc1] = constant(new Error("Invalid MessagePack token: 0xC1"));
91
92 // false -- 0xc2
93 // true -- 0xc3
94 token[0xc2] = constant(false);
95 token[0xc3] = constant(true);
96
97 // bin 8 -- 0xc4
98 // bin 16 -- 0xc5
99 // bin 32 -- 0xc6
100 token[0xc4] = flex(uint8, bin);
101 token[0xc5] = flex(uint16, bin);
102 token[0xc6] = flex(uint32, bin);
103
104 // ext 8 -- 0xc7
105 // ext 16 -- 0xc8
106 // ext 32 -- 0xc9
107 token[0xc7] = flex(uint8, ext);
108 token[0xc8] = flex(uint16, ext);
109 token[0xc9] = flex(uint32, ext);
110
111 // float 32 -- 0xca
112 // float 64 -- 0xcb
113 token[0xca] = float32;
114 token[0xcb] = float64;
115
116 // uint 8 -- 0xcc
117 // uint 16 -- 0xcd
118 // uint 32 -- 0xce
119 // uint 64 -- 0xcf
120 token[0xcc] = uint8;
121 token[0xcd] = uint16;
122 token[0xce] = uint32;
123 token[0xcf] = uint64;
124
125 // int 8 -- 0xd0
126 // int 16 -- 0xd1
127 // int 32 -- 0xd2
128 // int 64 -- 0xd3
129 token[0xd0] = int8;
130 token[0xd1] = int16;
131 token[0xd2] = int32;
132 token[0xd3] = int64;
133
134 // fixext 1 -- 0xd4
135 // fixext 2 -- 0xd5
136 // fixext 4 -- 0xd6
137 // fixext 8 -- 0xd7
138 // fixext 16 -- 0xd8
139 token[0xd4] = fix(1, ext);
140 token[0xd5] = fix(2, ext);
141 token[0xd6] = fix(4, ext);
142 token[0xd7] = fix(8, ext);
143 token[0xd8] = fix(16, ext);
144
145 // str 8 -- 0xd9
146 // str 16 -- 0xda
147 // str 32 -- 0xdb
148 // array 16 -- 0xdc
149 // array 32 -- 0xdd
150 // map 16 -- 0xde
151 // map 32 -- 0xdf
152 token[0xd9] = flex(uint8, str);
153 token[0xda] = flex(uint16, str);
154 token[0xdb] = flex(uint32, str);
155 token[0xdc] = flex(uint16, array);
156 token[0xdd] = flex(uint32, array);
157 token[0xde] = flex(uint16, map);
158 token[0xdf] = flex(uint32, map);
159
160 // negative fixint -- 0xe0 - 0xff
161 for (i = 0xe0; i <= 0xff; i++) {
162 token[i] = constant(i - 0x100);
163 }
164}
165
166function decode(decoder) {
167 var type = uint8(decoder);
168 if (type === BUFFER_SHORTAGE) return type;
169 var func = token[type];
170 if (!func) throw new Error("Invalid MessagePack token: 0x" + (type.toString(16)));
171 return func(decoder);
172}
173
174function constant(value) {
175 return function(decoder) {
176 return value;
177 };
178}
179
180function flex(lenFunc, decodeFunc) {
181 return function(decoder) {
182 var len = lenFunc(decoder);
183 return decodeFunc(decoder, len);
184 };
185}
186
187function fix(len, method) {
188 return function(decoder) {
189 return method(decoder, len);
190 };
191}
192
193function map(decoder, len) {
194 var value = {};
195 for (var i = 0; i < len; i++) {
196 var key = decode(decoder);
197 value[key] = decode(decoder);
198 }
199 return value;
200}
201
202function array(decoder, len) {
203 var value = new Array(len);
204 for (var i = 0; i < len; i++) {
205 value[i] = decode(decoder);
206 }
207 return value;
208}
209
210function str(decoder, len) {
211 var start = decoder.offset;
212 var end = start + len;
213 if (end > decoder.bufferLength) return BUFFER_SHORTAGE;
214 decoder.offset = end;
215
216 if (IS_BUFFER_SHIM) {
217 // slower (compat)
218 return BufferLite.readString.call(decoder.buffer, start, end);
219 } else {
220 // 2x faster
221 return decoder.buffer.toString("utf-8", start, end);
222 }
223}
224
225function read(len, method) {
226 return function(decoder) {
227 var start = decoder.offset;
228 var end = start + len;
229 if (end > decoder.bufferLength) return BUFFER_SHORTAGE;
230 var value = method.call(decoder.buffer, start, NO_ASSERT);
231 decoder.offset = end;
232 return value;
233 };
234}
235
236function readUInt64BE(start, noAssert) {
237 var upper = this.readUInt32BE(start, noAssert);
238 var lower = this.readUInt32BE(start + 4, noAssert);
239 return upper ? (upper * 4294967296 + lower) : lower;
240}
241
242function readInt64BE(start, noAssert) {
243 var upper = this.readInt32BE(start, noAssert);
244 var lower = this.readUInt32BE(start + 4, noAssert);
245 return upper ? (upper * 4294967296 + lower) : lower;
246}
247
248function bin(decoder, len) {
249 var start = decoder.offset;
250 var end = start + len;
251 if (end > decoder.bufferLength) return BUFFER_SHORTAGE;
252 var buf = decoder.buffer.slice(start, end);
253 decoder.offset = end;
254 return buf;
255}
256
257function ext(decoder, len) {
258 var start = decoder.offset;
259 var end = start + len + 1;
260 if (end > decoder.bufferLength) return BUFFER_SHORTAGE;
261 var type = decoder.buffer[start];
262 decoder.offset = end;
263
264 var e = extdecoders[type];
265 if (e) {
266 var buf = decoder.buffer.slice(start + 1, end);
267 return e.decode(buf);
268 }
269
270 return decoder.buffer.slice(start, end);
271}
272
273function BUFFER_SHORTAGE() {
274}
\No newline at end of file