• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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(function() {
6  var internal = mojo.internal;
7
8  var kErrorUnsigned = "Passing negative value to unsigned";
9  var kErrorArray = "Passing non Array for array type";
10  var kErrorString = "Passing non String for string type";
11  var kErrorMap = "Passing non Map for map type";
12
13  // Memory -------------------------------------------------------------------
14
15  var kAlignment = 8;
16
17  function align(size) {
18    return size + (kAlignment - (size % kAlignment)) % kAlignment;
19  }
20
21  function isAligned(offset) {
22    return offset >= 0 && (offset % kAlignment) === 0;
23  }
24
25  // Constants ----------------------------------------------------------------
26
27  var kArrayHeaderSize = 8;
28  var kStructHeaderSize = 8;
29  var kMessageV0HeaderSize = 24;
30  var kMessageV1HeaderSize = 32;
31  var kMessageV2HeaderSize = 48;
32  var kMapStructPayloadSize = 16;
33
34  var kStructHeaderNumBytesOffset = 0;
35  var kStructHeaderVersionOffset = 4;
36
37  var kEncodedInvalidHandleValue = 0xFFFFFFFF;
38
39  // Decoder ------------------------------------------------------------------
40
41  function Decoder(buffer, handles, associatedEndpointHandles, base) {
42    this.buffer = buffer;
43    this.handles = handles;
44    this.associatedEndpointHandles = associatedEndpointHandles;
45    this.base = base;
46    this.next = base;
47  }
48
49  Decoder.prototype.align = function() {
50    this.next = align(this.next);
51  };
52
53  Decoder.prototype.skip = function(offset) {
54    this.next += offset;
55  };
56
57  Decoder.prototype.readInt8 = function() {
58    var result = this.buffer.getInt8(this.next);
59    this.next += 1;
60    return result;
61  };
62
63  Decoder.prototype.readUint8 = function() {
64    var result = this.buffer.getUint8(this.next);
65    this.next += 1;
66    return result;
67  };
68
69  Decoder.prototype.readInt16 = function() {
70    var result = this.buffer.getInt16(this.next);
71    this.next += 2;
72    return result;
73  };
74
75  Decoder.prototype.readUint16 = function() {
76    var result = this.buffer.getUint16(this.next);
77    this.next += 2;
78    return result;
79  };
80
81  Decoder.prototype.readInt32 = function() {
82    var result = this.buffer.getInt32(this.next);
83    this.next += 4;
84    return result;
85  };
86
87  Decoder.prototype.readUint32 = function() {
88    var result = this.buffer.getUint32(this.next);
89    this.next += 4;
90    return result;
91  };
92
93  Decoder.prototype.readInt64 = function() {
94    var result = this.buffer.getInt64(this.next);
95    this.next += 8;
96    return result;
97  };
98
99  Decoder.prototype.readUint64 = function() {
100    var result = this.buffer.getUint64(this.next);
101    this.next += 8;
102    return result;
103  };
104
105  Decoder.prototype.readFloat = function() {
106    var result = this.buffer.getFloat32(this.next);
107    this.next += 4;
108    return result;
109  };
110
111  Decoder.prototype.readDouble = function() {
112    var result = this.buffer.getFloat64(this.next);
113    this.next += 8;
114    return result;
115  };
116
117  Decoder.prototype.decodePointer = function() {
118    // TODO(abarth): To correctly decode a pointer, we need to know the real
119    // base address of the array buffer.
120    var offsetPointer = this.next;
121    var offset = this.readUint64();
122    if (!offset)
123      return 0;
124    return offsetPointer + offset;
125  };
126
127  Decoder.prototype.decodeAndCreateDecoder = function(pointer) {
128    return new Decoder(this.buffer, this.handles,
129        this.associatedEndpointHandles, pointer);
130  };
131
132  Decoder.prototype.decodeHandle = function() {
133    return this.handles[this.readUint32()] || null;
134  };
135
136  Decoder.prototype.decodeAssociatedEndpointHandle = function() {
137    return this.associatedEndpointHandles[this.readUint32()] || null;
138  };
139
140  Decoder.prototype.decodeString = function() {
141    var numberOfBytes = this.readUint32();
142    var numberOfElements = this.readUint32();
143    var base = this.next;
144    this.next += numberOfElements;
145    return internal.decodeUtf8String(
146        new Uint8Array(this.buffer.arrayBuffer, base, numberOfElements));
147  };
148
149  Decoder.prototype.decodeArray = function(cls) {
150    var numberOfBytes = this.readUint32();
151    var numberOfElements = this.readUint32();
152    var val = new Array(numberOfElements);
153    if (cls === PackedBool) {
154      var byte;
155      for (var i = 0; i < numberOfElements; ++i) {
156        if (i % 8 === 0)
157          byte = this.readUint8();
158        val[i] = (byte & (1 << i % 8)) ? true : false;
159      }
160    } else {
161      for (var i = 0; i < numberOfElements; ++i) {
162        val[i] = cls.decode(this);
163      }
164    }
165    return val;
166  };
167
168  Decoder.prototype.decodeStruct = function(cls) {
169    return cls.decode(this);
170  };
171
172  Decoder.prototype.decodeStructPointer = function(cls) {
173    var pointer = this.decodePointer();
174    if (!pointer) {
175      return null;
176    }
177    return cls.decode(this.decodeAndCreateDecoder(pointer));
178  };
179
180  Decoder.prototype.decodeArrayPointer = function(cls) {
181    var pointer = this.decodePointer();
182    if (!pointer) {
183      return null;
184    }
185    return this.decodeAndCreateDecoder(pointer).decodeArray(cls);
186  };
187
188  Decoder.prototype.decodeStringPointer = function() {
189    var pointer = this.decodePointer();
190    if (!pointer) {
191      return null;
192    }
193    return this.decodeAndCreateDecoder(pointer).decodeString();
194  };
195
196  Decoder.prototype.decodeMap = function(keyClass, valueClass) {
197    this.skip(4); // numberOfBytes
198    this.skip(4); // version
199    var keys = this.decodeArrayPointer(keyClass);
200    var values = this.decodeArrayPointer(valueClass);
201    var val = new Map();
202    for (var i = 0; i < keys.length; i++)
203      val.set(keys[i], values[i]);
204    return val;
205  };
206
207  Decoder.prototype.decodeMapPointer = function(keyClass, valueClass) {
208    var pointer = this.decodePointer();
209    if (!pointer) {
210      return null;
211    }
212    var decoder = this.decodeAndCreateDecoder(pointer);
213    return decoder.decodeMap(keyClass, valueClass);
214  };
215
216  // Encoder ------------------------------------------------------------------
217
218  function Encoder(buffer, handles, associatedEndpointHandles, base) {
219    this.buffer = buffer;
220    this.handles = handles;
221    this.associatedEndpointHandles = associatedEndpointHandles;
222    this.base = base;
223    this.next = base;
224  }
225
226  Encoder.prototype.align = function() {
227    this.next = align(this.next);
228  };
229
230  Encoder.prototype.skip = function(offset) {
231    this.next += offset;
232  };
233
234  Encoder.prototype.writeInt8 = function(val) {
235    this.buffer.setInt8(this.next, val);
236    this.next += 1;
237  };
238
239  Encoder.prototype.writeUint8 = function(val) {
240    if (val < 0) {
241      throw new Error(kErrorUnsigned);
242    }
243    this.buffer.setUint8(this.next, val);
244    this.next += 1;
245  };
246
247  Encoder.prototype.writeInt16 = function(val) {
248    this.buffer.setInt16(this.next, val);
249    this.next += 2;
250  };
251
252  Encoder.prototype.writeUint16 = function(val) {
253    if (val < 0) {
254      throw new Error(kErrorUnsigned);
255    }
256    this.buffer.setUint16(this.next, val);
257    this.next += 2;
258  };
259
260  Encoder.prototype.writeInt32 = function(val) {
261    this.buffer.setInt32(this.next, val);
262    this.next += 4;
263  };
264
265  Encoder.prototype.writeUint32 = function(val) {
266    if (val < 0) {
267      throw new Error(kErrorUnsigned);
268    }
269    this.buffer.setUint32(this.next, val);
270    this.next += 4;
271  };
272
273  Encoder.prototype.writeInt64 = function(val) {
274    this.buffer.setInt64(this.next, val);
275    this.next += 8;
276  };
277
278  Encoder.prototype.writeUint64 = function(val) {
279    if (val < 0) {
280      throw new Error(kErrorUnsigned);
281    }
282    this.buffer.setUint64(this.next, val);
283    this.next += 8;
284  };
285
286  Encoder.prototype.writeFloat = function(val) {
287    this.buffer.setFloat32(this.next, val);
288    this.next += 4;
289  };
290
291  Encoder.prototype.writeDouble = function(val) {
292    this.buffer.setFloat64(this.next, val);
293    this.next += 8;
294  };
295
296  Encoder.prototype.encodePointer = function(pointer) {
297    if (!pointer)
298      return this.writeUint64(0);
299    // TODO(abarth): To correctly encode a pointer, we need to know the real
300    // base address of the array buffer.
301    var offset = pointer - this.next;
302    this.writeUint64(offset);
303  };
304
305  Encoder.prototype.createAndEncodeEncoder = function(size) {
306    var pointer = this.buffer.alloc(align(size));
307    this.encodePointer(pointer);
308    return new Encoder(this.buffer, this.handles,
309        this.associatedEndpointHandles, pointer);
310  };
311
312  Encoder.prototype.encodeHandle = function(handle) {
313    if (handle) {
314      this.handles.push(handle);
315      this.writeUint32(this.handles.length - 1);
316    } else {
317      this.writeUint32(kEncodedInvalidHandleValue);
318    }
319  };
320
321  Encoder.prototype.encodeAssociatedEndpointHandle = function(endpointHandle) {
322    if (endpointHandle) {
323      this.associatedEndpointHandles.push(endpointHandle);
324      this.writeUint32(this.associatedEndpointHandles.length - 1);
325    } else {
326      this.writeUint32(kEncodedInvalidHandleValue);
327    }
328  };
329
330  Encoder.prototype.encodeString = function(val) {
331    var base = this.next + kArrayHeaderSize;
332    var numberOfElements = internal.encodeUtf8String(
333        val, new Uint8Array(this.buffer.arrayBuffer, base));
334    var numberOfBytes = kArrayHeaderSize + numberOfElements;
335    this.writeUint32(numberOfBytes);
336    this.writeUint32(numberOfElements);
337    this.next += numberOfElements;
338  };
339
340  Encoder.prototype.encodeArray =
341      function(cls, val, numberOfElements, encodedSize) {
342    if (numberOfElements === undefined)
343      numberOfElements = val.length;
344    if (encodedSize === undefined)
345      encodedSize = kArrayHeaderSize + cls.encodedSize * numberOfElements;
346
347    this.writeUint32(encodedSize);
348    this.writeUint32(numberOfElements);
349
350    if (cls === PackedBool) {
351      var byte = 0;
352      for (i = 0; i < numberOfElements; ++i) {
353        if (val[i])
354          byte |= (1 << i % 8);
355        if (i % 8 === 7 || i == numberOfElements - 1) {
356          Uint8.encode(this, byte);
357          byte = 0;
358        }
359      }
360    } else {
361      for (var i = 0; i < numberOfElements; ++i)
362        cls.encode(this, val[i]);
363    }
364  };
365
366  Encoder.prototype.encodeStruct = function(cls, val) {
367    return cls.encode(this, val);
368  };
369
370  Encoder.prototype.encodeStructPointer = function(cls, val) {
371    if (val == null) {
372      // Also handles undefined, since undefined == null.
373      this.encodePointer(val);
374      return;
375    }
376    var encoder = this.createAndEncodeEncoder(cls.encodedSize);
377    cls.encode(encoder, val);
378  };
379
380  Encoder.prototype.encodeArrayPointer = function(cls, val) {
381    if (val == null) {
382      // Also handles undefined, since undefined == null.
383      this.encodePointer(val);
384      return;
385    }
386
387    var numberOfElements = val.length;
388    if (!Number.isSafeInteger(numberOfElements) || numberOfElements < 0)
389      throw new Error(kErrorArray);
390
391    var encodedSize = kArrayHeaderSize + ((cls === PackedBool) ?
392        Math.ceil(numberOfElements / 8) : cls.encodedSize * numberOfElements);
393    var encoder = this.createAndEncodeEncoder(encodedSize);
394    encoder.encodeArray(cls, val, numberOfElements, encodedSize);
395  };
396
397  Encoder.prototype.encodeStringPointer = function(val) {
398    if (val == null) {
399      // Also handles undefined, since undefined == null.
400      this.encodePointer(val);
401      return;
402    }
403    // Only accepts string primivites, not String Objects like new String("foo")
404    if (typeof(val) !== "string") {
405      throw new Error(kErrorString);
406    }
407    var encodedSize = kArrayHeaderSize + internal.utf8Length(val);
408    var encoder = this.createAndEncodeEncoder(encodedSize);
409    encoder.encodeString(val);
410  };
411
412  Encoder.prototype.encodeMap = function(keyClass, valueClass, val) {
413    var keys = new Array(val.size);
414    var values = new Array(val.size);
415    var i = 0;
416    val.forEach(function(value, key) {
417      values[i] = value;
418      keys[i++] = key;
419    });
420    this.writeUint32(kStructHeaderSize + kMapStructPayloadSize);
421    this.writeUint32(0);  // version
422    this.encodeArrayPointer(keyClass, keys);
423    this.encodeArrayPointer(valueClass, values);
424  }
425
426  Encoder.prototype.encodeMapPointer = function(keyClass, valueClass, val) {
427    if (val == null) {
428      // Also handles undefined, since undefined == null.
429      this.encodePointer(val);
430      return;
431    }
432    if (!(val instanceof Map)) {
433      throw new Error(kErrorMap);
434    }
435    var encodedSize = kStructHeaderSize + kMapStructPayloadSize;
436    var encoder = this.createAndEncodeEncoder(encodedSize);
437    encoder.encodeMap(keyClass, valueClass, val);
438  };
439
440  // Message ------------------------------------------------------------------
441
442  var kMessageInterfaceIdOffset = kStructHeaderSize;
443  var kMessageNameOffset = kMessageInterfaceIdOffset + 4;
444  var kMessageFlagsOffset = kMessageNameOffset + 4;
445  var kMessageRequestIDOffset = kMessageFlagsOffset + 8;
446  var kMessagePayloadInterfaceIdsPointerOffset = kMessageV2HeaderSize - 8;
447
448  var kMessageExpectsResponse = 1 << 0;
449  var kMessageIsResponse      = 1 << 1;
450
451  function Message(buffer, handles, associatedEndpointHandles) {
452    if (associatedEndpointHandles === undefined) {
453      associatedEndpointHandles = [];
454    }
455
456    this.buffer = buffer;
457    this.handles = handles;
458    this.associatedEndpointHandles = associatedEndpointHandles;
459  }
460
461  Message.prototype.getHeaderNumBytes = function() {
462    return this.buffer.getUint32(kStructHeaderNumBytesOffset);
463  };
464
465  Message.prototype.getHeaderVersion = function() {
466    return this.buffer.getUint32(kStructHeaderVersionOffset);
467  };
468
469  Message.prototype.getName = function() {
470    return this.buffer.getUint32(kMessageNameOffset);
471  };
472
473  Message.prototype.getFlags = function() {
474    return this.buffer.getUint32(kMessageFlagsOffset);
475  };
476
477  Message.prototype.getInterfaceId = function() {
478    return this.buffer.getUint32(kMessageInterfaceIdOffset);
479  };
480
481  Message.prototype.getPayloadInterfaceIds = function() {
482    if (this.getHeaderVersion() < 2) {
483      return null;
484    }
485
486    var decoder = new Decoder(this.buffer, this.handles,
487        this.associatedEndpointHandles,
488        kMessagePayloadInterfaceIdsPointerOffset);
489    var payloadInterfaceIds = decoder.decodeArrayPointer(Uint32);
490    return payloadInterfaceIds;
491  };
492
493  Message.prototype.isResponse = function() {
494    return (this.getFlags() & kMessageIsResponse) != 0;
495  };
496
497  Message.prototype.expectsResponse = function() {
498    return (this.getFlags() & kMessageExpectsResponse) != 0;
499  };
500
501  Message.prototype.setRequestID = function(requestID) {
502    // TODO(darin): Verify that space was reserved for this field!
503    this.buffer.setUint64(kMessageRequestIDOffset, requestID);
504  };
505
506  Message.prototype.setInterfaceId = function(interfaceId) {
507    this.buffer.setUint32(kMessageInterfaceIdOffset, interfaceId);
508  };
509
510  Message.prototype.setPayloadInterfaceIds_ = function(payloadInterfaceIds) {
511    if (this.getHeaderVersion() < 2) {
512      throw new Error(
513          "Version of message does not support payload interface ids");
514    }
515
516    var decoder = new Decoder(this.buffer, this.handles,
517        this.associatedEndpointHandles,
518        kMessagePayloadInterfaceIdsPointerOffset);
519    var payloadInterfaceIdsOffset = decoder.decodePointer();
520    var encoder = new Encoder(this.buffer, this.handles,
521        this.associatedEndpointHandles,
522        payloadInterfaceIdsOffset);
523    encoder.encodeArray(Uint32, payloadInterfaceIds);
524  };
525
526  Message.prototype.serializeAssociatedEndpointHandles = function(
527      associatedGroupController) {
528    if (this.associatedEndpointHandles.length > 0) {
529      if (this.getHeaderVersion() < 2) {
530        throw new Error(
531            "Version of message does not support associated endpoint handles");
532      }
533
534      var data = [];
535      for (var i = 0; i < this.associatedEndpointHandles.length; i++) {
536        var handle = this.associatedEndpointHandles[i];
537        data.push(associatedGroupController.associateInterface(handle));
538      }
539      this.associatedEndpointHandles = [];
540      this.setPayloadInterfaceIds_(data);
541    }
542  };
543
544  Message.prototype.deserializeAssociatedEndpointHandles = function(
545      associatedGroupController) {
546    if (this.getHeaderVersion() < 2) {
547      return true;
548    }
549
550    this.associatedEndpointHandles = [];
551    var ids = this.getPayloadInterfaceIds();
552
553    var result = true;
554    for (var i = 0; i < ids.length; i++) {
555      var handle = associatedGroupController.createLocalEndpointHandle(ids[i]);
556      if (internal.isValidInterfaceId(ids[i]) && !handle.isValid()) {
557        // |ids[i]| itself is valid but handle creation failed. In that case,
558        // mark deserialization as failed but continue to deserialize the
559        // rest of handles.
560        result = false;
561      }
562      this.associatedEndpointHandles.push(handle);
563      ids[i] = internal.kInvalidInterfaceId;
564    }
565
566    this.setPayloadInterfaceIds_(ids);
567    return result;
568  };
569
570
571  // MessageV0Builder ---------------------------------------------------------
572
573  function MessageV0Builder(messageName, payloadSize) {
574    // Currently, we don't compute the payload size correctly ahead of time.
575    // Instead, we resize the buffer at the end.
576    var numberOfBytes = kMessageV0HeaderSize + payloadSize;
577    this.buffer = new internal.Buffer(numberOfBytes);
578    this.handles = [];
579    var encoder = this.createEncoder(kMessageV0HeaderSize);
580    encoder.writeUint32(kMessageV0HeaderSize);
581    encoder.writeUint32(0);  // version.
582    encoder.writeUint32(0);  // interface ID.
583    encoder.writeUint32(messageName);
584    encoder.writeUint32(0);  // flags.
585    encoder.writeUint32(0);  // padding.
586  }
587
588  MessageV0Builder.prototype.createEncoder = function(size) {
589    var pointer = this.buffer.alloc(size);
590    return new Encoder(this.buffer, this.handles, [], pointer);
591  };
592
593  MessageV0Builder.prototype.encodeStruct = function(cls, val) {
594    cls.encode(this.createEncoder(cls.encodedSize), val);
595  };
596
597  MessageV0Builder.prototype.finish = function() {
598    // TODO(abarth): Rather than resizing the buffer at the end, we could
599    // compute the size we need ahead of time, like we do in C++.
600    this.buffer.trim();
601    var message = new Message(this.buffer, this.handles);
602    this.buffer = null;
603    this.handles = null;
604    this.encoder = null;
605    return message;
606  };
607
608  // MessageV1Builder -----------------------------------------------
609
610  function MessageV1Builder(messageName, payloadSize, flags,
611                                       requestID) {
612    // Currently, we don't compute the payload size correctly ahead of time.
613    // Instead, we resize the buffer at the end.
614    var numberOfBytes = kMessageV1HeaderSize + payloadSize;
615    this.buffer = new internal.Buffer(numberOfBytes);
616    this.handles = [];
617    var encoder = this.createEncoder(kMessageV1HeaderSize);
618    encoder.writeUint32(kMessageV1HeaderSize);
619    encoder.writeUint32(1);  // version.
620    encoder.writeUint32(0);  // interface ID.
621    encoder.writeUint32(messageName);
622    encoder.writeUint32(flags);
623    encoder.writeUint32(0);  // padding.
624    encoder.writeUint64(requestID);
625  }
626
627  MessageV1Builder.prototype =
628      Object.create(MessageV0Builder.prototype);
629
630  MessageV1Builder.prototype.constructor =
631      MessageV1Builder;
632
633  // MessageV2 -----------------------------------------------
634
635  function MessageV2Builder(messageName, payloadSize, flags, requestID) {
636    // Currently, we don't compute the payload size correctly ahead of time.
637    // Instead, we resize the buffer at the end.
638    var numberOfBytes = kMessageV2HeaderSize + payloadSize;
639    this.buffer = new internal.Buffer(numberOfBytes);
640    this.handles = [];
641
642    this.payload = null;
643    this.associatedEndpointHandles = [];
644
645    this.encoder = this.createEncoder(kMessageV2HeaderSize);
646    this.encoder.writeUint32(kMessageV2HeaderSize);
647    this.encoder.writeUint32(2);  // version.
648    // Gets set to an appropriate interfaceId for the endpoint by the Router.
649    this.encoder.writeUint32(0);  // interface ID.
650    this.encoder.writeUint32(messageName);
651    this.encoder.writeUint32(flags);
652    this.encoder.writeUint32(0);  // padding.
653    this.encoder.writeUint64(requestID);
654  }
655
656  MessageV2Builder.prototype.createEncoder = function(size) {
657    var pointer = this.buffer.alloc(size);
658    return new Encoder(this.buffer, this.handles,
659        this.associatedEndpointHandles, pointer);
660  };
661
662  MessageV2Builder.prototype.setPayload = function(cls, val) {
663    this.payload = {cls: cls, val: val};
664  };
665
666  MessageV2Builder.prototype.finish = function() {
667    if (!this.payload) {
668      throw new Error("Payload needs to be set before calling finish");
669    }
670
671    this.encoder.encodeStructPointer(this.payload.cls, this.payload.val);
672    this.encoder.encodeArrayPointer(Uint32,
673        new Array(this.associatedEndpointHandles.length));
674
675    this.buffer.trim();
676    var message = new Message(this.buffer, this.handles,
677        this.associatedEndpointHandles);
678    this.buffer = null;
679    this.handles = null;
680    this.encoder = null;
681    this.payload = null;
682    this.associatedEndpointHandles = null;
683
684    return message;
685  };
686
687  // MessageReader ------------------------------------------------------------
688
689  function MessageReader(message) {
690    this.decoder = new Decoder(message.buffer, message.handles,
691        message.associatedEndpointHandles, 0);
692    var messageHeaderSize = this.decoder.readUint32();
693    this.payloadSize = message.buffer.byteLength - messageHeaderSize;
694    var version = this.decoder.readUint32();
695    var interface_id = this.decoder.readUint32();
696    this.messageName = this.decoder.readUint32();
697    this.flags = this.decoder.readUint32();
698    // Skip the padding.
699    this.decoder.skip(4);
700    if (version >= 1)
701      this.requestID = this.decoder.readUint64();
702    this.decoder.skip(messageHeaderSize - this.decoder.next);
703  }
704
705  MessageReader.prototype.decodeStruct = function(cls) {
706    return cls.decode(this.decoder);
707  };
708
709  // Built-in types -----------------------------------------------------------
710
711  // This type is only used with ArrayOf(PackedBool).
712  function PackedBool() {
713  }
714
715  function Int8() {
716  }
717
718  Int8.encodedSize = 1;
719
720  Int8.decode = function(decoder) {
721    return decoder.readInt8();
722  };
723
724  Int8.encode = function(encoder, val) {
725    encoder.writeInt8(val);
726  };
727
728  Uint8.encode = function(encoder, val) {
729    encoder.writeUint8(val);
730  };
731
732  function Uint8() {
733  }
734
735  Uint8.encodedSize = 1;
736
737  Uint8.decode = function(decoder) {
738    return decoder.readUint8();
739  };
740
741  Uint8.encode = function(encoder, val) {
742    encoder.writeUint8(val);
743  };
744
745  function Int16() {
746  }
747
748  Int16.encodedSize = 2;
749
750  Int16.decode = function(decoder) {
751    return decoder.readInt16();
752  };
753
754  Int16.encode = function(encoder, val) {
755    encoder.writeInt16(val);
756  };
757
758  function Uint16() {
759  }
760
761  Uint16.encodedSize = 2;
762
763  Uint16.decode = function(decoder) {
764    return decoder.readUint16();
765  };
766
767  Uint16.encode = function(encoder, val) {
768    encoder.writeUint16(val);
769  };
770
771  function Int32() {
772  }
773
774  Int32.encodedSize = 4;
775
776  Int32.decode = function(decoder) {
777    return decoder.readInt32();
778  };
779
780  Int32.encode = function(encoder, val) {
781    encoder.writeInt32(val);
782  };
783
784  function Uint32() {
785  }
786
787  Uint32.encodedSize = 4;
788
789  Uint32.decode = function(decoder) {
790    return decoder.readUint32();
791  };
792
793  Uint32.encode = function(encoder, val) {
794    encoder.writeUint32(val);
795  };
796
797  function Int64() {
798  }
799
800  Int64.encodedSize = 8;
801
802  Int64.decode = function(decoder) {
803    return decoder.readInt64();
804  };
805
806  Int64.encode = function(encoder, val) {
807    encoder.writeInt64(val);
808  };
809
810  function Uint64() {
811  }
812
813  Uint64.encodedSize = 8;
814
815  Uint64.decode = function(decoder) {
816    return decoder.readUint64();
817  };
818
819  Uint64.encode = function(encoder, val) {
820    encoder.writeUint64(val);
821  };
822
823  function String() {
824  };
825
826  String.encodedSize = 8;
827
828  String.decode = function(decoder) {
829    return decoder.decodeStringPointer();
830  };
831
832  String.encode = function(encoder, val) {
833    encoder.encodeStringPointer(val);
834  };
835
836  function NullableString() {
837  }
838
839  NullableString.encodedSize = String.encodedSize;
840
841  NullableString.decode = String.decode;
842
843  NullableString.encode = String.encode;
844
845  function Float() {
846  }
847
848  Float.encodedSize = 4;
849
850  Float.decode = function(decoder) {
851    return decoder.readFloat();
852  };
853
854  Float.encode = function(encoder, val) {
855    encoder.writeFloat(val);
856  };
857
858  function Double() {
859  }
860
861  Double.encodedSize = 8;
862
863  Double.decode = function(decoder) {
864    return decoder.readDouble();
865  };
866
867  Double.encode = function(encoder, val) {
868    encoder.writeDouble(val);
869  };
870
871  function Enum(cls) {
872    this.cls = cls;
873  }
874
875  Enum.prototype.encodedSize = 4;
876
877  Enum.prototype.decode = function(decoder) {
878    return decoder.readInt32();
879  };
880
881  Enum.prototype.encode = function(encoder, val) {
882    encoder.writeInt32(val);
883  };
884
885  function PointerTo(cls) {
886    this.cls = cls;
887  }
888
889  PointerTo.prototype.encodedSize = 8;
890
891  PointerTo.prototype.decode = function(decoder) {
892    var pointer = decoder.decodePointer();
893    if (!pointer) {
894      return null;
895    }
896    return this.cls.decode(decoder.decodeAndCreateDecoder(pointer));
897  };
898
899  PointerTo.prototype.encode = function(encoder, val) {
900    if (!val) {
901      encoder.encodePointer(val);
902      return;
903    }
904    var objectEncoder = encoder.createAndEncodeEncoder(this.cls.encodedSize);
905    this.cls.encode(objectEncoder, val);
906  };
907
908  function NullablePointerTo(cls) {
909    PointerTo.call(this, cls);
910  }
911
912  NullablePointerTo.prototype = Object.create(PointerTo.prototype);
913
914  function ArrayOf(cls, length) {
915    this.cls = cls;
916    this.length = length || 0;
917  }
918
919  ArrayOf.prototype.encodedSize = 8;
920
921  ArrayOf.prototype.dimensions = function() {
922    return [this.length].concat(
923      (this.cls instanceof ArrayOf) ? this.cls.dimensions() : []);
924  }
925
926  ArrayOf.prototype.decode = function(decoder) {
927    return decoder.decodeArrayPointer(this.cls);
928  };
929
930  ArrayOf.prototype.encode = function(encoder, val) {
931    encoder.encodeArrayPointer(this.cls, val);
932  };
933
934  function NullableArrayOf(cls) {
935    ArrayOf.call(this, cls);
936  }
937
938  NullableArrayOf.prototype = Object.create(ArrayOf.prototype);
939
940  function Handle() {
941  }
942
943  Handle.encodedSize = 4;
944
945  Handle.decode = function(decoder) {
946    return decoder.decodeHandle();
947  };
948
949  Handle.encode = function(encoder, val) {
950    encoder.encodeHandle(val);
951  };
952
953  function NullableHandle() {
954  }
955
956  NullableHandle.encodedSize = Handle.encodedSize;
957
958  NullableHandle.decode = Handle.decode;
959
960  NullableHandle.encode = Handle.encode;
961
962  function Interface(cls) {
963    this.cls = cls;
964  }
965
966  Interface.prototype.encodedSize = 8;
967
968  Interface.prototype.decode = function(decoder) {
969    var interfacePtrInfo = new mojo.InterfacePtrInfo(
970        decoder.decodeHandle(), decoder.readUint32());
971    var interfacePtr = new this.cls();
972    interfacePtr.ptr.bind(interfacePtrInfo);
973    return interfacePtr;
974  };
975
976  Interface.prototype.encode = function(encoder, val) {
977    var interfacePtrInfo =
978        val ? val.ptr.passInterface() : new mojo.InterfacePtrInfo(null, 0);
979    encoder.encodeHandle(interfacePtrInfo.handle);
980    encoder.writeUint32(interfacePtrInfo.version);
981  };
982
983  function NullableInterface(cls) {
984    Interface.call(this, cls);
985  }
986
987  NullableInterface.prototype = Object.create(Interface.prototype);
988
989  function AssociatedInterfacePtrInfo() {
990  }
991
992  AssociatedInterfacePtrInfo.prototype.encodedSize = 8;
993
994  AssociatedInterfacePtrInfo.decode = function(decoder) {
995    return new mojo.AssociatedInterfacePtrInfo(
996      decoder.decodeAssociatedEndpointHandle(), decoder.readUint32());
997  };
998
999  AssociatedInterfacePtrInfo.encode = function(encoder, val) {
1000    var associatedinterfacePtrInfo =
1001        val ? val : new mojo.AssociatedInterfacePtrInfo(null, 0);
1002    encoder.encodeAssociatedEndpointHandle(
1003        associatedinterfacePtrInfo.interfaceEndpointHandle);
1004    encoder.writeUint32(associatedinterfacePtrInfo.version);
1005  };
1006
1007  function NullableAssociatedInterfacePtrInfo() {
1008  }
1009
1010  NullableAssociatedInterfacePtrInfo.encodedSize =
1011      AssociatedInterfacePtrInfo.encodedSize;
1012
1013  NullableAssociatedInterfacePtrInfo.decode =
1014      AssociatedInterfacePtrInfo.decode;
1015
1016  NullableAssociatedInterfacePtrInfo.encode =
1017      AssociatedInterfacePtrInfo.encode;
1018
1019  function InterfaceRequest() {
1020  }
1021
1022  InterfaceRequest.encodedSize = 4;
1023
1024  InterfaceRequest.decode = function(decoder) {
1025    return new mojo.InterfaceRequest(decoder.decodeHandle());
1026  };
1027
1028  InterfaceRequest.encode = function(encoder, val) {
1029    encoder.encodeHandle(val ? val.handle : null);
1030  };
1031
1032  function NullableInterfaceRequest() {
1033  }
1034
1035  NullableInterfaceRequest.encodedSize = InterfaceRequest.encodedSize;
1036
1037  NullableInterfaceRequest.decode = InterfaceRequest.decode;
1038
1039  NullableInterfaceRequest.encode = InterfaceRequest.encode;
1040
1041  function AssociatedInterfaceRequest() {
1042  }
1043
1044  AssociatedInterfaceRequest.decode = function(decoder) {
1045    var handle = decoder.decodeAssociatedEndpointHandle();
1046    return new mojo.AssociatedInterfaceRequest(handle);
1047  };
1048
1049  AssociatedInterfaceRequest.encode = function(encoder, val) {
1050    encoder.encodeAssociatedEndpointHandle(
1051        val ? val.interfaceEndpointHandle : null);
1052  };
1053
1054  AssociatedInterfaceRequest.encodedSize = 4;
1055
1056  function NullableAssociatedInterfaceRequest() {
1057  }
1058
1059  NullableAssociatedInterfaceRequest.encodedSize =
1060      AssociatedInterfaceRequest.encodedSize;
1061
1062  NullableAssociatedInterfaceRequest.decode =
1063      AssociatedInterfaceRequest.decode;
1064
1065  NullableAssociatedInterfaceRequest.encode =
1066      AssociatedInterfaceRequest.encode;
1067
1068  function MapOf(keyClass, valueClass) {
1069    this.keyClass = keyClass;
1070    this.valueClass = valueClass;
1071  }
1072
1073  MapOf.prototype.encodedSize = 8;
1074
1075  MapOf.prototype.decode = function(decoder) {
1076    return decoder.decodeMapPointer(this.keyClass, this.valueClass);
1077  };
1078
1079  MapOf.prototype.encode = function(encoder, val) {
1080    encoder.encodeMapPointer(this.keyClass, this.valueClass, val);
1081  };
1082
1083  function NullableMapOf(keyClass, valueClass) {
1084    MapOf.call(this, keyClass, valueClass);
1085  }
1086
1087  NullableMapOf.prototype = Object.create(MapOf.prototype);
1088
1089  internal.align = align;
1090  internal.isAligned = isAligned;
1091  internal.Message = Message;
1092  internal.MessageV0Builder = MessageV0Builder;
1093  internal.MessageV1Builder = MessageV1Builder;
1094  internal.MessageV2Builder = MessageV2Builder;
1095  internal.MessageReader = MessageReader;
1096  internal.kArrayHeaderSize = kArrayHeaderSize;
1097  internal.kMapStructPayloadSize = kMapStructPayloadSize;
1098  internal.kStructHeaderSize = kStructHeaderSize;
1099  internal.kEncodedInvalidHandleValue = kEncodedInvalidHandleValue;
1100  internal.kMessageV0HeaderSize = kMessageV0HeaderSize;
1101  internal.kMessageV1HeaderSize = kMessageV1HeaderSize;
1102  internal.kMessageV2HeaderSize = kMessageV2HeaderSize;
1103  internal.kMessagePayloadInterfaceIdsPointerOffset =
1104      kMessagePayloadInterfaceIdsPointerOffset;
1105  internal.kMessageExpectsResponse = kMessageExpectsResponse;
1106  internal.kMessageIsResponse = kMessageIsResponse;
1107  internal.Int8 = Int8;
1108  internal.Uint8 = Uint8;
1109  internal.Int16 = Int16;
1110  internal.Uint16 = Uint16;
1111  internal.Int32 = Int32;
1112  internal.Uint32 = Uint32;
1113  internal.Int64 = Int64;
1114  internal.Uint64 = Uint64;
1115  internal.Float = Float;
1116  internal.Double = Double;
1117  internal.String = String;
1118  internal.Enum = Enum;
1119  internal.NullableString = NullableString;
1120  internal.PointerTo = PointerTo;
1121  internal.NullablePointerTo = NullablePointerTo;
1122  internal.ArrayOf = ArrayOf;
1123  internal.NullableArrayOf = NullableArrayOf;
1124  internal.PackedBool = PackedBool;
1125  internal.Handle = Handle;
1126  internal.NullableHandle = NullableHandle;
1127  internal.Interface = Interface;
1128  internal.NullableInterface = NullableInterface;
1129  internal.InterfaceRequest = InterfaceRequest;
1130  internal.NullableInterfaceRequest = NullableInterfaceRequest;
1131  internal.AssociatedInterfacePtrInfo = AssociatedInterfacePtrInfo;
1132  internal.NullableAssociatedInterfacePtrInfo =
1133      NullableAssociatedInterfacePtrInfo;
1134  internal.AssociatedInterfaceRequest = AssociatedInterfaceRequest;
1135  internal.NullableAssociatedInterfaceRequest =
1136      NullableAssociatedInterfaceRequest;
1137  internal.MapOf = MapOf;
1138  internal.NullableMapOf = NullableMapOf;
1139})();
1140