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