OLD | NEW |
| (Empty) |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 define("mojo/public/js/bindings/codec", [ | |
6 "mojo/public/js/bindings/unicode", | |
7 "mojo/public/js/bindings/buffer", | |
8 ], function(unicode, buffer) { | |
9 | |
10 var kErrorUnsigned = "Passing negative value to unsigned"; | |
11 | |
12 // Memory ------------------------------------------------------------------- | |
13 | |
14 var kAlignment = 8; | |
15 | |
16 function align(size) { | |
17 return size + (kAlignment - (size % kAlignment)) % kAlignment; | |
18 } | |
19 | |
20 function isAligned(offset) { | |
21 return offset >= 0 && (offset % kAlignment) === 0; | |
22 } | |
23 | |
24 // Constants ---------------------------------------------------------------- | |
25 | |
26 var kArrayHeaderSize = 8; | |
27 var kStructHeaderSize = 8; | |
28 var kMessageHeaderSize = 16; | |
29 var kMessageWithRequestIDHeaderSize = 24; | |
30 var kMapStructPayloadSize = 16; | |
31 | |
32 var kStructHeaderNumBytesOffset = 0; | |
33 var kStructHeaderNumFieldsOffset = 4; | |
34 | |
35 var kEncodedInvalidHandleValue = 0xFFFFFFFF; | |
36 | |
37 // Decoder ------------------------------------------------------------------ | |
38 | |
39 function Decoder(buffer, handles, base) { | |
40 this.buffer = buffer; | |
41 this.handles = handles; | |
42 this.base = base; | |
43 this.next = base; | |
44 } | |
45 | |
46 Decoder.prototype.skip = function(offset) { | |
47 this.next += offset; | |
48 }; | |
49 | |
50 Decoder.prototype.readInt8 = function() { | |
51 var result = this.buffer.getInt8(this.next); | |
52 this.next += 1; | |
53 return result; | |
54 }; | |
55 | |
56 Decoder.prototype.readUint8 = function() { | |
57 var result = this.buffer.getUint8(this.next); | |
58 this.next += 1; | |
59 return result; | |
60 }; | |
61 | |
62 Decoder.prototype.readInt16 = function() { | |
63 var result = this.buffer.getInt16(this.next); | |
64 this.next += 2; | |
65 return result; | |
66 }; | |
67 | |
68 Decoder.prototype.readUint16 = function() { | |
69 var result = this.buffer.getUint16(this.next); | |
70 this.next += 2; | |
71 return result; | |
72 }; | |
73 | |
74 Decoder.prototype.readInt32 = function() { | |
75 var result = this.buffer.getInt32(this.next); | |
76 this.next += 4; | |
77 return result; | |
78 }; | |
79 | |
80 Decoder.prototype.readUint32 = function() { | |
81 var result = this.buffer.getUint32(this.next); | |
82 this.next += 4; | |
83 return result; | |
84 }; | |
85 | |
86 Decoder.prototype.readInt64 = function() { | |
87 var result = this.buffer.getInt64(this.next); | |
88 this.next += 8; | |
89 return result; | |
90 }; | |
91 | |
92 Decoder.prototype.readUint64 = function() { | |
93 var result = this.buffer.getUint64(this.next); | |
94 this.next += 8; | |
95 return result; | |
96 }; | |
97 | |
98 Decoder.prototype.readFloat = function() { | |
99 var result = this.buffer.getFloat32(this.next); | |
100 this.next += 4; | |
101 return result; | |
102 }; | |
103 | |
104 Decoder.prototype.readDouble = function() { | |
105 var result = this.buffer.getFloat64(this.next); | |
106 this.next += 8; | |
107 return result; | |
108 }; | |
109 | |
110 Decoder.prototype.decodePointer = function() { | |
111 // TODO(abarth): To correctly decode a pointer, we need to know the real | |
112 // base address of the array buffer. | |
113 var offsetPointer = this.next; | |
114 var offset = this.readUint64(); | |
115 if (!offset) | |
116 return 0; | |
117 return offsetPointer + offset; | |
118 }; | |
119 | |
120 Decoder.prototype.decodeAndCreateDecoder = function(pointer) { | |
121 return new Decoder(this.buffer, this.handles, pointer); | |
122 }; | |
123 | |
124 Decoder.prototype.decodeHandle = function() { | |
125 return this.handles[this.readUint32()]; | |
126 }; | |
127 | |
128 Decoder.prototype.decodeString = function() { | |
129 var numberOfBytes = this.readUint32(); | |
130 var numberOfElements = this.readUint32(); | |
131 var base = this.next; | |
132 this.next += numberOfElements; | |
133 return unicode.decodeUtf8String( | |
134 new Uint8Array(this.buffer.arrayBuffer, base, numberOfElements)); | |
135 }; | |
136 | |
137 Decoder.prototype.decodeArray = function(cls) { | |
138 var numberOfBytes = this.readUint32(); | |
139 var numberOfElements = this.readUint32(); | |
140 var val = new Array(numberOfElements); | |
141 if (cls === PackedBool) { | |
142 var byte; | |
143 for (var i = 0; i < numberOfElements; ++i) { | |
144 if (i % 8 === 0) | |
145 byte = this.readUint8(); | |
146 val[i] = (byte & (1 << i % 8)) ? true : false; | |
147 } | |
148 } else { | |
149 for (var i = 0; i < numberOfElements; ++i) { | |
150 val[i] = cls.decode(this); | |
151 } | |
152 } | |
153 return val; | |
154 }; | |
155 | |
156 Decoder.prototype.decodeStruct = function(cls) { | |
157 return cls.decode(this); | |
158 }; | |
159 | |
160 Decoder.prototype.decodeStructPointer = function(cls) { | |
161 var pointer = this.decodePointer(); | |
162 if (!pointer) { | |
163 return null; | |
164 } | |
165 return cls.decode(this.decodeAndCreateDecoder(pointer)); | |
166 }; | |
167 | |
168 Decoder.prototype.decodeArrayPointer = function(cls) { | |
169 var pointer = this.decodePointer(); | |
170 if (!pointer) { | |
171 return null; | |
172 } | |
173 return this.decodeAndCreateDecoder(pointer).decodeArray(cls); | |
174 }; | |
175 | |
176 Decoder.prototype.decodeStringPointer = function() { | |
177 var pointer = this.decodePointer(); | |
178 if (!pointer) { | |
179 return null; | |
180 } | |
181 return this.decodeAndCreateDecoder(pointer).decodeString(); | |
182 }; | |
183 | |
184 Decoder.prototype.decodeMap = function(keyClass, valueClass) { | |
185 this.skip(4); // numberOfBytes | |
186 this.skip(4); // numberOfFields | |
187 var keys = this.decodeArrayPointer(keyClass); | |
188 var values = this.decodeArrayPointer(valueClass); | |
189 var val = new Map(); | |
190 for (var i = 0; i < keys.length; i++) | |
191 val.set(keys[i], values[i]); | |
192 return val; | |
193 }; | |
194 | |
195 Decoder.prototype.decodeMapPointer = function(keyClass, valueClass) { | |
196 var pointer = this.decodePointer(); | |
197 if (!pointer) { | |
198 return null; | |
199 } | |
200 var decoder = this.decodeAndCreateDecoder(pointer); | |
201 return decoder.decodeMap(keyClass, valueClass); | |
202 }; | |
203 | |
204 // Encoder ------------------------------------------------------------------ | |
205 | |
206 function Encoder(buffer, handles, base) { | |
207 this.buffer = buffer; | |
208 this.handles = handles; | |
209 this.base = base; | |
210 this.next = base; | |
211 } | |
212 | |
213 Encoder.prototype.skip = function(offset) { | |
214 this.next += offset; | |
215 }; | |
216 | |
217 Encoder.prototype.writeInt8 = function(val) { | |
218 this.buffer.setInt8(this.next, val); | |
219 this.next += 1; | |
220 }; | |
221 | |
222 Encoder.prototype.writeUint8 = function(val) { | |
223 if (val < 0) { | |
224 throw new Error(kErrorUnsigned); | |
225 } | |
226 this.buffer.setUint8(this.next, val); | |
227 this.next += 1; | |
228 }; | |
229 | |
230 Encoder.prototype.writeInt16 = function(val) { | |
231 this.buffer.setInt16(this.next, val); | |
232 this.next += 2; | |
233 }; | |
234 | |
235 Encoder.prototype.writeUint16 = function(val) { | |
236 if (val < 0) { | |
237 throw new Error(kErrorUnsigned); | |
238 } | |
239 this.buffer.setUint16(this.next, val); | |
240 this.next += 2; | |
241 }; | |
242 | |
243 Encoder.prototype.writeInt32 = function(val) { | |
244 this.buffer.setInt32(this.next, val); | |
245 this.next += 4; | |
246 }; | |
247 | |
248 Encoder.prototype.writeUint32 = function(val) { | |
249 if (val < 0) { | |
250 throw new Error(kErrorUnsigned); | |
251 } | |
252 this.buffer.setUint32(this.next, val); | |
253 this.next += 4; | |
254 }; | |
255 | |
256 Encoder.prototype.writeInt64 = function(val) { | |
257 this.buffer.setInt64(this.next, val); | |
258 this.next += 8; | |
259 }; | |
260 | |
261 Encoder.prototype.writeUint64 = function(val) { | |
262 if (val < 0) { | |
263 throw new Error(kErrorUnsigned); | |
264 } | |
265 this.buffer.setUint64(this.next, val); | |
266 this.next += 8; | |
267 }; | |
268 | |
269 Encoder.prototype.writeFloat = function(val) { | |
270 this.buffer.setFloat32(this.next, val); | |
271 this.next += 4; | |
272 }; | |
273 | |
274 Encoder.prototype.writeDouble = function(val) { | |
275 this.buffer.setFloat64(this.next, val); | |
276 this.next += 8; | |
277 }; | |
278 | |
279 Encoder.prototype.encodePointer = function(pointer) { | |
280 if (!pointer) | |
281 return this.writeUint64(0); | |
282 // TODO(abarth): To correctly encode a pointer, we need to know the real | |
283 // base address of the array buffer. | |
284 var offset = pointer - this.next; | |
285 this.writeUint64(offset); | |
286 }; | |
287 | |
288 Encoder.prototype.createAndEncodeEncoder = function(size) { | |
289 var pointer = this.buffer.alloc(align(size)); | |
290 this.encodePointer(pointer); | |
291 return new Encoder(this.buffer, this.handles, pointer); | |
292 }; | |
293 | |
294 Encoder.prototype.encodeHandle = function(handle) { | |
295 this.handles.push(handle); | |
296 this.writeUint32(this.handles.length - 1); | |
297 }; | |
298 | |
299 Encoder.prototype.encodeString = function(val) { | |
300 var base = this.next + kArrayHeaderSize; | |
301 var numberOfElements = unicode.encodeUtf8String( | |
302 val, new Uint8Array(this.buffer.arrayBuffer, base)); | |
303 var numberOfBytes = kArrayHeaderSize + numberOfElements; | |
304 this.writeUint32(numberOfBytes); | |
305 this.writeUint32(numberOfElements); | |
306 this.next += numberOfElements; | |
307 }; | |
308 | |
309 Encoder.prototype.encodeArray = | |
310 function(cls, val, numberOfElements, encodedSize) { | |
311 if (numberOfElements === undefined) | |
312 numberOfElements = val.length; | |
313 if (encodedSize === undefined) | |
314 encodedSize = kArrayHeaderSize + cls.encodedSize * numberOfElements; | |
315 | |
316 this.writeUint32(encodedSize); | |
317 this.writeUint32(numberOfElements); | |
318 | |
319 if (cls === PackedBool) { | |
320 var byte = 0; | |
321 for (i = 0; i < numberOfElements; ++i) { | |
322 if (val[i]) | |
323 byte |= (1 << i % 8); | |
324 if (i % 8 === 7 || i == numberOfElements - 1) { | |
325 Uint8.encode(this, byte); | |
326 byte = 0; | |
327 } | |
328 } | |
329 } else { | |
330 for (var i = 0; i < numberOfElements; ++i) | |
331 cls.encode(this, val[i]); | |
332 } | |
333 }; | |
334 | |
335 Encoder.prototype.encodeStruct = function(cls, val) { | |
336 return cls.encode(this, val); | |
337 }; | |
338 | |
339 Encoder.prototype.encodeStructPointer = function(cls, val) { | |
340 if (val == null) { | |
341 // Also handles undefined, since undefined == null. | |
342 this.encodePointer(val); | |
343 return; | |
344 } | |
345 var encoder = this.createAndEncodeEncoder(cls.encodedSize); | |
346 cls.encode(encoder, val); | |
347 }; | |
348 | |
349 Encoder.prototype.encodeArrayPointer = function(cls, val) { | |
350 if (val == null) { | |
351 // Also handles undefined, since undefined == null. | |
352 this.encodePointer(val); | |
353 return; | |
354 } | |
355 var numberOfElements = val.length; | |
356 var encodedSize = kArrayHeaderSize + ((cls === PackedBool) ? | |
357 Math.ceil(numberOfElements / 8) : cls.encodedSize * numberOfElements); | |
358 var encoder = this.createAndEncodeEncoder(encodedSize); | |
359 encoder.encodeArray(cls, val, numberOfElements, encodedSize); | |
360 }; | |
361 | |
362 Encoder.prototype.encodeStringPointer = function(val) { | |
363 if (val == null) { | |
364 // Also handles undefined, since undefined == null. | |
365 this.encodePointer(val); | |
366 return; | |
367 } | |
368 var encodedSize = kArrayHeaderSize + unicode.utf8Length(val); | |
369 var encoder = this.createAndEncodeEncoder(encodedSize); | |
370 encoder.encodeString(val); | |
371 }; | |
372 | |
373 Encoder.prototype.encodeMap = function(keyClass, valueClass, val) { | |
374 var keys = new Array(val.size); | |
375 var values = new Array(val.size); | |
376 var i = 0; | |
377 val.forEach(function(value, key) { | |
378 values[i] = value; | |
379 keys[i++] = key; | |
380 }); | |
381 this.writeUint32(kStructHeaderSize + kMapStructPayloadSize); | |
382 this.writeUint32(2); // two fields: keys, values | |
383 this.encodeArrayPointer(keyClass, keys); | |
384 this.encodeArrayPointer(valueClass, values); | |
385 } | |
386 | |
387 Encoder.prototype.encodeMapPointer = function(keyClass, valueClass, val) { | |
388 if (val == null) { | |
389 // Also handles undefined, since undefined == null. | |
390 this.encodePointer(val); | |
391 return; | |
392 } | |
393 var encodedSize = kStructHeaderSize + kMapStructPayloadSize; | |
394 var encoder = this.createAndEncodeEncoder(encodedSize); | |
395 encoder.encodeMap(keyClass, valueClass, val); | |
396 }; | |
397 | |
398 // Message ------------------------------------------------------------------ | |
399 | |
400 var kMessageNameOffset = kStructHeaderSize; | |
401 var kMessageFlagsOffset = kMessageNameOffset + 4; | |
402 var kMessageRequestIDOffset = kMessageFlagsOffset + 4; | |
403 | |
404 var kMessageExpectsResponse = 1 << 0; | |
405 var kMessageIsResponse = 1 << 1; | |
406 | |
407 function Message(buffer, handles) { | |
408 this.buffer = buffer; | |
409 this.handles = handles; | |
410 } | |
411 | |
412 Message.prototype.getHeaderNumBytes = function() { | |
413 return this.buffer.getUint32(kStructHeaderNumBytesOffset); | |
414 }; | |
415 | |
416 Message.prototype.getHeaderNumFields = function() { | |
417 return this.buffer.getUint32(kStructHeaderNumFieldsOffset); | |
418 }; | |
419 | |
420 Message.prototype.getName = function() { | |
421 return this.buffer.getUint32(kMessageNameOffset); | |
422 }; | |
423 | |
424 Message.prototype.getFlags = function() { | |
425 return this.buffer.getUint32(kMessageFlagsOffset); | |
426 }; | |
427 | |
428 Message.prototype.isResponse = function() { | |
429 return (this.getFlags() & kMessageIsResponse) != 0; | |
430 }; | |
431 | |
432 Message.prototype.expectsResponse = function() { | |
433 return (this.getFlags() & kMessageExpectsResponse) != 0; | |
434 }; | |
435 | |
436 Message.prototype.setRequestID = function(requestID) { | |
437 // TODO(darin): Verify that space was reserved for this field! | |
438 this.buffer.setUint64(kMessageRequestIDOffset, requestID); | |
439 }; | |
440 | |
441 | |
442 // MessageBuilder ----------------------------------------------------------- | |
443 | |
444 function MessageBuilder(messageName, payloadSize) { | |
445 // Currently, we don't compute the payload size correctly ahead of time. | |
446 // Instead, we resize the buffer at the end. | |
447 var numberOfBytes = kMessageHeaderSize + payloadSize; | |
448 this.buffer = new buffer.Buffer(numberOfBytes); | |
449 this.handles = []; | |
450 var encoder = this.createEncoder(kMessageHeaderSize); | |
451 encoder.writeUint32(kMessageHeaderSize); | |
452 encoder.writeUint32(2); // num_fields. | |
453 encoder.writeUint32(messageName); | |
454 encoder.writeUint32(0); // flags. | |
455 } | |
456 | |
457 MessageBuilder.prototype.createEncoder = function(size) { | |
458 var pointer = this.buffer.alloc(size); | |
459 return new Encoder(this.buffer, this.handles, pointer); | |
460 }; | |
461 | |
462 MessageBuilder.prototype.encodeStruct = function(cls, val) { | |
463 cls.encode(this.createEncoder(cls.encodedSize), val); | |
464 }; | |
465 | |
466 MessageBuilder.prototype.finish = function() { | |
467 // TODO(abarth): Rather than resizing the buffer at the end, we could | |
468 // compute the size we need ahead of time, like we do in C++. | |
469 this.buffer.trim(); | |
470 var message = new Message(this.buffer, this.handles); | |
471 this.buffer = null; | |
472 this.handles = null; | |
473 this.encoder = null; | |
474 return message; | |
475 }; | |
476 | |
477 // MessageWithRequestIDBuilder ----------------------------------------------- | |
478 | |
479 function MessageWithRequestIDBuilder(messageName, payloadSize, flags, | |
480 requestID) { | |
481 // Currently, we don't compute the payload size correctly ahead of time. | |
482 // Instead, we resize the buffer at the end. | |
483 var numberOfBytes = kMessageWithRequestIDHeaderSize + payloadSize; | |
484 this.buffer = new buffer.Buffer(numberOfBytes); | |
485 this.handles = []; | |
486 var encoder = this.createEncoder(kMessageWithRequestIDHeaderSize); | |
487 encoder.writeUint32(kMessageWithRequestIDHeaderSize); | |
488 encoder.writeUint32(3); // num_fields. | |
489 encoder.writeUint32(messageName); | |
490 encoder.writeUint32(flags); | |
491 encoder.writeUint64(requestID); | |
492 } | |
493 | |
494 MessageWithRequestIDBuilder.prototype = | |
495 Object.create(MessageBuilder.prototype); | |
496 | |
497 MessageWithRequestIDBuilder.prototype.constructor = | |
498 MessageWithRequestIDBuilder; | |
499 | |
500 // MessageReader ------------------------------------------------------------ | |
501 | |
502 function MessageReader(message) { | |
503 this.decoder = new Decoder(message.buffer, message.handles, 0); | |
504 var messageHeaderSize = this.decoder.readUint32(); | |
505 this.payloadSize = message.buffer.byteLength - messageHeaderSize; | |
506 var numFields = this.decoder.readUint32(); | |
507 this.messageName = this.decoder.readUint32(); | |
508 this.flags = this.decoder.readUint32(); | |
509 if (numFields >= 3) | |
510 this.requestID = this.decoder.readUint64(); | |
511 this.decoder.skip(messageHeaderSize - this.decoder.next); | |
512 } | |
513 | |
514 MessageReader.prototype.decodeStruct = function(cls) { | |
515 return cls.decode(this.decoder); | |
516 }; | |
517 | |
518 // Built-in types ----------------------------------------------------------- | |
519 | |
520 // This type is only used with ArrayOf(PackedBool). | |
521 function PackedBool() { | |
522 } | |
523 | |
524 function Int8() { | |
525 } | |
526 | |
527 Int8.encodedSize = 1; | |
528 | |
529 Int8.decode = function(decoder) { | |
530 return decoder.readInt8(); | |
531 }; | |
532 | |
533 Int8.encode = function(encoder, val) { | |
534 encoder.writeInt8(val); | |
535 }; | |
536 | |
537 Uint8.encode = function(encoder, val) { | |
538 encoder.writeUint8(val); | |
539 }; | |
540 | |
541 function Uint8() { | |
542 } | |
543 | |
544 Uint8.encodedSize = 1; | |
545 | |
546 Uint8.decode = function(decoder) { | |
547 return decoder.readUint8(); | |
548 }; | |
549 | |
550 Uint8.encode = function(encoder, val) { | |
551 encoder.writeUint8(val); | |
552 }; | |
553 | |
554 function Int16() { | |
555 } | |
556 | |
557 Int16.encodedSize = 2; | |
558 | |
559 Int16.decode = function(decoder) { | |
560 return decoder.readInt16(); | |
561 }; | |
562 | |
563 Int16.encode = function(encoder, val) { | |
564 encoder.writeInt16(val); | |
565 }; | |
566 | |
567 function Uint16() { | |
568 } | |
569 | |
570 Uint16.encodedSize = 2; | |
571 | |
572 Uint16.decode = function(decoder) { | |
573 return decoder.readUint16(); | |
574 }; | |
575 | |
576 Uint16.encode = function(encoder, val) { | |
577 encoder.writeUint16(val); | |
578 }; | |
579 | |
580 function Int32() { | |
581 } | |
582 | |
583 Int32.encodedSize = 4; | |
584 | |
585 Int32.decode = function(decoder) { | |
586 return decoder.readInt32(); | |
587 }; | |
588 | |
589 Int32.encode = function(encoder, val) { | |
590 encoder.writeInt32(val); | |
591 }; | |
592 | |
593 function Uint32() { | |
594 } | |
595 | |
596 Uint32.encodedSize = 4; | |
597 | |
598 Uint32.decode = function(decoder) { | |
599 return decoder.readUint32(); | |
600 }; | |
601 | |
602 Uint32.encode = function(encoder, val) { | |
603 encoder.writeUint32(val); | |
604 }; | |
605 | |
606 function Int64() { | |
607 } | |
608 | |
609 Int64.encodedSize = 8; | |
610 | |
611 Int64.decode = function(decoder) { | |
612 return decoder.readInt64(); | |
613 }; | |
614 | |
615 Int64.encode = function(encoder, val) { | |
616 encoder.writeInt64(val); | |
617 }; | |
618 | |
619 function Uint64() { | |
620 } | |
621 | |
622 Uint64.encodedSize = 8; | |
623 | |
624 Uint64.decode = function(decoder) { | |
625 return decoder.readUint64(); | |
626 }; | |
627 | |
628 Uint64.encode = function(encoder, val) { | |
629 encoder.writeUint64(val); | |
630 }; | |
631 | |
632 function String() { | |
633 }; | |
634 | |
635 String.encodedSize = 8; | |
636 | |
637 String.decode = function(decoder) { | |
638 return decoder.decodeStringPointer(); | |
639 }; | |
640 | |
641 String.encode = function(encoder, val) { | |
642 encoder.encodeStringPointer(val); | |
643 }; | |
644 | |
645 function NullableString() { | |
646 } | |
647 | |
648 NullableString.encodedSize = String.encodedSize; | |
649 | |
650 NullableString.decode = String.decode; | |
651 | |
652 NullableString.encode = String.encode; | |
653 | |
654 function Float() { | |
655 } | |
656 | |
657 Float.encodedSize = 4; | |
658 | |
659 Float.decode = function(decoder) { | |
660 return decoder.readFloat(); | |
661 }; | |
662 | |
663 Float.encode = function(encoder, val) { | |
664 encoder.writeFloat(val); | |
665 }; | |
666 | |
667 function Double() { | |
668 } | |
669 | |
670 Double.encodedSize = 8; | |
671 | |
672 Double.decode = function(decoder) { | |
673 return decoder.readDouble(); | |
674 }; | |
675 | |
676 Double.encode = function(encoder, val) { | |
677 encoder.writeDouble(val); | |
678 }; | |
679 | |
680 function PointerTo(cls) { | |
681 this.cls = cls; | |
682 } | |
683 | |
684 PointerTo.prototype.encodedSize = 8; | |
685 | |
686 PointerTo.prototype.decode = function(decoder) { | |
687 var pointer = decoder.decodePointer(); | |
688 if (!pointer) { | |
689 return null; | |
690 } | |
691 return this.cls.decode(decoder.decodeAndCreateDecoder(pointer)); | |
692 }; | |
693 | |
694 PointerTo.prototype.encode = function(encoder, val) { | |
695 if (!val) { | |
696 encoder.encodePointer(val); | |
697 return; | |
698 } | |
699 var objectEncoder = encoder.createAndEncodeEncoder(this.cls.encodedSize); | |
700 this.cls.encode(objectEncoder, val); | |
701 }; | |
702 | |
703 function NullablePointerTo(cls) { | |
704 PointerTo.call(this, cls); | |
705 } | |
706 | |
707 NullablePointerTo.prototype = Object.create(PointerTo.prototype); | |
708 | |
709 function ArrayOf(cls, length) { | |
710 this.cls = cls; | |
711 this.length = length || 0; | |
712 } | |
713 | |
714 ArrayOf.prototype.encodedSize = 8; | |
715 | |
716 ArrayOf.prototype.dimensions = function() { | |
717 return [this.length].concat( | |
718 (this.cls instanceof ArrayOf) ? this.cls.dimensions() : []); | |
719 } | |
720 | |
721 ArrayOf.prototype.decode = function(decoder) { | |
722 return decoder.decodeArrayPointer(this.cls); | |
723 }; | |
724 | |
725 ArrayOf.prototype.encode = function(encoder, val) { | |
726 encoder.encodeArrayPointer(this.cls, val); | |
727 }; | |
728 | |
729 function NullableArrayOf(cls) { | |
730 ArrayOf.call(this, cls); | |
731 } | |
732 | |
733 NullableArrayOf.prototype = Object.create(ArrayOf.prototype); | |
734 | |
735 function Handle() { | |
736 } | |
737 | |
738 Handle.encodedSize = 4; | |
739 | |
740 Handle.decode = function(decoder) { | |
741 return decoder.decodeHandle(); | |
742 }; | |
743 | |
744 Handle.encode = function(encoder, val) { | |
745 encoder.encodeHandle(val); | |
746 }; | |
747 | |
748 function NullableHandle() { | |
749 } | |
750 | |
751 NullableHandle.encodedSize = Handle.encodedSize; | |
752 | |
753 NullableHandle.decode = Handle.decode; | |
754 | |
755 NullableHandle.encode = Handle.encode; | |
756 | |
757 var exports = {}; | |
758 exports.align = align; | |
759 exports.isAligned = isAligned; | |
760 exports.Message = Message; | |
761 exports.MessageBuilder = MessageBuilder; | |
762 exports.MessageWithRequestIDBuilder = MessageWithRequestIDBuilder; | |
763 exports.MessageReader = MessageReader; | |
764 exports.kArrayHeaderSize = kArrayHeaderSize; | |
765 exports.kMapStructPayloadSize = kMapStructPayloadSize; | |
766 exports.kStructHeaderSize = kStructHeaderSize; | |
767 exports.kEncodedInvalidHandleValue = kEncodedInvalidHandleValue; | |
768 exports.kMessageHeaderSize = kMessageHeaderSize; | |
769 exports.kMessageWithRequestIDHeaderSize = kMessageWithRequestIDHeaderSize; | |
770 exports.kMessageExpectsResponse = kMessageExpectsResponse; | |
771 exports.kMessageIsResponse = kMessageIsResponse; | |
772 exports.Int8 = Int8; | |
773 exports.Uint8 = Uint8; | |
774 exports.Int16 = Int16; | |
775 exports.Uint16 = Uint16; | |
776 exports.Int32 = Int32; | |
777 exports.Uint32 = Uint32; | |
778 exports.Int64 = Int64; | |
779 exports.Uint64 = Uint64; | |
780 exports.Float = Float; | |
781 exports.Double = Double; | |
782 exports.String = String; | |
783 exports.NullableString = NullableString; | |
784 exports.PointerTo = PointerTo; | |
785 exports.NullablePointerTo = NullablePointerTo; | |
786 exports.ArrayOf = ArrayOf; | |
787 exports.NullableArrayOf = NullableArrayOf; | |
788 exports.PackedBool = PackedBool; | |
789 exports.Handle = Handle; | |
790 exports.NullableHandle = NullableHandle; | |
791 return exports; | |
792 }); | |
OLD | NEW |