1ffe3c632Sopenharmony_ci// Protocol Buffers - Google's data interchange format 2ffe3c632Sopenharmony_ci// Copyright 2008 Google Inc. All rights reserved. 3ffe3c632Sopenharmony_ci// https://developers.google.com/protocol-buffers/ 4ffe3c632Sopenharmony_ci// 5ffe3c632Sopenharmony_ci// Redistribution and use in source and binary forms, with or without 6ffe3c632Sopenharmony_ci// modification, are permitted provided that the following conditions are 7ffe3c632Sopenharmony_ci// met: 8ffe3c632Sopenharmony_ci// 9ffe3c632Sopenharmony_ci// * Redistributions of source code must retain the above copyright 10ffe3c632Sopenharmony_ci// notice, this list of conditions and the following disclaimer. 11ffe3c632Sopenharmony_ci// * Redistributions in binary form must reproduce the above 12ffe3c632Sopenharmony_ci// copyright notice, this list of conditions and the following disclaimer 13ffe3c632Sopenharmony_ci// in the documentation and/or other materials provided with the 14ffe3c632Sopenharmony_ci// distribution. 15ffe3c632Sopenharmony_ci// * Neither the name of Google Inc. nor the names of its 16ffe3c632Sopenharmony_ci// contributors may be used to endorse or promote products derived from 17ffe3c632Sopenharmony_ci// this software without specific prior written permission. 18ffe3c632Sopenharmony_ci// 19ffe3c632Sopenharmony_ci// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20ffe3c632Sopenharmony_ci// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21ffe3c632Sopenharmony_ci// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22ffe3c632Sopenharmony_ci// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23ffe3c632Sopenharmony_ci// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24ffe3c632Sopenharmony_ci// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25ffe3c632Sopenharmony_ci// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26ffe3c632Sopenharmony_ci// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27ffe3c632Sopenharmony_ci// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28ffe3c632Sopenharmony_ci// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29ffe3c632Sopenharmony_ci// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30ffe3c632Sopenharmony_ci 31ffe3c632Sopenharmony_ci/** 32ffe3c632Sopenharmony_ci * @fileoverview BinaryEncode defines methods for encoding Javascript values 33ffe3c632Sopenharmony_ci * into arrays of bytes compatible with the Protocol Buffer wire format. 34ffe3c632Sopenharmony_ci * 35ffe3c632Sopenharmony_ci * @author aappleby@google.com (Austin Appleby) 36ffe3c632Sopenharmony_ci */ 37ffe3c632Sopenharmony_ci 38ffe3c632Sopenharmony_cigoog.provide('jspb.BinaryEncoder'); 39ffe3c632Sopenharmony_ci 40ffe3c632Sopenharmony_cigoog.require('goog.asserts'); 41ffe3c632Sopenharmony_cigoog.require('jspb.BinaryConstants'); 42ffe3c632Sopenharmony_cigoog.require('jspb.utils'); 43ffe3c632Sopenharmony_ci 44ffe3c632Sopenharmony_ci 45ffe3c632Sopenharmony_ci 46ffe3c632Sopenharmony_ci/** 47ffe3c632Sopenharmony_ci * BinaryEncoder implements encoders for all the wire types specified in 48ffe3c632Sopenharmony_ci * https://developers.google.com/protocol-buffers/docs/encoding. 49ffe3c632Sopenharmony_ci * 50ffe3c632Sopenharmony_ci * @constructor 51ffe3c632Sopenharmony_ci * @struct 52ffe3c632Sopenharmony_ci */ 53ffe3c632Sopenharmony_cijspb.BinaryEncoder = function() { 54ffe3c632Sopenharmony_ci /** @private {!Array<number>} */ 55ffe3c632Sopenharmony_ci this.buffer_ = []; 56ffe3c632Sopenharmony_ci}; 57ffe3c632Sopenharmony_ci 58ffe3c632Sopenharmony_ci 59ffe3c632Sopenharmony_ci/** 60ffe3c632Sopenharmony_ci * @return {number} 61ffe3c632Sopenharmony_ci */ 62ffe3c632Sopenharmony_cijspb.BinaryEncoder.prototype.length = function() { 63ffe3c632Sopenharmony_ci return this.buffer_.length; 64ffe3c632Sopenharmony_ci}; 65ffe3c632Sopenharmony_ci 66ffe3c632Sopenharmony_ci 67ffe3c632Sopenharmony_ci/** 68ffe3c632Sopenharmony_ci * @return {!Array<number>} 69ffe3c632Sopenharmony_ci */ 70ffe3c632Sopenharmony_cijspb.BinaryEncoder.prototype.end = function() { 71ffe3c632Sopenharmony_ci var buffer = this.buffer_; 72ffe3c632Sopenharmony_ci this.buffer_ = []; 73ffe3c632Sopenharmony_ci return buffer; 74ffe3c632Sopenharmony_ci}; 75ffe3c632Sopenharmony_ci 76ffe3c632Sopenharmony_ci 77ffe3c632Sopenharmony_ci/** 78ffe3c632Sopenharmony_ci * Encodes a 64-bit integer in 32:32 split representation into its wire-format 79ffe3c632Sopenharmony_ci * varint representation and stores it in the buffer. 80ffe3c632Sopenharmony_ci * @param {number} lowBits The low 32 bits of the int. 81ffe3c632Sopenharmony_ci * @param {number} highBits The high 32 bits of the int. 82ffe3c632Sopenharmony_ci */ 83ffe3c632Sopenharmony_cijspb.BinaryEncoder.prototype.writeSplitVarint64 = function(lowBits, highBits) { 84ffe3c632Sopenharmony_ci goog.asserts.assert(lowBits == Math.floor(lowBits)); 85ffe3c632Sopenharmony_ci goog.asserts.assert(highBits == Math.floor(highBits)); 86ffe3c632Sopenharmony_ci goog.asserts.assert((lowBits >= 0) && 87ffe3c632Sopenharmony_ci (lowBits < jspb.BinaryConstants.TWO_TO_32)); 88ffe3c632Sopenharmony_ci goog.asserts.assert((highBits >= 0) && 89ffe3c632Sopenharmony_ci (highBits < jspb.BinaryConstants.TWO_TO_32)); 90ffe3c632Sopenharmony_ci 91ffe3c632Sopenharmony_ci // Break the binary representation into chunks of 7 bits, set the 8th bit 92ffe3c632Sopenharmony_ci // in each chunk if it's not the final chunk, and append to the result. 93ffe3c632Sopenharmony_ci while (highBits > 0 || lowBits > 127) { 94ffe3c632Sopenharmony_ci this.buffer_.push((lowBits & 0x7f) | 0x80); 95ffe3c632Sopenharmony_ci lowBits = ((lowBits >>> 7) | (highBits << 25)) >>> 0; 96ffe3c632Sopenharmony_ci highBits = highBits >>> 7; 97ffe3c632Sopenharmony_ci } 98ffe3c632Sopenharmony_ci this.buffer_.push(lowBits); 99ffe3c632Sopenharmony_ci}; 100ffe3c632Sopenharmony_ci 101ffe3c632Sopenharmony_ci 102ffe3c632Sopenharmony_ci/** 103ffe3c632Sopenharmony_ci * Encodes a 64-bit integer in 32:32 split representation into its wire-format 104ffe3c632Sopenharmony_ci * fixed representation and stores it in the buffer. 105ffe3c632Sopenharmony_ci * @param {number} lowBits The low 32 bits of the int. 106ffe3c632Sopenharmony_ci * @param {number} highBits The high 32 bits of the int. 107ffe3c632Sopenharmony_ci */ 108ffe3c632Sopenharmony_cijspb.BinaryEncoder.prototype.writeSplitFixed64 = function(lowBits, highBits) { 109ffe3c632Sopenharmony_ci goog.asserts.assert(lowBits == Math.floor(lowBits)); 110ffe3c632Sopenharmony_ci goog.asserts.assert(highBits == Math.floor(highBits)); 111ffe3c632Sopenharmony_ci goog.asserts.assert((lowBits >= 0) && 112ffe3c632Sopenharmony_ci (lowBits < jspb.BinaryConstants.TWO_TO_32)); 113ffe3c632Sopenharmony_ci goog.asserts.assert((highBits >= 0) && 114ffe3c632Sopenharmony_ci (highBits < jspb.BinaryConstants.TWO_TO_32)); 115ffe3c632Sopenharmony_ci this.writeUint32(lowBits); 116ffe3c632Sopenharmony_ci this.writeUint32(highBits); 117ffe3c632Sopenharmony_ci}; 118ffe3c632Sopenharmony_ci 119ffe3c632Sopenharmony_ci 120ffe3c632Sopenharmony_ci/** 121ffe3c632Sopenharmony_ci * Encodes a 32-bit unsigned integer into its wire-format varint representation 122ffe3c632Sopenharmony_ci * and stores it in the buffer. 123ffe3c632Sopenharmony_ci * @param {number} value The integer to convert. 124ffe3c632Sopenharmony_ci */ 125ffe3c632Sopenharmony_cijspb.BinaryEncoder.prototype.writeUnsignedVarint32 = function(value) { 126ffe3c632Sopenharmony_ci goog.asserts.assert(value == Math.floor(value)); 127ffe3c632Sopenharmony_ci goog.asserts.assert((value >= 0) && 128ffe3c632Sopenharmony_ci (value < jspb.BinaryConstants.TWO_TO_32)); 129ffe3c632Sopenharmony_ci 130ffe3c632Sopenharmony_ci while (value > 127) { 131ffe3c632Sopenharmony_ci this.buffer_.push((value & 0x7f) | 0x80); 132ffe3c632Sopenharmony_ci value = value >>> 7; 133ffe3c632Sopenharmony_ci } 134ffe3c632Sopenharmony_ci 135ffe3c632Sopenharmony_ci this.buffer_.push(value); 136ffe3c632Sopenharmony_ci}; 137ffe3c632Sopenharmony_ci 138ffe3c632Sopenharmony_ci 139ffe3c632Sopenharmony_ci/** 140ffe3c632Sopenharmony_ci * Encodes a 32-bit signed integer into its wire-format varint representation 141ffe3c632Sopenharmony_ci * and stores it in the buffer. 142ffe3c632Sopenharmony_ci * @param {number} value The integer to convert. 143ffe3c632Sopenharmony_ci */ 144ffe3c632Sopenharmony_cijspb.BinaryEncoder.prototype.writeSignedVarint32 = function(value) { 145ffe3c632Sopenharmony_ci goog.asserts.assert(value == Math.floor(value)); 146ffe3c632Sopenharmony_ci goog.asserts.assert((value >= -jspb.BinaryConstants.TWO_TO_31) && 147ffe3c632Sopenharmony_ci (value < jspb.BinaryConstants.TWO_TO_31)); 148ffe3c632Sopenharmony_ci 149ffe3c632Sopenharmony_ci // Use the unsigned version if the value is not negative. 150ffe3c632Sopenharmony_ci if (value >= 0) { 151ffe3c632Sopenharmony_ci this.writeUnsignedVarint32(value); 152ffe3c632Sopenharmony_ci return; 153ffe3c632Sopenharmony_ci } 154ffe3c632Sopenharmony_ci 155ffe3c632Sopenharmony_ci // Write nine bytes with a _signed_ right shift so we preserve the sign bit. 156ffe3c632Sopenharmony_ci for (var i = 0; i < 9; i++) { 157ffe3c632Sopenharmony_ci this.buffer_.push((value & 0x7f) | 0x80); 158ffe3c632Sopenharmony_ci value = value >> 7; 159ffe3c632Sopenharmony_ci } 160ffe3c632Sopenharmony_ci 161ffe3c632Sopenharmony_ci // The above loop writes out 63 bits, so the last byte is always the sign bit 162ffe3c632Sopenharmony_ci // which is always set for negative numbers. 163ffe3c632Sopenharmony_ci this.buffer_.push(1); 164ffe3c632Sopenharmony_ci}; 165ffe3c632Sopenharmony_ci 166ffe3c632Sopenharmony_ci 167ffe3c632Sopenharmony_ci/** 168ffe3c632Sopenharmony_ci * Encodes a 64-bit unsigned integer into its wire-format varint representation 169ffe3c632Sopenharmony_ci * and stores it in the buffer. Integers that are not representable in 64 bits 170ffe3c632Sopenharmony_ci * will be truncated. 171ffe3c632Sopenharmony_ci * @param {number} value The integer to convert. 172ffe3c632Sopenharmony_ci */ 173ffe3c632Sopenharmony_cijspb.BinaryEncoder.prototype.writeUnsignedVarint64 = function(value) { 174ffe3c632Sopenharmony_ci goog.asserts.assert(value == Math.floor(value)); 175ffe3c632Sopenharmony_ci goog.asserts.assert((value >= 0) && 176ffe3c632Sopenharmony_ci (value < jspb.BinaryConstants.TWO_TO_64)); 177ffe3c632Sopenharmony_ci jspb.utils.splitInt64(value); 178ffe3c632Sopenharmony_ci this.writeSplitVarint64(jspb.utils.split64Low, 179ffe3c632Sopenharmony_ci jspb.utils.split64High); 180ffe3c632Sopenharmony_ci}; 181ffe3c632Sopenharmony_ci 182ffe3c632Sopenharmony_ci 183ffe3c632Sopenharmony_ci/** 184ffe3c632Sopenharmony_ci * Encodes a 64-bit signed integer into its wire-format varint representation 185ffe3c632Sopenharmony_ci * and stores it in the buffer. Integers that are not representable in 64 bits 186ffe3c632Sopenharmony_ci * will be truncated. 187ffe3c632Sopenharmony_ci * @param {number} value The integer to convert. 188ffe3c632Sopenharmony_ci */ 189ffe3c632Sopenharmony_cijspb.BinaryEncoder.prototype.writeSignedVarint64 = function(value) { 190ffe3c632Sopenharmony_ci goog.asserts.assert(value == Math.floor(value)); 191ffe3c632Sopenharmony_ci goog.asserts.assert((value >= -jspb.BinaryConstants.TWO_TO_63) && 192ffe3c632Sopenharmony_ci (value < jspb.BinaryConstants.TWO_TO_63)); 193ffe3c632Sopenharmony_ci jspb.utils.splitInt64(value); 194ffe3c632Sopenharmony_ci this.writeSplitVarint64(jspb.utils.split64Low, 195ffe3c632Sopenharmony_ci jspb.utils.split64High); 196ffe3c632Sopenharmony_ci}; 197ffe3c632Sopenharmony_ci 198ffe3c632Sopenharmony_ci 199ffe3c632Sopenharmony_ci/** 200ffe3c632Sopenharmony_ci * Encodes a JavaScript integer into its wire-format, zigzag-encoded varint 201ffe3c632Sopenharmony_ci * representation and stores it in the buffer. 202ffe3c632Sopenharmony_ci * @param {number} value The integer to convert. 203ffe3c632Sopenharmony_ci */ 204ffe3c632Sopenharmony_cijspb.BinaryEncoder.prototype.writeZigzagVarint32 = function(value) { 205ffe3c632Sopenharmony_ci goog.asserts.assert(value == Math.floor(value)); 206ffe3c632Sopenharmony_ci goog.asserts.assert((value >= -jspb.BinaryConstants.TWO_TO_31) && 207ffe3c632Sopenharmony_ci (value < jspb.BinaryConstants.TWO_TO_31)); 208ffe3c632Sopenharmony_ci this.writeUnsignedVarint32(((value << 1) ^ (value >> 31)) >>> 0); 209ffe3c632Sopenharmony_ci}; 210ffe3c632Sopenharmony_ci 211ffe3c632Sopenharmony_ci 212ffe3c632Sopenharmony_ci/** 213ffe3c632Sopenharmony_ci * Encodes a JavaScript integer into its wire-format, zigzag-encoded varint 214ffe3c632Sopenharmony_ci * representation and stores it in the buffer. Integers not representable in 64 215ffe3c632Sopenharmony_ci * bits will be truncated. 216ffe3c632Sopenharmony_ci * @param {number} value The integer to convert. 217ffe3c632Sopenharmony_ci */ 218ffe3c632Sopenharmony_cijspb.BinaryEncoder.prototype.writeZigzagVarint64 = function(value) { 219ffe3c632Sopenharmony_ci goog.asserts.assert(value == Math.floor(value)); 220ffe3c632Sopenharmony_ci goog.asserts.assert((value >= -jspb.BinaryConstants.TWO_TO_63) && 221ffe3c632Sopenharmony_ci (value < jspb.BinaryConstants.TWO_TO_63)); 222ffe3c632Sopenharmony_ci jspb.utils.splitZigzag64(value); 223ffe3c632Sopenharmony_ci this.writeSplitVarint64(jspb.utils.split64Low, 224ffe3c632Sopenharmony_ci jspb.utils.split64High); 225ffe3c632Sopenharmony_ci}; 226ffe3c632Sopenharmony_ci 227ffe3c632Sopenharmony_ci 228ffe3c632Sopenharmony_ci/** 229ffe3c632Sopenharmony_ci * Encodes a JavaScript decimal string into its wire-format, zigzag-encoded 230ffe3c632Sopenharmony_ci * varint representation and stores it in the buffer. Integers not representable 231ffe3c632Sopenharmony_ci * in 64 bits will be truncated. 232ffe3c632Sopenharmony_ci * @param {string} value The integer to convert. 233ffe3c632Sopenharmony_ci */ 234ffe3c632Sopenharmony_cijspb.BinaryEncoder.prototype.writeZigzagVarint64String = function(value) { 235ffe3c632Sopenharmony_ci this.writeZigzagVarintHash64(jspb.utils.decimalStringToHash64(value)); 236ffe3c632Sopenharmony_ci}; 237ffe3c632Sopenharmony_ci 238ffe3c632Sopenharmony_ci 239ffe3c632Sopenharmony_ci/** 240ffe3c632Sopenharmony_ci * Writes a 64-bit hash string (8 characters @ 8 bits of data each) to the 241ffe3c632Sopenharmony_ci * buffer as a zigzag varint. 242ffe3c632Sopenharmony_ci * @param {string} hash The hash to write. 243ffe3c632Sopenharmony_ci */ 244ffe3c632Sopenharmony_cijspb.BinaryEncoder.prototype.writeZigzagVarintHash64 = function(hash) { 245ffe3c632Sopenharmony_ci var self = this; 246ffe3c632Sopenharmony_ci jspb.utils.splitHash64(hash); 247ffe3c632Sopenharmony_ci jspb.utils.toZigzag64( 248ffe3c632Sopenharmony_ci jspb.utils.split64Low, jspb.utils.split64High, function(lo, hi) { 249ffe3c632Sopenharmony_ci self.writeSplitVarint64(lo >>> 0, hi >>> 0); 250ffe3c632Sopenharmony_ci }); 251ffe3c632Sopenharmony_ci}; 252ffe3c632Sopenharmony_ci 253ffe3c632Sopenharmony_ci 254ffe3c632Sopenharmony_ci/** 255ffe3c632Sopenharmony_ci * Writes an 8-bit unsigned integer to the buffer. Numbers outside the range 256ffe3c632Sopenharmony_ci * [0,2^8) will be truncated. 257ffe3c632Sopenharmony_ci * @param {number} value The value to write. 258ffe3c632Sopenharmony_ci */ 259ffe3c632Sopenharmony_cijspb.BinaryEncoder.prototype.writeUint8 = function(value) { 260ffe3c632Sopenharmony_ci goog.asserts.assert(value == Math.floor(value)); 261ffe3c632Sopenharmony_ci goog.asserts.assert((value >= 0) && (value < 256)); 262ffe3c632Sopenharmony_ci this.buffer_.push((value >>> 0) & 0xFF); 263ffe3c632Sopenharmony_ci}; 264ffe3c632Sopenharmony_ci 265ffe3c632Sopenharmony_ci 266ffe3c632Sopenharmony_ci/** 267ffe3c632Sopenharmony_ci * Writes a 16-bit unsigned integer to the buffer. Numbers outside the 268ffe3c632Sopenharmony_ci * range [0,2^16) will be truncated. 269ffe3c632Sopenharmony_ci * @param {number} value The value to write. 270ffe3c632Sopenharmony_ci */ 271ffe3c632Sopenharmony_cijspb.BinaryEncoder.prototype.writeUint16 = function(value) { 272ffe3c632Sopenharmony_ci goog.asserts.assert(value == Math.floor(value)); 273ffe3c632Sopenharmony_ci goog.asserts.assert((value >= 0) && (value < 65536)); 274ffe3c632Sopenharmony_ci this.buffer_.push((value >>> 0) & 0xFF); 275ffe3c632Sopenharmony_ci this.buffer_.push((value >>> 8) & 0xFF); 276ffe3c632Sopenharmony_ci}; 277ffe3c632Sopenharmony_ci 278ffe3c632Sopenharmony_ci 279ffe3c632Sopenharmony_ci/** 280ffe3c632Sopenharmony_ci * Writes a 32-bit unsigned integer to the buffer. Numbers outside the 281ffe3c632Sopenharmony_ci * range [0,2^32) will be truncated. 282ffe3c632Sopenharmony_ci * @param {number} value The value to write. 283ffe3c632Sopenharmony_ci */ 284ffe3c632Sopenharmony_cijspb.BinaryEncoder.prototype.writeUint32 = function(value) { 285ffe3c632Sopenharmony_ci goog.asserts.assert(value == Math.floor(value)); 286ffe3c632Sopenharmony_ci goog.asserts.assert((value >= 0) && 287ffe3c632Sopenharmony_ci (value < jspb.BinaryConstants.TWO_TO_32)); 288ffe3c632Sopenharmony_ci this.buffer_.push((value >>> 0) & 0xFF); 289ffe3c632Sopenharmony_ci this.buffer_.push((value >>> 8) & 0xFF); 290ffe3c632Sopenharmony_ci this.buffer_.push((value >>> 16) & 0xFF); 291ffe3c632Sopenharmony_ci this.buffer_.push((value >>> 24) & 0xFF); 292ffe3c632Sopenharmony_ci}; 293ffe3c632Sopenharmony_ci 294ffe3c632Sopenharmony_ci 295ffe3c632Sopenharmony_ci/** 296ffe3c632Sopenharmony_ci * Writes a 64-bit unsigned integer to the buffer. Numbers outside the 297ffe3c632Sopenharmony_ci * range [0,2^64) will be truncated. 298ffe3c632Sopenharmony_ci * @param {number} value The value to write. 299ffe3c632Sopenharmony_ci */ 300ffe3c632Sopenharmony_cijspb.BinaryEncoder.prototype.writeUint64 = function(value) { 301ffe3c632Sopenharmony_ci goog.asserts.assert(value == Math.floor(value)); 302ffe3c632Sopenharmony_ci goog.asserts.assert((value >= 0) && 303ffe3c632Sopenharmony_ci (value < jspb.BinaryConstants.TWO_TO_64)); 304ffe3c632Sopenharmony_ci jspb.utils.splitUint64(value); 305ffe3c632Sopenharmony_ci this.writeUint32(jspb.utils.split64Low); 306ffe3c632Sopenharmony_ci this.writeUint32(jspb.utils.split64High); 307ffe3c632Sopenharmony_ci}; 308ffe3c632Sopenharmony_ci 309ffe3c632Sopenharmony_ci 310ffe3c632Sopenharmony_ci/** 311ffe3c632Sopenharmony_ci * Writes an 8-bit integer to the buffer. Numbers outside the range 312ffe3c632Sopenharmony_ci * [-2^7,2^7) will be truncated. 313ffe3c632Sopenharmony_ci * @param {number} value The value to write. 314ffe3c632Sopenharmony_ci */ 315ffe3c632Sopenharmony_cijspb.BinaryEncoder.prototype.writeInt8 = function(value) { 316ffe3c632Sopenharmony_ci goog.asserts.assert(value == Math.floor(value)); 317ffe3c632Sopenharmony_ci goog.asserts.assert((value >= -128) && (value < 128)); 318ffe3c632Sopenharmony_ci this.buffer_.push((value >>> 0) & 0xFF); 319ffe3c632Sopenharmony_ci}; 320ffe3c632Sopenharmony_ci 321ffe3c632Sopenharmony_ci 322ffe3c632Sopenharmony_ci/** 323ffe3c632Sopenharmony_ci * Writes a 16-bit integer to the buffer. Numbers outside the range 324ffe3c632Sopenharmony_ci * [-2^15,2^15) will be truncated. 325ffe3c632Sopenharmony_ci * @param {number} value The value to write. 326ffe3c632Sopenharmony_ci */ 327ffe3c632Sopenharmony_cijspb.BinaryEncoder.prototype.writeInt16 = function(value) { 328ffe3c632Sopenharmony_ci goog.asserts.assert(value == Math.floor(value)); 329ffe3c632Sopenharmony_ci goog.asserts.assert((value >= -32768) && (value < 32768)); 330ffe3c632Sopenharmony_ci this.buffer_.push((value >>> 0) & 0xFF); 331ffe3c632Sopenharmony_ci this.buffer_.push((value >>> 8) & 0xFF); 332ffe3c632Sopenharmony_ci}; 333ffe3c632Sopenharmony_ci 334ffe3c632Sopenharmony_ci 335ffe3c632Sopenharmony_ci/** 336ffe3c632Sopenharmony_ci * Writes a 32-bit integer to the buffer. Numbers outside the range 337ffe3c632Sopenharmony_ci * [-2^31,2^31) will be truncated. 338ffe3c632Sopenharmony_ci * @param {number} value The value to write. 339ffe3c632Sopenharmony_ci */ 340ffe3c632Sopenharmony_cijspb.BinaryEncoder.prototype.writeInt32 = function(value) { 341ffe3c632Sopenharmony_ci goog.asserts.assert(value == Math.floor(value)); 342ffe3c632Sopenharmony_ci goog.asserts.assert((value >= -jspb.BinaryConstants.TWO_TO_31) && 343ffe3c632Sopenharmony_ci (value < jspb.BinaryConstants.TWO_TO_31)); 344ffe3c632Sopenharmony_ci this.buffer_.push((value >>> 0) & 0xFF); 345ffe3c632Sopenharmony_ci this.buffer_.push((value >>> 8) & 0xFF); 346ffe3c632Sopenharmony_ci this.buffer_.push((value >>> 16) & 0xFF); 347ffe3c632Sopenharmony_ci this.buffer_.push((value >>> 24) & 0xFF); 348ffe3c632Sopenharmony_ci}; 349ffe3c632Sopenharmony_ci 350ffe3c632Sopenharmony_ci 351ffe3c632Sopenharmony_ci/** 352ffe3c632Sopenharmony_ci * Writes a 64-bit integer to the buffer. Numbers outside the range 353ffe3c632Sopenharmony_ci * [-2^63,2^63) will be truncated. 354ffe3c632Sopenharmony_ci * @param {number} value The value to write. 355ffe3c632Sopenharmony_ci */ 356ffe3c632Sopenharmony_cijspb.BinaryEncoder.prototype.writeInt64 = function(value) { 357ffe3c632Sopenharmony_ci goog.asserts.assert(value == Math.floor(value)); 358ffe3c632Sopenharmony_ci goog.asserts.assert((value >= -jspb.BinaryConstants.TWO_TO_63) && 359ffe3c632Sopenharmony_ci (value < jspb.BinaryConstants.TWO_TO_63)); 360ffe3c632Sopenharmony_ci jspb.utils.splitInt64(value); 361ffe3c632Sopenharmony_ci this.writeSplitFixed64(jspb.utils.split64Low, jspb.utils.split64High); 362ffe3c632Sopenharmony_ci}; 363ffe3c632Sopenharmony_ci 364ffe3c632Sopenharmony_ci 365ffe3c632Sopenharmony_ci/** 366ffe3c632Sopenharmony_ci * Writes a 64-bit integer decimal strings to the buffer. Numbers outside the 367ffe3c632Sopenharmony_ci * range [-2^63,2^63) will be truncated. 368ffe3c632Sopenharmony_ci * @param {string} value The value to write. 369ffe3c632Sopenharmony_ci */ 370ffe3c632Sopenharmony_cijspb.BinaryEncoder.prototype.writeInt64String = function(value) { 371ffe3c632Sopenharmony_ci goog.asserts.assert(value == Math.floor(value)); 372ffe3c632Sopenharmony_ci goog.asserts.assert((+value >= -jspb.BinaryConstants.TWO_TO_63) && 373ffe3c632Sopenharmony_ci (+value < jspb.BinaryConstants.TWO_TO_63)); 374ffe3c632Sopenharmony_ci jspb.utils.splitHash64(jspb.utils.decimalStringToHash64(value)); 375ffe3c632Sopenharmony_ci this.writeSplitFixed64(jspb.utils.split64Low, jspb.utils.split64High); 376ffe3c632Sopenharmony_ci}; 377ffe3c632Sopenharmony_ci 378ffe3c632Sopenharmony_ci 379ffe3c632Sopenharmony_ci/** 380ffe3c632Sopenharmony_ci * Writes a single-precision floating point value to the buffer. Numbers 381ffe3c632Sopenharmony_ci * requiring more than 32 bits of precision will be truncated. 382ffe3c632Sopenharmony_ci * @param {number} value The value to write. 383ffe3c632Sopenharmony_ci */ 384ffe3c632Sopenharmony_cijspb.BinaryEncoder.prototype.writeFloat = function(value) { 385ffe3c632Sopenharmony_ci goog.asserts.assert( 386ffe3c632Sopenharmony_ci value === Infinity || value === -Infinity || isNaN(value) || 387ffe3c632Sopenharmony_ci ((value >= -jspb.BinaryConstants.FLOAT32_MAX) && 388ffe3c632Sopenharmony_ci (value <= jspb.BinaryConstants.FLOAT32_MAX))); 389ffe3c632Sopenharmony_ci jspb.utils.splitFloat32(value); 390ffe3c632Sopenharmony_ci this.writeUint32(jspb.utils.split64Low); 391ffe3c632Sopenharmony_ci}; 392ffe3c632Sopenharmony_ci 393ffe3c632Sopenharmony_ci 394ffe3c632Sopenharmony_ci/** 395ffe3c632Sopenharmony_ci * Writes a double-precision floating point value to the buffer. As this is 396ffe3c632Sopenharmony_ci * the native format used by JavaScript, no precision will be lost. 397ffe3c632Sopenharmony_ci * @param {number} value The value to write. 398ffe3c632Sopenharmony_ci */ 399ffe3c632Sopenharmony_cijspb.BinaryEncoder.prototype.writeDouble = function(value) { 400ffe3c632Sopenharmony_ci goog.asserts.assert( 401ffe3c632Sopenharmony_ci value === Infinity || value === -Infinity || isNaN(value) || 402ffe3c632Sopenharmony_ci ((value >= -jspb.BinaryConstants.FLOAT64_MAX) && 403ffe3c632Sopenharmony_ci (value <= jspb.BinaryConstants.FLOAT64_MAX))); 404ffe3c632Sopenharmony_ci jspb.utils.splitFloat64(value); 405ffe3c632Sopenharmony_ci this.writeUint32(jspb.utils.split64Low); 406ffe3c632Sopenharmony_ci this.writeUint32(jspb.utils.split64High); 407ffe3c632Sopenharmony_ci}; 408ffe3c632Sopenharmony_ci 409ffe3c632Sopenharmony_ci 410ffe3c632Sopenharmony_ci/** 411ffe3c632Sopenharmony_ci * Writes a boolean value to the buffer as a varint. We allow numbers as input 412ffe3c632Sopenharmony_ci * because the JSPB code generator uses 0/1 instead of true/false to save space 413ffe3c632Sopenharmony_ci * in the string representation of the proto. 414ffe3c632Sopenharmony_ci * @param {boolean|number} value The value to write. 415ffe3c632Sopenharmony_ci */ 416ffe3c632Sopenharmony_cijspb.BinaryEncoder.prototype.writeBool = function(value) { 417ffe3c632Sopenharmony_ci goog.asserts.assert(typeof value === 'boolean' || typeof value === 'number'); 418ffe3c632Sopenharmony_ci this.buffer_.push(value ? 1 : 0); 419ffe3c632Sopenharmony_ci}; 420ffe3c632Sopenharmony_ci 421ffe3c632Sopenharmony_ci 422ffe3c632Sopenharmony_ci/** 423ffe3c632Sopenharmony_ci * Writes an enum value to the buffer as a varint. 424ffe3c632Sopenharmony_ci * @param {number} value The value to write. 425ffe3c632Sopenharmony_ci */ 426ffe3c632Sopenharmony_cijspb.BinaryEncoder.prototype.writeEnum = function(value) { 427ffe3c632Sopenharmony_ci goog.asserts.assert(value == Math.floor(value)); 428ffe3c632Sopenharmony_ci goog.asserts.assert((value >= -jspb.BinaryConstants.TWO_TO_31) && 429ffe3c632Sopenharmony_ci (value < jspb.BinaryConstants.TWO_TO_31)); 430ffe3c632Sopenharmony_ci this.writeSignedVarint32(value); 431ffe3c632Sopenharmony_ci}; 432ffe3c632Sopenharmony_ci 433ffe3c632Sopenharmony_ci 434ffe3c632Sopenharmony_ci/** 435ffe3c632Sopenharmony_ci * Writes an arbitrary byte array to the buffer. 436ffe3c632Sopenharmony_ci * @param {!Uint8Array} bytes The array of bytes to write. 437ffe3c632Sopenharmony_ci */ 438ffe3c632Sopenharmony_cijspb.BinaryEncoder.prototype.writeBytes = function(bytes) { 439ffe3c632Sopenharmony_ci this.buffer_.push.apply(this.buffer_, bytes); 440ffe3c632Sopenharmony_ci}; 441ffe3c632Sopenharmony_ci 442ffe3c632Sopenharmony_ci 443ffe3c632Sopenharmony_ci/** 444ffe3c632Sopenharmony_ci * Writes a 64-bit hash string (8 characters @ 8 bits of data each) to the 445ffe3c632Sopenharmony_ci * buffer as a varint. 446ffe3c632Sopenharmony_ci * @param {string} hash The hash to write. 447ffe3c632Sopenharmony_ci */ 448ffe3c632Sopenharmony_cijspb.BinaryEncoder.prototype.writeVarintHash64 = function(hash) { 449ffe3c632Sopenharmony_ci jspb.utils.splitHash64(hash); 450ffe3c632Sopenharmony_ci this.writeSplitVarint64(jspb.utils.split64Low, 451ffe3c632Sopenharmony_ci jspb.utils.split64High); 452ffe3c632Sopenharmony_ci}; 453ffe3c632Sopenharmony_ci 454ffe3c632Sopenharmony_ci 455ffe3c632Sopenharmony_ci/** 456ffe3c632Sopenharmony_ci * Writes a 64-bit hash string (8 characters @ 8 bits of data each) to the 457ffe3c632Sopenharmony_ci * buffer as a fixed64. 458ffe3c632Sopenharmony_ci * @param {string} hash The hash to write. 459ffe3c632Sopenharmony_ci */ 460ffe3c632Sopenharmony_cijspb.BinaryEncoder.prototype.writeFixedHash64 = function(hash) { 461ffe3c632Sopenharmony_ci jspb.utils.splitHash64(hash); 462ffe3c632Sopenharmony_ci this.writeUint32(jspb.utils.split64Low); 463ffe3c632Sopenharmony_ci this.writeUint32(jspb.utils.split64High); 464ffe3c632Sopenharmony_ci}; 465ffe3c632Sopenharmony_ci 466ffe3c632Sopenharmony_ci 467ffe3c632Sopenharmony_ci/** 468ffe3c632Sopenharmony_ci * Writes a UTF16 Javascript string to the buffer encoded as UTF8. 469ffe3c632Sopenharmony_ci * TODO(aappleby): Add support for surrogate pairs, reject unpaired surrogates. 470ffe3c632Sopenharmony_ci * @param {string} value The string to write. 471ffe3c632Sopenharmony_ci * @return {number} The number of bytes used to encode the string. 472ffe3c632Sopenharmony_ci */ 473ffe3c632Sopenharmony_cijspb.BinaryEncoder.prototype.writeString = function(value) { 474ffe3c632Sopenharmony_ci var oldLength = this.buffer_.length; 475ffe3c632Sopenharmony_ci 476ffe3c632Sopenharmony_ci for (var i = 0; i < value.length; i++) { 477ffe3c632Sopenharmony_ci 478ffe3c632Sopenharmony_ci var c = value.charCodeAt(i); 479ffe3c632Sopenharmony_ci 480ffe3c632Sopenharmony_ci if (c < 128) { 481ffe3c632Sopenharmony_ci this.buffer_.push(c); 482ffe3c632Sopenharmony_ci } else if (c < 2048) { 483ffe3c632Sopenharmony_ci this.buffer_.push((c >> 6) | 192); 484ffe3c632Sopenharmony_ci this.buffer_.push((c & 63) | 128); 485ffe3c632Sopenharmony_ci } else if (c < 65536) { 486ffe3c632Sopenharmony_ci // Look for surrogates 487ffe3c632Sopenharmony_ci if (c >= 0xD800 && c <= 0xDBFF && i + 1 < value.length) { 488ffe3c632Sopenharmony_ci var second = value.charCodeAt(i + 1); 489ffe3c632Sopenharmony_ci if (second >= 0xDC00 && second <= 0xDFFF) { // low surrogate 490ffe3c632Sopenharmony_ci // http://mathiasbynens.be/notes/javascript-encoding#surrogate-formulae 491ffe3c632Sopenharmony_ci c = (c - 0xD800) * 0x400 + second - 0xDC00 + 0x10000; 492ffe3c632Sopenharmony_ci 493ffe3c632Sopenharmony_ci this.buffer_.push((c >> 18) | 240); 494ffe3c632Sopenharmony_ci this.buffer_.push(((c >> 12) & 63 ) | 128); 495ffe3c632Sopenharmony_ci this.buffer_.push(((c >> 6) & 63) | 128); 496ffe3c632Sopenharmony_ci this.buffer_.push((c & 63) | 128); 497ffe3c632Sopenharmony_ci i++; 498ffe3c632Sopenharmony_ci } 499ffe3c632Sopenharmony_ci } 500ffe3c632Sopenharmony_ci else { 501ffe3c632Sopenharmony_ci this.buffer_.push((c >> 12) | 224); 502ffe3c632Sopenharmony_ci this.buffer_.push(((c >> 6) & 63) | 128); 503ffe3c632Sopenharmony_ci this.buffer_.push((c & 63) | 128); 504ffe3c632Sopenharmony_ci } 505ffe3c632Sopenharmony_ci } 506ffe3c632Sopenharmony_ci } 507ffe3c632Sopenharmony_ci 508ffe3c632Sopenharmony_ci var length = this.buffer_.length - oldLength; 509ffe3c632Sopenharmony_ci return length; 510ffe3c632Sopenharmony_ci}; 511