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