| // Copyright 2014 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| define("mojo/public/js/codec", [ |
| "mojo/public/js/buffer", |
| "mojo/public/js/interface_types", |
| "mojo/public/js/lib/interface_endpoint_handle", |
| "mojo/public/js/unicode", |
| ], function(buffer, types, interfaceEndpointHandle, unicode) { |
| |
| var kErrorUnsigned = "Passing negative value to unsigned"; |
| var kErrorArray = "Passing non Array for array type"; |
| var kErrorString = "Passing non String for string type"; |
| var kErrorMap = "Passing non Map for map type"; |
| var InterfaceEndpointHandle = interfaceEndpointHandle.InterfaceEndpointHandle; |
| |
| // Memory ------------------------------------------------------------------- |
| |
| var kAlignment = 8; |
| |
| function align(size) { |
| return size + (kAlignment - (size % kAlignment)) % kAlignment; |
| } |
| |
| function isAligned(offset) { |
| return offset >= 0 && (offset % kAlignment) === 0; |
| } |
| |
| // Constants ---------------------------------------------------------------- |
| |
| var kArrayHeaderSize = 8; |
| var kStructHeaderSize = 8; |
| var kMessageV0HeaderSize = 24; |
| var kMessageV1HeaderSize = 32; |
| var kMessageV2HeaderSize = 48; |
| var kMapStructPayloadSize = 16; |
| |
| var kStructHeaderNumBytesOffset = 0; |
| var kStructHeaderVersionOffset = 4; |
| |
| var kEncodedInvalidHandleValue = 0xFFFFFFFF; |
| |
| // Decoder ------------------------------------------------------------------ |
| |
| function Decoder(buffer, handles, associatedEndpointHandles, base) { |
| this.buffer = buffer; |
| this.handles = handles; |
| this.associatedEndpointHandles = associatedEndpointHandles; |
| this.base = base; |
| this.next = base; |
| } |
| |
| Decoder.prototype.align = function() { |
| this.next = align(this.next); |
| }; |
| |
| Decoder.prototype.skip = function(offset) { |
| this.next += offset; |
| }; |
| |
| Decoder.prototype.readInt8 = function() { |
| var result = this.buffer.getInt8(this.next); |
| this.next += 1; |
| return result; |
| }; |
| |
| Decoder.prototype.readUint8 = function() { |
| var result = this.buffer.getUint8(this.next); |
| this.next += 1; |
| return result; |
| }; |
| |
| Decoder.prototype.readInt16 = function() { |
| var result = this.buffer.getInt16(this.next); |
| this.next += 2; |
| return result; |
| }; |
| |
| Decoder.prototype.readUint16 = function() { |
| var result = this.buffer.getUint16(this.next); |
| this.next += 2; |
| return result; |
| }; |
| |
| Decoder.prototype.readInt32 = function() { |
| var result = this.buffer.getInt32(this.next); |
| this.next += 4; |
| return result; |
| }; |
| |
| Decoder.prototype.readUint32 = function() { |
| var result = this.buffer.getUint32(this.next); |
| this.next += 4; |
| return result; |
| }; |
| |
| Decoder.prototype.readInt64 = function() { |
| var result = this.buffer.getInt64(this.next); |
| this.next += 8; |
| return result; |
| }; |
| |
| Decoder.prototype.readUint64 = function() { |
| var result = this.buffer.getUint64(this.next); |
| this.next += 8; |
| return result; |
| }; |
| |
| Decoder.prototype.readFloat = function() { |
| var result = this.buffer.getFloat32(this.next); |
| this.next += 4; |
| return result; |
| }; |
| |
| Decoder.prototype.readDouble = function() { |
| var result = this.buffer.getFloat64(this.next); |
| this.next += 8; |
| return result; |
| }; |
| |
| Decoder.prototype.decodePointer = function() { |
| // TODO(abarth): To correctly decode a pointer, we need to know the real |
| // base address of the array buffer. |
| var offsetPointer = this.next; |
| var offset = this.readUint64(); |
| if (!offset) |
| return 0; |
| return offsetPointer + offset; |
| }; |
| |
| Decoder.prototype.decodeAndCreateDecoder = function(pointer) { |
| return new Decoder(this.buffer, this.handles, |
| this.associatedEndpointHandles, pointer); |
| }; |
| |
| Decoder.prototype.decodeHandle = function() { |
| return this.handles[this.readUint32()] || null; |
| }; |
| |
| Decoder.prototype.decodeAssociatedEndpointHandle = function() { |
| return this.associatedEndpointHandles[this.readUint32()] || null; |
| }; |
| |
| Decoder.prototype.decodeString = function() { |
| var numberOfBytes = this.readUint32(); |
| var numberOfElements = this.readUint32(); |
| var base = this.next; |
| this.next += numberOfElements; |
| return unicode.decodeUtf8String( |
| new Uint8Array(this.buffer.arrayBuffer, base, numberOfElements)); |
| }; |
| |
| Decoder.prototype.decodeArray = function(cls) { |
| var numberOfBytes = this.readUint32(); |
| var numberOfElements = this.readUint32(); |
| var val = new Array(numberOfElements); |
| if (cls === PackedBool) { |
| var byte; |
| for (var i = 0; i < numberOfElements; ++i) { |
| if (i % 8 === 0) |
| byte = this.readUint8(); |
| val[i] = (byte & (1 << i % 8)) ? true : false; |
| } |
| } else { |
| for (var i = 0; i < numberOfElements; ++i) { |
| val[i] = cls.decode(this); |
| } |
| } |
| return val; |
| }; |
| |
| Decoder.prototype.decodeStruct = function(cls) { |
| return cls.decode(this); |
| }; |
| |
| Decoder.prototype.decodeStructPointer = function(cls) { |
| var pointer = this.decodePointer(); |
| if (!pointer) { |
| return null; |
| } |
| return cls.decode(this.decodeAndCreateDecoder(pointer)); |
| }; |
| |
| Decoder.prototype.decodeArrayPointer = function(cls) { |
| var pointer = this.decodePointer(); |
| if (!pointer) { |
| return null; |
| } |
| return this.decodeAndCreateDecoder(pointer).decodeArray(cls); |
| }; |
| |
| Decoder.prototype.decodeStringPointer = function() { |
| var pointer = this.decodePointer(); |
| if (!pointer) { |
| return null; |
| } |
| return this.decodeAndCreateDecoder(pointer).decodeString(); |
| }; |
| |
| Decoder.prototype.decodeMap = function(keyClass, valueClass) { |
| this.skip(4); // numberOfBytes |
| this.skip(4); // version |
| var keys = this.decodeArrayPointer(keyClass); |
| var values = this.decodeArrayPointer(valueClass); |
| var val = new Map(); |
| for (var i = 0; i < keys.length; i++) |
| val.set(keys[i], values[i]); |
| return val; |
| }; |
| |
| Decoder.prototype.decodeMapPointer = function(keyClass, valueClass) { |
| var pointer = this.decodePointer(); |
| if (!pointer) { |
| return null; |
| } |
| var decoder = this.decodeAndCreateDecoder(pointer); |
| return decoder.decodeMap(keyClass, valueClass); |
| }; |
| |
| // Encoder ------------------------------------------------------------------ |
| |
| function Encoder(buffer, handles, associatedEndpointHandles, base) { |
| this.buffer = buffer; |
| this.handles = handles; |
| this.associatedEndpointHandles = associatedEndpointHandles; |
| this.base = base; |
| this.next = base; |
| } |
| |
| Encoder.prototype.align = function() { |
| this.next = align(this.next); |
| }; |
| |
| Encoder.prototype.skip = function(offset) { |
| this.next += offset; |
| }; |
| |
| Encoder.prototype.writeInt8 = function(val) { |
| this.buffer.setInt8(this.next, val); |
| this.next += 1; |
| }; |
| |
| Encoder.prototype.writeUint8 = function(val) { |
| if (val < 0) { |
| throw new Error(kErrorUnsigned); |
| } |
| this.buffer.setUint8(this.next, val); |
| this.next += 1; |
| }; |
| |
| Encoder.prototype.writeInt16 = function(val) { |
| this.buffer.setInt16(this.next, val); |
| this.next += 2; |
| }; |
| |
| Encoder.prototype.writeUint16 = function(val) { |
| if (val < 0) { |
| throw new Error(kErrorUnsigned); |
| } |
| this.buffer.setUint16(this.next, val); |
| this.next += 2; |
| }; |
| |
| Encoder.prototype.writeInt32 = function(val) { |
| this.buffer.setInt32(this.next, val); |
| this.next += 4; |
| }; |
| |
| Encoder.prototype.writeUint32 = function(val) { |
| if (val < 0) { |
| throw new Error(kErrorUnsigned); |
| } |
| this.buffer.setUint32(this.next, val); |
| this.next += 4; |
| }; |
| |
| Encoder.prototype.writeInt64 = function(val) { |
| this.buffer.setInt64(this.next, val); |
| this.next += 8; |
| }; |
| |
| Encoder.prototype.writeUint64 = function(val) { |
| if (val < 0) { |
| throw new Error(kErrorUnsigned); |
| } |
| this.buffer.setUint64(this.next, val); |
| this.next += 8; |
| }; |
| |
| Encoder.prototype.writeFloat = function(val) { |
| this.buffer.setFloat32(this.next, val); |
| this.next += 4; |
| }; |
| |
| Encoder.prototype.writeDouble = function(val) { |
| this.buffer.setFloat64(this.next, val); |
| this.next += 8; |
| }; |
| |
| Encoder.prototype.encodePointer = function(pointer) { |
| if (!pointer) |
| return this.writeUint64(0); |
| // TODO(abarth): To correctly encode a pointer, we need to know the real |
| // base address of the array buffer. |
| var offset = pointer - this.next; |
| this.writeUint64(offset); |
| }; |
| |
| Encoder.prototype.createAndEncodeEncoder = function(size) { |
| var pointer = this.buffer.alloc(align(size)); |
| this.encodePointer(pointer); |
| return new Encoder(this.buffer, this.handles, |
| this.associatedEndpointHandles, pointer); |
| }; |
| |
| Encoder.prototype.encodeHandle = function(handle) { |
| if (handle) { |
| this.handles.push(handle); |
| this.writeUint32(this.handles.length - 1); |
| } else { |
| this.writeUint32(kEncodedInvalidHandleValue); |
| } |
| }; |
| |
| Encoder.prototype.encodeAssociatedEndpointHandle = function(endpointHandle) { |
| if (endpointHandle) { |
| this.associatedEndpointHandles.push(endpointHandle); |
| this.writeUint32(this.associatedEndpointHandles.length - 1); |
| } else { |
| this.writeUint32(kEncodedInvalidHandleValue); |
| } |
| }; |
| |
| Encoder.prototype.encodeString = function(val) { |
| var base = this.next + kArrayHeaderSize; |
| var numberOfElements = unicode.encodeUtf8String( |
| val, new Uint8Array(this.buffer.arrayBuffer, base)); |
| var numberOfBytes = kArrayHeaderSize + numberOfElements; |
| this.writeUint32(numberOfBytes); |
| this.writeUint32(numberOfElements); |
| this.next += numberOfElements; |
| }; |
| |
| Encoder.prototype.encodeArray = |
| function(cls, val, numberOfElements, encodedSize) { |
| if (numberOfElements === undefined) |
| numberOfElements = val.length; |
| if (encodedSize === undefined) |
| encodedSize = kArrayHeaderSize + cls.encodedSize * numberOfElements; |
| |
| this.writeUint32(encodedSize); |
| this.writeUint32(numberOfElements); |
| |
| if (cls === PackedBool) { |
| var byte = 0; |
| for (i = 0; i < numberOfElements; ++i) { |
| if (val[i]) |
| byte |= (1 << i % 8); |
| if (i % 8 === 7 || i == numberOfElements - 1) { |
| Uint8.encode(this, byte); |
| byte = 0; |
| } |
| } |
| } else { |
| for (var i = 0; i < numberOfElements; ++i) |
| cls.encode(this, val[i]); |
| } |
| }; |
| |
| Encoder.prototype.encodeStruct = function(cls, val) { |
| return cls.encode(this, val); |
| }; |
| |
| Encoder.prototype.encodeStructPointer = function(cls, val) { |
| if (val == null) { |
| // Also handles undefined, since undefined == null. |
| this.encodePointer(val); |
| return; |
| } |
| var encoder = this.createAndEncodeEncoder(cls.encodedSize); |
| cls.encode(encoder, val); |
| }; |
| |
| Encoder.prototype.encodeArrayPointer = function(cls, val) { |
| if (val == null) { |
| // Also handles undefined, since undefined == null. |
| this.encodePointer(val); |
| return; |
| } |
| |
| var numberOfElements = val.length; |
| if (!Number.isSafeInteger(numberOfElements) || numberOfElements < 0) |
| throw new Error(kErrorArray); |
| |
| var encodedSize = kArrayHeaderSize + ((cls === PackedBool) ? |
| Math.ceil(numberOfElements / 8) : cls.encodedSize * numberOfElements); |
| var encoder = this.createAndEncodeEncoder(encodedSize); |
| encoder.encodeArray(cls, val, numberOfElements, encodedSize); |
| }; |
| |
| Encoder.prototype.encodeStringPointer = function(val) { |
| if (val == null) { |
| // Also handles undefined, since undefined == null. |
| this.encodePointer(val); |
| return; |
| } |
| // Only accepts string primivites, not String Objects like new String("foo") |
| if (typeof(val) !== "string") { |
| throw new Error(kErrorString); |
| } |
| var encodedSize = kArrayHeaderSize + unicode.utf8Length(val); |
| var encoder = this.createAndEncodeEncoder(encodedSize); |
| encoder.encodeString(val); |
| }; |
| |
| Encoder.prototype.encodeMap = function(keyClass, valueClass, val) { |
| var keys = new Array(val.size); |
| var values = new Array(val.size); |
| var i = 0; |
| val.forEach(function(value, key) { |
| values[i] = value; |
| keys[i++] = key; |
| }); |
| this.writeUint32(kStructHeaderSize + kMapStructPayloadSize); |
| this.writeUint32(0); // version |
| this.encodeArrayPointer(keyClass, keys); |
| this.encodeArrayPointer(valueClass, values); |
| } |
| |
| Encoder.prototype.encodeMapPointer = function(keyClass, valueClass, val) { |
| if (val == null) { |
| // Also handles undefined, since undefined == null. |
| this.encodePointer(val); |
| return; |
| } |
| if (!(val instanceof Map)) { |
| throw new Error(kErrorMap); |
| } |
| var encodedSize = kStructHeaderSize + kMapStructPayloadSize; |
| var encoder = this.createAndEncodeEncoder(encodedSize); |
| encoder.encodeMap(keyClass, valueClass, val); |
| }; |
| |
| // Message ------------------------------------------------------------------ |
| |
| var kMessageInterfaceIdOffset = kStructHeaderSize; |
| var kMessageNameOffset = kMessageInterfaceIdOffset + 4; |
| var kMessageFlagsOffset = kMessageNameOffset + 4; |
| var kMessageRequestIDOffset = kMessageFlagsOffset + 8; |
| var kMessagePayloadInterfaceIdsPointerOffset = kMessageV2HeaderSize - 8; |
| |
| var kMessageExpectsResponse = 1 << 0; |
| var kMessageIsResponse = 1 << 1; |
| |
| function Message(buffer, handles, associatedEndpointHandles) { |
| if (associatedEndpointHandles === undefined) { |
| associatedEndpointHandles = []; |
| } |
| |
| this.buffer = buffer; |
| this.handles = handles; |
| this.associatedEndpointHandles = associatedEndpointHandles; |
| } |
| |
| Message.prototype.getHeaderNumBytes = function() { |
| return this.buffer.getUint32(kStructHeaderNumBytesOffset); |
| }; |
| |
| Message.prototype.getHeaderVersion = function() { |
| return this.buffer.getUint32(kStructHeaderVersionOffset); |
| }; |
| |
| Message.prototype.getName = function() { |
| return this.buffer.getUint32(kMessageNameOffset); |
| }; |
| |
| Message.prototype.getFlags = function() { |
| return this.buffer.getUint32(kMessageFlagsOffset); |
| }; |
| |
| Message.prototype.getInterfaceId = function() { |
| return this.buffer.getUint32(kMessageInterfaceIdOffset); |
| }; |
| |
| Message.prototype.getPayloadInterfaceIds = function() { |
| if (this.getHeaderVersion() < 2) { |
| return null; |
| } |
| |
| var decoder = new Decoder(this.buffer, this.handles, |
| this.associatedEndpointHandles, |
| kMessagePayloadInterfaceIdsPointerOffset); |
| var payloadInterfaceIds = decoder.decodeArrayPointer(Uint32); |
| return payloadInterfaceIds; |
| }; |
| |
| Message.prototype.isResponse = function() { |
| return (this.getFlags() & kMessageIsResponse) != 0; |
| }; |
| |
| Message.prototype.expectsResponse = function() { |
| return (this.getFlags() & kMessageExpectsResponse) != 0; |
| }; |
| |
| Message.prototype.setRequestID = function(requestID) { |
| // TODO(darin): Verify that space was reserved for this field! |
| this.buffer.setUint64(kMessageRequestIDOffset, requestID); |
| }; |
| |
| Message.prototype.setInterfaceId = function(interfaceId) { |
| this.buffer.setUint32(kMessageInterfaceIdOffset, interfaceId); |
| }; |
| |
| Message.prototype.setPayloadInterfaceIds_ = function(payloadInterfaceIds) { |
| if (this.getHeaderVersion() < 2) { |
| throw new Error( |
| "Version of message does not support payload interface ids"); |
| } |
| |
| var decoder = new Decoder(this.buffer, this.handles, |
| this.associatedEndpointHandles, |
| kMessagePayloadInterfaceIdsPointerOffset); |
| var payloadInterfaceIdsOffset = decoder.decodePointer(); |
| var encoder = new Encoder(this.buffer, this.handles, |
| this.associatedEndpointHandles, |
| payloadInterfaceIdsOffset); |
| encoder.encodeArray(Uint32, payloadInterfaceIds); |
| }; |
| |
| Message.prototype.serializeAssociatedEndpointHandles = function( |
| associatedGroupController) { |
| if (this.associatedEndpointHandles.length > 0) { |
| if (this.getHeaderVersion() < 2) { |
| throw new Error( |
| "Version of message does not support associated endpoint handles"); |
| } |
| |
| var data = []; |
| for (var i = 0; i < this.associatedEndpointHandles.length; i++) { |
| var handle = this.associatedEndpointHandles[i]; |
| data.push(associatedGroupController.associateInterface(handle)); |
| } |
| this.associatedEndpointHandles = []; |
| this.setPayloadInterfaceIds_(data); |
| } |
| }; |
| |
| Message.prototype.deserializeAssociatedEndpointHandles = function( |
| associatedGroupController) { |
| if (this.getHeaderVersion() < 2) { |
| return true; |
| } |
| |
| this.associatedEndpointHandles = []; |
| var ids = this.getPayloadInterfaceIds(); |
| |
| var result = true; |
| for (var i = 0; i < ids.length; i++) { |
| var handle = associatedGroupController.createLocalEndpointHandle(ids[i]); |
| if (types.isValidInterfaceId(ids[i]) && !handle.isValid()) { |
| // |ids[i]| itself is valid but handle creation failed. In that case, |
| // mark deserialization as failed but continue to deserialize the |
| // rest of handles. |
| result = false; |
| } |
| this.associatedEndpointHandles.push(handle); |
| ids[i] = types.kInvalidInterfaceId; |
| } |
| |
| this.setPayloadInterfaceIds_(ids); |
| return result; |
| }; |
| |
| |
| // MessageV0Builder --------------------------------------------------------- |
| |
| function MessageV0Builder(messageName, payloadSize) { |
| // Currently, we don't compute the payload size correctly ahead of time. |
| // Instead, we resize the buffer at the end. |
| var numberOfBytes = kMessageV0HeaderSize + payloadSize; |
| this.buffer = new buffer.Buffer(numberOfBytes); |
| this.handles = []; |
| var encoder = this.createEncoder(kMessageV0HeaderSize); |
| encoder.writeUint32(kMessageV0HeaderSize); |
| encoder.writeUint32(0); // version. |
| encoder.writeUint32(0); // interface ID. |
| encoder.writeUint32(messageName); |
| encoder.writeUint32(0); // flags. |
| encoder.writeUint32(0); // padding. |
| } |
| |
| MessageV0Builder.prototype.createEncoder = function(size) { |
| var pointer = this.buffer.alloc(size); |
| return new Encoder(this.buffer, this.handles, [], pointer); |
| }; |
| |
| MessageV0Builder.prototype.encodeStruct = function(cls, val) { |
| cls.encode(this.createEncoder(cls.encodedSize), val); |
| }; |
| |
| MessageV0Builder.prototype.finish = function() { |
| // TODO(abarth): Rather than resizing the buffer at the end, we could |
| // compute the size we need ahead of time, like we do in C++. |
| this.buffer.trim(); |
| var message = new Message(this.buffer, this.handles); |
| this.buffer = null; |
| this.handles = null; |
| this.encoder = null; |
| return message; |
| }; |
| |
| // MessageV1Builder ----------------------------------------------- |
| |
| function MessageV1Builder(messageName, payloadSize, flags, |
| requestID) { |
| // Currently, we don't compute the payload size correctly ahead of time. |
| // Instead, we resize the buffer at the end. |
| var numberOfBytes = kMessageV1HeaderSize + payloadSize; |
| this.buffer = new buffer.Buffer(numberOfBytes); |
| this.handles = []; |
| var encoder = this.createEncoder(kMessageV1HeaderSize); |
| encoder.writeUint32(kMessageV1HeaderSize); |
| encoder.writeUint32(1); // version. |
| encoder.writeUint32(0); // interface ID. |
| encoder.writeUint32(messageName); |
| encoder.writeUint32(flags); |
| encoder.writeUint32(0); // padding. |
| encoder.writeUint64(requestID); |
| } |
| |
| MessageV1Builder.prototype = |
| Object.create(MessageV0Builder.prototype); |
| |
| MessageV1Builder.prototype.constructor = |
| MessageV1Builder; |
| |
| // MessageV2 ----------------------------------------------- |
| |
| function MessageV2Builder(messageName, payloadSize, flags, requestID) { |
| // Currently, we don't compute the payload size correctly ahead of time. |
| // Instead, we resize the buffer at the end. |
| var numberOfBytes = kMessageV2HeaderSize + payloadSize; |
| this.buffer = new buffer.Buffer(numberOfBytes); |
| this.handles = []; |
| |
| this.payload = null; |
| this.associatedEndpointHandles = []; |
| |
| this.encoder = this.createEncoder(kMessageV2HeaderSize); |
| this.encoder.writeUint32(kMessageV2HeaderSize); |
| this.encoder.writeUint32(2); // version. |
| // Gets set to an appropriate interfaceId for the endpoint by the Router. |
| this.encoder.writeUint32(0); // interface ID. |
| this.encoder.writeUint32(messageName); |
| this.encoder.writeUint32(flags); |
| this.encoder.writeUint32(0); // padding. |
| this.encoder.writeUint64(requestID); |
| } |
| |
| MessageV2Builder.prototype.createEncoder = function(size) { |
| var pointer = this.buffer.alloc(size); |
| return new Encoder(this.buffer, this.handles, |
| this.associatedEndpointHandles, pointer); |
| }; |
| |
| MessageV2Builder.prototype.setPayload = function(cls, val) { |
| this.payload = {cls: cls, val: val}; |
| }; |
| |
| MessageV2Builder.prototype.finish = function() { |
| if (!this.payload) { |
| throw new Error("Payload needs to be set before calling finish"); |
| } |
| |
| this.encoder.encodeStructPointer(this.payload.cls, this.payload.val); |
| this.encoder.encodeArrayPointer(Uint32, |
| new Array(this.associatedEndpointHandles.length)); |
| |
| this.buffer.trim(); |
| var message = new Message(this.buffer, this.handles, |
| this.associatedEndpointHandles); |
| this.buffer = null; |
| this.handles = null; |
| this.encoder = null; |
| this.payload = null; |
| this.associatedEndpointHandles = null; |
| |
| return message; |
| }; |
| |
| // MessageReader ------------------------------------------------------------ |
| |
| function MessageReader(message) { |
| this.decoder = new Decoder(message.buffer, message.handles, |
| message.associatedEndpointHandles, 0); |
| var messageHeaderSize = this.decoder.readUint32(); |
| this.payloadSize = message.buffer.byteLength - messageHeaderSize; |
| var version = this.decoder.readUint32(); |
| var interface_id = this.decoder.readUint32(); |
| this.messageName = this.decoder.readUint32(); |
| this.flags = this.decoder.readUint32(); |
| // Skip the padding. |
| this.decoder.skip(4); |
| if (version >= 1) |
| this.requestID = this.decoder.readUint64(); |
| this.decoder.skip(messageHeaderSize - this.decoder.next); |
| } |
| |
| MessageReader.prototype.decodeStruct = function(cls) { |
| return cls.decode(this.decoder); |
| }; |
| |
| // Built-in types ----------------------------------------------------------- |
| |
| // This type is only used with ArrayOf(PackedBool). |
| function PackedBool() { |
| } |
| |
| function Int8() { |
| } |
| |
| Int8.encodedSize = 1; |
| |
| Int8.decode = function(decoder) { |
| return decoder.readInt8(); |
| }; |
| |
| Int8.encode = function(encoder, val) { |
| encoder.writeInt8(val); |
| }; |
| |
| Uint8.encode = function(encoder, val) { |
| encoder.writeUint8(val); |
| }; |
| |
| function Uint8() { |
| } |
| |
| Uint8.encodedSize = 1; |
| |
| Uint8.decode = function(decoder) { |
| return decoder.readUint8(); |
| }; |
| |
| Uint8.encode = function(encoder, val) { |
| encoder.writeUint8(val); |
| }; |
| |
| function Int16() { |
| } |
| |
| Int16.encodedSize = 2; |
| |
| Int16.decode = function(decoder) { |
| return decoder.readInt16(); |
| }; |
| |
| Int16.encode = function(encoder, val) { |
| encoder.writeInt16(val); |
| }; |
| |
| function Uint16() { |
| } |
| |
| Uint16.encodedSize = 2; |
| |
| Uint16.decode = function(decoder) { |
| return decoder.readUint16(); |
| }; |
| |
| Uint16.encode = function(encoder, val) { |
| encoder.writeUint16(val); |
| }; |
| |
| function Int32() { |
| } |
| |
| Int32.encodedSize = 4; |
| |
| Int32.decode = function(decoder) { |
| return decoder.readInt32(); |
| }; |
| |
| Int32.encode = function(encoder, val) { |
| encoder.writeInt32(val); |
| }; |
| |
| function Uint32() { |
| } |
| |
| Uint32.encodedSize = 4; |
| |
| Uint32.decode = function(decoder) { |
| return decoder.readUint32(); |
| }; |
| |
| Uint32.encode = function(encoder, val) { |
| encoder.writeUint32(val); |
| }; |
| |
| function Int64() { |
| } |
| |
| Int64.encodedSize = 8; |
| |
| Int64.decode = function(decoder) { |
| return decoder.readInt64(); |
| }; |
| |
| Int64.encode = function(encoder, val) { |
| encoder.writeInt64(val); |
| }; |
| |
| function Uint64() { |
| } |
| |
| Uint64.encodedSize = 8; |
| |
| Uint64.decode = function(decoder) { |
| return decoder.readUint64(); |
| }; |
| |
| Uint64.encode = function(encoder, val) { |
| encoder.writeUint64(val); |
| }; |
| |
| function String() { |
| }; |
| |
| String.encodedSize = 8; |
| |
| String.decode = function(decoder) { |
| return decoder.decodeStringPointer(); |
| }; |
| |
| String.encode = function(encoder, val) { |
| encoder.encodeStringPointer(val); |
| }; |
| |
| function NullableString() { |
| } |
| |
| NullableString.encodedSize = String.encodedSize; |
| |
| NullableString.decode = String.decode; |
| |
| NullableString.encode = String.encode; |
| |
| function Float() { |
| } |
| |
| Float.encodedSize = 4; |
| |
| Float.decode = function(decoder) { |
| return decoder.readFloat(); |
| }; |
| |
| Float.encode = function(encoder, val) { |
| encoder.writeFloat(val); |
| }; |
| |
| function Double() { |
| } |
| |
| Double.encodedSize = 8; |
| |
| Double.decode = function(decoder) { |
| return decoder.readDouble(); |
| }; |
| |
| Double.encode = function(encoder, val) { |
| encoder.writeDouble(val); |
| }; |
| |
| function Enum(cls) { |
| this.cls = cls; |
| } |
| |
| Enum.prototype.encodedSize = 4; |
| |
| Enum.prototype.decode = function(decoder) { |
| return decoder.readInt32(); |
| }; |
| |
| Enum.prototype.encode = function(encoder, val) { |
| encoder.writeInt32(val); |
| }; |
| |
| function PointerTo(cls) { |
| this.cls = cls; |
| } |
| |
| PointerTo.prototype.encodedSize = 8; |
| |
| PointerTo.prototype.decode = function(decoder) { |
| var pointer = decoder.decodePointer(); |
| if (!pointer) { |
| return null; |
| } |
| return this.cls.decode(decoder.decodeAndCreateDecoder(pointer)); |
| }; |
| |
| PointerTo.prototype.encode = function(encoder, val) { |
| if (!val) { |
| encoder.encodePointer(val); |
| return; |
| } |
| var objectEncoder = encoder.createAndEncodeEncoder(this.cls.encodedSize); |
| this.cls.encode(objectEncoder, val); |
| }; |
| |
| function NullablePointerTo(cls) { |
| PointerTo.call(this, cls); |
| } |
| |
| NullablePointerTo.prototype = Object.create(PointerTo.prototype); |
| |
| function ArrayOf(cls, length) { |
| this.cls = cls; |
| this.length = length || 0; |
| } |
| |
| ArrayOf.prototype.encodedSize = 8; |
| |
| ArrayOf.prototype.dimensions = function() { |
| return [this.length].concat( |
| (this.cls instanceof ArrayOf) ? this.cls.dimensions() : []); |
| } |
| |
| ArrayOf.prototype.decode = function(decoder) { |
| return decoder.decodeArrayPointer(this.cls); |
| }; |
| |
| ArrayOf.prototype.encode = function(encoder, val) { |
| encoder.encodeArrayPointer(this.cls, val); |
| }; |
| |
| function NullableArrayOf(cls) { |
| ArrayOf.call(this, cls); |
| } |
| |
| NullableArrayOf.prototype = Object.create(ArrayOf.prototype); |
| |
| function Handle() { |
| } |
| |
| Handle.encodedSize = 4; |
| |
| Handle.decode = function(decoder) { |
| return decoder.decodeHandle(); |
| }; |
| |
| Handle.encode = function(encoder, val) { |
| encoder.encodeHandle(val); |
| }; |
| |
| function NullableHandle() { |
| } |
| |
| NullableHandle.encodedSize = Handle.encodedSize; |
| |
| NullableHandle.decode = Handle.decode; |
| |
| NullableHandle.encode = Handle.encode; |
| |
| function Interface(cls) { |
| this.cls = cls; |
| } |
| |
| Interface.prototype.encodedSize = 8; |
| |
| Interface.prototype.decode = function(decoder) { |
| var interfacePtrInfo = new types.InterfacePtrInfo( |
| decoder.decodeHandle(), decoder.readUint32()); |
| var interfacePtr = new this.cls(); |
| interfacePtr.ptr.bind(interfacePtrInfo); |
| return interfacePtr; |
| }; |
| |
| Interface.prototype.encode = function(encoder, val) { |
| var interfacePtrInfo = |
| val ? val.ptr.passInterface() : new types.InterfacePtrInfo(null, 0); |
| encoder.encodeHandle(interfacePtrInfo.handle); |
| encoder.writeUint32(interfacePtrInfo.version); |
| }; |
| |
| function NullableInterface(cls) { |
| Interface.call(this, cls); |
| } |
| |
| NullableInterface.prototype = Object.create(Interface.prototype); |
| |
| function AssociatedInterfacePtrInfo() { |
| } |
| |
| AssociatedInterfacePtrInfo.prototype.encodedSize = 8; |
| |
| AssociatedInterfacePtrInfo.decode = function(decoder) { |
| return new types.AssociatedInterfacePtrInfo( |
| decoder.decodeAssociatedEndpointHandle(), decoder.readUint32()); |
| }; |
| |
| AssociatedInterfacePtrInfo.encode = function(encoder, val) { |
| var associatedinterfacePtrInfo = |
| val ? val : new types.AssociatedInterfacePtrInfo(null, 0); |
| encoder.encodeAssociatedEndpointHandle( |
| associatedinterfacePtrInfo.interfaceEndpointHandle); |
| encoder.writeUint32(associatedinterfacePtrInfo.version); |
| }; |
| |
| function NullableAssociatedInterfacePtrInfo() { |
| } |
| |
| NullableAssociatedInterfacePtrInfo.encodedSize = |
| AssociatedInterfacePtrInfo.encodedSize; |
| |
| NullableAssociatedInterfacePtrInfo.decode = |
| AssociatedInterfacePtrInfo.decode; |
| |
| NullableAssociatedInterfacePtrInfo.encode = |
| AssociatedInterfacePtrInfo.encode; |
| |
| function InterfaceRequest() { |
| } |
| |
| InterfaceRequest.encodedSize = 4; |
| |
| InterfaceRequest.decode = function(decoder) { |
| return new types.InterfaceRequest(decoder.decodeHandle()); |
| }; |
| |
| InterfaceRequest.encode = function(encoder, val) { |
| encoder.encodeHandle(val ? val.handle : null); |
| }; |
| |
| function NullableInterfaceRequest() { |
| } |
| |
| NullableInterfaceRequest.encodedSize = InterfaceRequest.encodedSize; |
| |
| NullableInterfaceRequest.decode = InterfaceRequest.decode; |
| |
| NullableInterfaceRequest.encode = InterfaceRequest.encode; |
| |
| function AssociatedInterfaceRequest() { |
| } |
| |
| AssociatedInterfaceRequest.decode = function(decoder) { |
| var handle = decoder.decodeAssociatedEndpointHandle(); |
| return new types.AssociatedInterfaceRequest(handle); |
| }; |
| |
| AssociatedInterfaceRequest.encode = function(encoder, val) { |
| encoder.encodeAssociatedEndpointHandle( |
| val ? val.interfaceEndpointHandle : null); |
| }; |
| |
| AssociatedInterfaceRequest.encodedSize = 4; |
| |
| function NullableAssociatedInterfaceRequest() { |
| } |
| |
| NullableAssociatedInterfaceRequest.encodedSize = |
| AssociatedInterfaceRequest.encodedSize; |
| |
| NullableAssociatedInterfaceRequest.decode = |
| AssociatedInterfaceRequest.decode; |
| |
| NullableAssociatedInterfaceRequest.encode = |
| AssociatedInterfaceRequest.encode; |
| |
| function MapOf(keyClass, valueClass) { |
| this.keyClass = keyClass; |
| this.valueClass = valueClass; |
| } |
| |
| MapOf.prototype.encodedSize = 8; |
| |
| MapOf.prototype.decode = function(decoder) { |
| return decoder.decodeMapPointer(this.keyClass, this.valueClass); |
| }; |
| |
| MapOf.prototype.encode = function(encoder, val) { |
| encoder.encodeMapPointer(this.keyClass, this.valueClass, val); |
| }; |
| |
| function NullableMapOf(keyClass, valueClass) { |
| MapOf.call(this, keyClass, valueClass); |
| } |
| |
| NullableMapOf.prototype = Object.create(MapOf.prototype); |
| |
| var exports = {}; |
| exports.align = align; |
| exports.isAligned = isAligned; |
| exports.Message = Message; |
| exports.MessageV0Builder = MessageV0Builder; |
| exports.MessageV1Builder = MessageV1Builder; |
| exports.MessageV2Builder = MessageV2Builder; |
| exports.MessageReader = MessageReader; |
| exports.kArrayHeaderSize = kArrayHeaderSize; |
| exports.kMapStructPayloadSize = kMapStructPayloadSize; |
| exports.kStructHeaderSize = kStructHeaderSize; |
| exports.kEncodedInvalidHandleValue = kEncodedInvalidHandleValue; |
| exports.kMessageV0HeaderSize = kMessageV0HeaderSize; |
| exports.kMessageV1HeaderSize = kMessageV1HeaderSize; |
| exports.kMessageV2HeaderSize = kMessageV2HeaderSize; |
| exports.kMessagePayloadInterfaceIdsPointerOffset = |
| kMessagePayloadInterfaceIdsPointerOffset; |
| exports.kMessageExpectsResponse = kMessageExpectsResponse; |
| exports.kMessageIsResponse = kMessageIsResponse; |
| exports.Int8 = Int8; |
| exports.Uint8 = Uint8; |
| exports.Int16 = Int16; |
| exports.Uint16 = Uint16; |
| exports.Int32 = Int32; |
| exports.Uint32 = Uint32; |
| exports.Int64 = Int64; |
| exports.Uint64 = Uint64; |
| exports.Float = Float; |
| exports.Double = Double; |
| exports.String = String; |
| exports.Enum = Enum; |
| exports.NullableString = NullableString; |
| exports.PointerTo = PointerTo; |
| exports.NullablePointerTo = NullablePointerTo; |
| exports.ArrayOf = ArrayOf; |
| exports.NullableArrayOf = NullableArrayOf; |
| exports.PackedBool = PackedBool; |
| exports.Handle = Handle; |
| exports.NullableHandle = NullableHandle; |
| exports.Interface = Interface; |
| exports.NullableInterface = NullableInterface; |
| exports.InterfaceRequest = InterfaceRequest; |
| exports.NullableInterfaceRequest = NullableInterfaceRequest; |
| exports.AssociatedInterfacePtrInfo = AssociatedInterfacePtrInfo; |
| exports.NullableAssociatedInterfacePtrInfo = |
| NullableAssociatedInterfacePtrInfo; |
| exports.AssociatedInterfaceRequest = AssociatedInterfaceRequest; |
| exports.NullableAssociatedInterfaceRequest = |
| NullableAssociatedInterfaceRequest; |
| exports.MapOf = MapOf; |
| exports.NullableMapOf = NullableMapOf; |
| return exports; |
| }); |