]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - apps/tidep0084.git/blob - example/iot-gateway/node_modules/bytebuffer/dist/bytebuffer.js
Initial commit
[apps/tidep0084.git] / example / iot-gateway / node_modules / bytebuffer / dist / bytebuffer.js
1 /*
2  Copyright 2013-2014 Daniel Wirtz <dcode@dcode.io>
4  Licensed under the Apache License, Version 2.0 (the "License");
5  you may not use this file except in compliance with the License.
6  You may obtain a copy of the License at
8  http://www.apache.org/licenses/LICENSE-2.0
10  Unless required by applicable law or agreed to in writing, software
11  distributed under the License is distributed on an "AS IS" BASIS,
12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  See the License for the specific language governing permissions and
14  limitations under the License.
15  */
17 /**
18  * @license bytebuffer.js (c) 2015 Daniel Wirtz <dcode@dcode.io>
19  * Backing buffer: ArrayBuffer, Accessor: Uint8Array
20  * Released under the Apache License, Version 2.0
21  * see: https://github.com/dcodeIO/bytebuffer.js for details
22  */
23 (function(global, factory) {
25     /* AMD */ if (typeof define === 'function' && define["amd"])
26         define(["long"], factory);
27     /* CommonJS */ else if (typeof require === 'function' && typeof module === "object" && module && module["exports"])
28         module['exports'] = (function() {
29             var Long; try { Long = require("long"); } catch (e) {}
30             return factory(Long);
31         })();
32     /* Global */ else
33         (global["dcodeIO"] = global["dcodeIO"] || {})["ByteBuffer"] = factory(global["dcodeIO"]["Long"]);
35 })(this, function(Long) {
36     "use strict";
38     /**
39      * Constructs a new ByteBuffer.
40      * @class The swiss army knife for binary data in JavaScript.
41      * @exports ByteBuffer
42      * @constructor
43      * @param {number=} capacity Initial capacity. Defaults to {@link ByteBuffer.DEFAULT_CAPACITY}.
44      * @param {boolean=} littleEndian Whether to use little or big endian byte order. Defaults to
45      *  {@link ByteBuffer.DEFAULT_ENDIAN}.
46      * @param {boolean=} noAssert Whether to skip assertions of offsets and values. Defaults to
47      *  {@link ByteBuffer.DEFAULT_NOASSERT}.
48      * @expose
49      */
50     var ByteBuffer = function(capacity, littleEndian, noAssert) {
51         if (typeof capacity === 'undefined')
52             capacity = ByteBuffer.DEFAULT_CAPACITY;
53         if (typeof littleEndian === 'undefined')
54             littleEndian = ByteBuffer.DEFAULT_ENDIAN;
55         if (typeof noAssert === 'undefined')
56             noAssert = ByteBuffer.DEFAULT_NOASSERT;
57         if (!noAssert) {
58             capacity = capacity | 0;
59             if (capacity < 0)
60                 throw RangeError("Illegal capacity");
61             littleEndian = !!littleEndian;
62             noAssert = !!noAssert;
63         }
65         /**
66          * Backing ArrayBuffer.
67          * @type {!ArrayBuffer}
68          * @expose
69          */
70         this.buffer = capacity === 0 ? EMPTY_BUFFER : new ArrayBuffer(capacity);
72         /**
73          * Uint8Array utilized to manipulate the backing buffer. Becomes `null` if the backing buffer has a capacity of `0`.
74          * @type {?Uint8Array}
75          * @expose
76          */
77         this.view = capacity === 0 ? null : new Uint8Array(this.buffer);
79         /**
80          * Absolute read/write offset.
81          * @type {number}
82          * @expose
83          * @see ByteBuffer#flip
84          * @see ByteBuffer#clear
85          */
86         this.offset = 0;
88         /**
89          * Marked offset.
90          * @type {number}
91          * @expose
92          * @see ByteBuffer#mark
93          * @see ByteBuffer#reset
94          */
95         this.markedOffset = -1;
97         /**
98          * Absolute limit of the contained data. Set to the backing buffer's capacity upon allocation.
99          * @type {number}
100          * @expose
101          * @see ByteBuffer#flip
102          * @see ByteBuffer#clear
103          */
104         this.limit = capacity;
106         /**
107          * Whether to use little endian byte order, defaults to `false` for big endian.
108          * @type {boolean}
109          * @expose
110          */
111         this.littleEndian = littleEndian;
113         /**
114          * Whether to skip assertions of offsets and values, defaults to `false`.
115          * @type {boolean}
116          * @expose
117          */
118         this.noAssert = noAssert;
119     };
121     /**
122      * ByteBuffer version.
123      * @type {string}
124      * @const
125      * @expose
126      */
127     ByteBuffer.VERSION = "5.0.1";
129     /**
130      * Little endian constant that can be used instead of its boolean value. Evaluates to `true`.
131      * @type {boolean}
132      * @const
133      * @expose
134      */
135     ByteBuffer.LITTLE_ENDIAN = true;
137     /**
138      * Big endian constant that can be used instead of its boolean value. Evaluates to `false`.
139      * @type {boolean}
140      * @const
141      * @expose
142      */
143     ByteBuffer.BIG_ENDIAN = false;
145     /**
146      * Default initial capacity of `16`.
147      * @type {number}
148      * @expose
149      */
150     ByteBuffer.DEFAULT_CAPACITY = 16;
152     /**
153      * Default endianess of `false` for big endian.
154      * @type {boolean}
155      * @expose
156      */
157     ByteBuffer.DEFAULT_ENDIAN = ByteBuffer.BIG_ENDIAN;
159     /**
160      * Default no assertions flag of `false`.
161      * @type {boolean}
162      * @expose
163      */
164     ByteBuffer.DEFAULT_NOASSERT = false;
166     /**
167      * A `Long` class for representing a 64-bit two's-complement integer value. May be `null` if Long.js has not been loaded
168      *  and int64 support is not available.
169      * @type {?Long}
170      * @const
171      * @see https://github.com/dcodeIO/long.js
172      * @expose
173      */
174     ByteBuffer.Long = Long || null;
176     /**
177      * @alias ByteBuffer.prototype
178      * @inner
179      */
180     var ByteBufferPrototype = ByteBuffer.prototype;
182     /**
183      * An indicator used to reliably determine if an object is a ByteBuffer or not.
184      * @type {boolean}
185      * @const
186      * @expose
187      * @private
188      */
189     ByteBufferPrototype.__isByteBuffer__;
191     Object.defineProperty(ByteBufferPrototype, "__isByteBuffer__", {
192         value: true,
193         enumerable: false,
194         configurable: false
195     });
197     // helpers
199     /**
200      * @type {!ArrayBuffer}
201      * @inner
202      */
203     var EMPTY_BUFFER = new ArrayBuffer(0);
205     /**
206      * String.fromCharCode reference for compile-time renaming.
207      * @type {function(...number):string}
208      * @inner
209      */
210     var stringFromCharCode = String.fromCharCode;
212     /**
213      * Creates a source function for a string.
214      * @param {string} s String to read from
215      * @returns {function():number|null} Source function returning the next char code respectively `null` if there are
216      *  no more characters left.
217      * @throws {TypeError} If the argument is invalid
218      * @inner
219      */
220     function stringSource(s) {
221         var i=0; return function() {
222             return i < s.length ? s.charCodeAt(i++) : null;
223         };
224     }
226     /**
227      * Creates a destination function for a string.
228      * @returns {function(number=):undefined|string} Destination function successively called with the next char code.
229      *  Returns the final string when called without arguments.
230      * @inner
231      */
232     function stringDestination() {
233         var cs = [], ps = []; return function() {
234             if (arguments.length === 0)
235                 return ps.join('')+stringFromCharCode.apply(String, cs);
236             if (cs.length + arguments.length > 1024)
237                 ps.push(stringFromCharCode.apply(String, cs)),
238                     cs.length = 0;
239             Array.prototype.push.apply(cs, arguments);
240         };
241     }
243     /**
244      * Gets the accessor type.
245      * @returns {Function} `Buffer` under node.js, `Uint8Array` respectively `DataView` in the browser (classes)
246      * @expose
247      */
248     ByteBuffer.accessor = function() {
249         return Uint8Array;
250     };
251     /**
252      * Allocates a new ByteBuffer backed by a buffer of the specified capacity.
253      * @param {number=} capacity Initial capacity. Defaults to {@link ByteBuffer.DEFAULT_CAPACITY}.
254      * @param {boolean=} littleEndian Whether to use little or big endian byte order. Defaults to
255      *  {@link ByteBuffer.DEFAULT_ENDIAN}.
256      * @param {boolean=} noAssert Whether to skip assertions of offsets and values. Defaults to
257      *  {@link ByteBuffer.DEFAULT_NOASSERT}.
258      * @returns {!ByteBuffer}
259      * @expose
260      */
261     ByteBuffer.allocate = function(capacity, littleEndian, noAssert) {
262         return new ByteBuffer(capacity, littleEndian, noAssert);
263     };
265     /**
266      * Concatenates multiple ByteBuffers into one.
267      * @param {!Array.<!ByteBuffer|!ArrayBuffer|!Uint8Array|string>} buffers Buffers to concatenate
268      * @param {(string|boolean)=} encoding String encoding if `buffers` contains a string ("base64", "hex", "binary",
269      *  defaults to "utf8")
270      * @param {boolean=} littleEndian Whether to use little or big endian byte order for the resulting ByteBuffer. Defaults
271      *  to {@link ByteBuffer.DEFAULT_ENDIAN}.
272      * @param {boolean=} noAssert Whether to skip assertions of offsets and values for the resulting ByteBuffer. Defaults to
273      *  {@link ByteBuffer.DEFAULT_NOASSERT}.
274      * @returns {!ByteBuffer} Concatenated ByteBuffer
275      * @expose
276      */
277     ByteBuffer.concat = function(buffers, encoding, littleEndian, noAssert) {
278         if (typeof encoding === 'boolean' || typeof encoding !== 'string') {
279             noAssert = littleEndian;
280             littleEndian = encoding;
281             encoding = undefined;
282         }
283         var capacity = 0;
284         for (var i=0, k=buffers.length, length; i<k; ++i) {
285             if (!ByteBuffer.isByteBuffer(buffers[i]))
286                 buffers[i] = ByteBuffer.wrap(buffers[i], encoding);
287             length = buffers[i].limit - buffers[i].offset;
288             if (length > 0) capacity += length;
289         }
290         if (capacity === 0)
291             return new ByteBuffer(0, littleEndian, noAssert);
292         var bb = new ByteBuffer(capacity, littleEndian, noAssert),
293             bi;
294         i=0; while (i<k) {
295             bi = buffers[i++];
296             length = bi.limit - bi.offset;
297             if (length <= 0) continue;
298             bb.view.set(bi.view.subarray(bi.offset, bi.limit), bb.offset);
299             bb.offset += length;
300         }
301         bb.limit = bb.offset;
302         bb.offset = 0;
303         return bb;
304     };
306     /**
307      * Tests if the specified type is a ByteBuffer.
308      * @param {*} bb ByteBuffer to test
309      * @returns {boolean} `true` if it is a ByteBuffer, otherwise `false`
310      * @expose
311      */
312     ByteBuffer.isByteBuffer = function(bb) {
313         return (bb && bb["__isByteBuffer__"]) === true;
314     };
315     /**
316      * Gets the backing buffer type.
317      * @returns {Function} `Buffer` under node.js, `ArrayBuffer` in the browser (classes)
318      * @expose
319      */
320     ByteBuffer.type = function() {
321         return ArrayBuffer;
322     };
323     /**
324      * Wraps a buffer or a string. Sets the allocated ByteBuffer's {@link ByteBuffer#offset} to `0` and its
325      *  {@link ByteBuffer#limit} to the length of the wrapped data.
326      * @param {!ByteBuffer|!ArrayBuffer|!Uint8Array|string|!Array.<number>} buffer Anything that can be wrapped
327      * @param {(string|boolean)=} encoding String encoding if `buffer` is a string ("base64", "hex", "binary", defaults to
328      *  "utf8")
329      * @param {boolean=} littleEndian Whether to use little or big endian byte order. Defaults to
330      *  {@link ByteBuffer.DEFAULT_ENDIAN}.
331      * @param {boolean=} noAssert Whether to skip assertions of offsets and values. Defaults to
332      *  {@link ByteBuffer.DEFAULT_NOASSERT}.
333      * @returns {!ByteBuffer} A ByteBuffer wrapping `buffer`
334      * @expose
335      */
336     ByteBuffer.wrap = function(buffer, encoding, littleEndian, noAssert) {
337         if (typeof encoding !== 'string') {
338             noAssert = littleEndian;
339             littleEndian = encoding;
340             encoding = undefined;
341         }
342         if (typeof buffer === 'string') {
343             if (typeof encoding === 'undefined')
344                 encoding = "utf8";
345             switch (encoding) {
346                 case "base64":
347                     return ByteBuffer.fromBase64(buffer, littleEndian);
348                 case "hex":
349                     return ByteBuffer.fromHex(buffer, littleEndian);
350                 case "binary":
351                     return ByteBuffer.fromBinary(buffer, littleEndian);
352                 case "utf8":
353                     return ByteBuffer.fromUTF8(buffer, littleEndian);
354                 case "debug":
355                     return ByteBuffer.fromDebug(buffer, littleEndian);
356                 default:
357                     throw Error("Unsupported encoding: "+encoding);
358             }
359         }
360         if (buffer === null || typeof buffer !== 'object')
361             throw TypeError("Illegal buffer");
362         var bb;
363         if (ByteBuffer.isByteBuffer(buffer)) {
364             bb = ByteBufferPrototype.clone.call(buffer);
365             bb.markedOffset = -1;
366             return bb;
367         }
368         if (buffer instanceof Uint8Array) { // Extract ArrayBuffer from Uint8Array
369             bb = new ByteBuffer(0, littleEndian, noAssert);
370             if (buffer.length > 0) { // Avoid references to more than one EMPTY_BUFFER
371                 bb.buffer = buffer.buffer;
372                 bb.offset = buffer.byteOffset;
373                 bb.limit = buffer.byteOffset + buffer.byteLength;
374                 bb.view = new Uint8Array(buffer.buffer);
375             }
376         } else if (buffer instanceof ArrayBuffer) { // Reuse ArrayBuffer
377             bb = new ByteBuffer(0, littleEndian, noAssert);
378             if (buffer.byteLength > 0) {
379                 bb.buffer = buffer;
380                 bb.offset = 0;
381                 bb.limit = buffer.byteLength;
382                 bb.view = buffer.byteLength > 0 ? new Uint8Array(buffer) : null;
383             }
384         } else if (Object.prototype.toString.call(buffer) === "[object Array]") { // Create from octets
385             bb = new ByteBuffer(buffer.length, littleEndian, noAssert);
386             bb.limit = buffer.length;
387             for (var i=0; i<buffer.length; ++i)
388                 bb.view[i] = buffer[i];
389         } else
390             throw TypeError("Illegal buffer"); // Otherwise fail
391         return bb;
392     };
394     /**
395      * Writes the array as a bitset.
396      * @param {Array<boolean>} value Array of booleans to write
397      * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by `length` if omitted.
398      * @returns {!ByteBuffer}
399      * @expose
400      */
401     ByteBufferPrototype.writeBitSet = function(value, offset) {
402       var relative = typeof offset === 'undefined';
403       if (relative) offset = this.offset;
404       if (!this.noAssert) {
405         if (!(value instanceof Array))
406           throw TypeError("Illegal BitSet: Not an array");
407         if (typeof offset !== 'number' || offset % 1 !== 0)
408             throw TypeError("Illegal offset: "+offset+" (not an integer)");
409         offset >>>= 0;
410         if (offset < 0 || offset + 0 > this.buffer.byteLength)
411             throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength);
412       }
414       var start = offset,
415           bits = value.length,
416           bytes = (bits >> 3),
417           bit = 0,
418           k;
420       offset += this.writeVarint32(bits,offset);
422       while(bytes--) {
423         k = (!!value[bit++] & 1) |
424             ((!!value[bit++] & 1) << 1) |
425             ((!!value[bit++] & 1) << 2) |
426             ((!!value[bit++] & 1) << 3) |
427             ((!!value[bit++] & 1) << 4) |
428             ((!!value[bit++] & 1) << 5) |
429             ((!!value[bit++] & 1) << 6) |
430             ((!!value[bit++] & 1) << 7);
431         this.writeByte(k,offset++);
432       }
434       if(bit < bits) {
435         var m = 0; k = 0;
436         while(bit < bits) k = k | ((!!value[bit++] & 1) << (m++));
437         this.writeByte(k,offset++);
438       }
440       if (relative) {
441         this.offset = offset;
442         return this;
443       }
444       return offset - start;
445     }
447     /**
448      * Reads a BitSet as an array of booleans.
449      * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by `length` if omitted.
450      * @returns {Array<boolean>
451      * @expose
452      */
453     ByteBufferPrototype.readBitSet = function(offset) {
454       var relative = typeof offset === 'undefined';
455       if (relative) offset = this.offset;
457       var ret = this.readVarint32(offset),
458           bits = ret.value,
459           bytes = (bits >> 3),
460           bit = 0,
461           value = [],
462           k;
464       offset += ret.length;
466       while(bytes--) {
467         k = this.readByte(offset++);
468         value[bit++] = !!(k & 0x01);
469         value[bit++] = !!(k & 0x02);
470         value[bit++] = !!(k & 0x04);
471         value[bit++] = !!(k & 0x08);
472         value[bit++] = !!(k & 0x10);
473         value[bit++] = !!(k & 0x20);
474         value[bit++] = !!(k & 0x40);
475         value[bit++] = !!(k & 0x80);
476       }
478       if(bit < bits) {
479         var m = 0;
480         k = this.readByte(offset++);
481         while(bit < bits) value[bit++] = !!((k >> (m++)) & 1);
482       }
484       if (relative) {
485         this.offset = offset;
486       }
487       return value;
488     }
489     /**
490      * Reads the specified number of bytes.
491      * @param {number} length Number of bytes to read
492      * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by `length` if omitted.
493      * @returns {!ByteBuffer}
494      * @expose
495      */
496     ByteBufferPrototype.readBytes = function(length, offset) {
497         var relative = typeof offset === 'undefined';
498         if (relative) offset = this.offset;
499         if (!this.noAssert) {
500             if (typeof offset !== 'number' || offset % 1 !== 0)
501                 throw TypeError("Illegal offset: "+offset+" (not an integer)");
502             offset >>>= 0;
503             if (offset < 0 || offset + length > this.buffer.byteLength)
504                 throw RangeError("Illegal offset: 0 <= "+offset+" (+"+length+") <= "+this.buffer.byteLength);
505         }
506         var slice = this.slice(offset, offset + length);
507         if (relative) this.offset += length;
508         return slice;
509     };
511     /**
512      * Writes a payload of bytes. This is an alias of {@link ByteBuffer#append}.
513      * @function
514      * @param {!ByteBuffer|!ArrayBuffer|!Uint8Array|string} source Data to write. If `source` is a ByteBuffer, its offsets
515      *  will be modified according to the performed read operation.
516      * @param {(string|number)=} encoding Encoding if `data` is a string ("base64", "hex", "binary", defaults to "utf8")
517      * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by the number of bytes
518      *  written if omitted.
519      * @returns {!ByteBuffer} this
520      * @expose
521      */
522     ByteBufferPrototype.writeBytes = ByteBufferPrototype.append;
524     // types/ints/int8
526     /**
527      * Writes an 8bit signed integer.
528      * @param {number} value Value to write
529      * @param {number=} offset Offset to write to. Will use and advance {@link ByteBuffer#offset} by `1` if omitted.
530      * @returns {!ByteBuffer} this
531      * @expose
532      */
533     ByteBufferPrototype.writeInt8 = function(value, offset) {
534         var relative = typeof offset === 'undefined';
535         if (relative) offset = this.offset;
536         if (!this.noAssert) {
537             if (typeof value !== 'number' || value % 1 !== 0)
538                 throw TypeError("Illegal value: "+value+" (not an integer)");
539             value |= 0;
540             if (typeof offset !== 'number' || offset % 1 !== 0)
541                 throw TypeError("Illegal offset: "+offset+" (not an integer)");
542             offset >>>= 0;
543             if (offset < 0 || offset + 0 > this.buffer.byteLength)
544                 throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength);
545         }
546         offset += 1;
547         var capacity0 = this.buffer.byteLength;
548         if (offset > capacity0)
549             this.resize((capacity0 *= 2) > offset ? capacity0 : offset);
550         offset -= 1;
551         this.view[offset] = value;
552         if (relative) this.offset += 1;
553         return this;
554     };
556     /**
557      * Writes an 8bit signed integer. This is an alias of {@link ByteBuffer#writeInt8}.
558      * @function
559      * @param {number} value Value to write
560      * @param {number=} offset Offset to write to. Will use and advance {@link ByteBuffer#offset} by `1` if omitted.
561      * @returns {!ByteBuffer} this
562      * @expose
563      */
564     ByteBufferPrototype.writeByte = ByteBufferPrototype.writeInt8;
566     /**
567      * Reads an 8bit signed integer.
568      * @param {number=} offset Offset to read from. Will use and advance {@link ByteBuffer#offset} by `1` if omitted.
569      * @returns {number} Value read
570      * @expose
571      */
572     ByteBufferPrototype.readInt8 = function(offset) {
573         var relative = typeof offset === 'undefined';
574         if (relative) offset = this.offset;
575         if (!this.noAssert) {
576             if (typeof offset !== 'number' || offset % 1 !== 0)
577                 throw TypeError("Illegal offset: "+offset+" (not an integer)");
578             offset >>>= 0;
579             if (offset < 0 || offset + 1 > this.buffer.byteLength)
580                 throw RangeError("Illegal offset: 0 <= "+offset+" (+"+1+") <= "+this.buffer.byteLength);
581         }
582         var value = this.view[offset];
583         if ((value & 0x80) === 0x80) value = -(0xFF - value + 1); // Cast to signed
584         if (relative) this.offset += 1;
585         return value;
586     };
588     /**
589      * Reads an 8bit signed integer. This is an alias of {@link ByteBuffer#readInt8}.
590      * @function
591      * @param {number=} offset Offset to read from. Will use and advance {@link ByteBuffer#offset} by `1` if omitted.
592      * @returns {number} Value read
593      * @expose
594      */
595     ByteBufferPrototype.readByte = ByteBufferPrototype.readInt8;
597     /**
598      * Writes an 8bit unsigned integer.
599      * @param {number} value Value to write
600      * @param {number=} offset Offset to write to. Will use and advance {@link ByteBuffer#offset} by `1` if omitted.
601      * @returns {!ByteBuffer} this
602      * @expose
603      */
604     ByteBufferPrototype.writeUint8 = function(value, offset) {
605         var relative = typeof offset === 'undefined';
606         if (relative) offset = this.offset;
607         if (!this.noAssert) {
608             if (typeof value !== 'number' || value % 1 !== 0)
609                 throw TypeError("Illegal value: "+value+" (not an integer)");
610             value >>>= 0;
611             if (typeof offset !== 'number' || offset % 1 !== 0)
612                 throw TypeError("Illegal offset: "+offset+" (not an integer)");
613             offset >>>= 0;
614             if (offset < 0 || offset + 0 > this.buffer.byteLength)
615                 throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength);
616         }
617         offset += 1;
618         var capacity1 = this.buffer.byteLength;
619         if (offset > capacity1)
620             this.resize((capacity1 *= 2) > offset ? capacity1 : offset);
621         offset -= 1;
622         this.view[offset] = value;
623         if (relative) this.offset += 1;
624         return this;
625     };
627     /**
628      * Writes an 8bit unsigned integer. This is an alias of {@link ByteBuffer#writeUint8}.
629      * @function
630      * @param {number} value Value to write
631      * @param {number=} offset Offset to write to. Will use and advance {@link ByteBuffer#offset} by `1` if omitted.
632      * @returns {!ByteBuffer} this
633      * @expose
634      */
635     ByteBufferPrototype.writeUInt8 = ByteBufferPrototype.writeUint8;
637     /**
638      * Reads an 8bit unsigned integer.
639      * @param {number=} offset Offset to read from. Will use and advance {@link ByteBuffer#offset} by `1` if omitted.
640      * @returns {number} Value read
641      * @expose
642      */
643     ByteBufferPrototype.readUint8 = function(offset) {
644         var relative = typeof offset === 'undefined';
645         if (relative) offset = this.offset;
646         if (!this.noAssert) {
647             if (typeof offset !== 'number' || offset % 1 !== 0)
648                 throw TypeError("Illegal offset: "+offset+" (not an integer)");
649             offset >>>= 0;
650             if (offset < 0 || offset + 1 > this.buffer.byteLength)
651                 throw RangeError("Illegal offset: 0 <= "+offset+" (+"+1+") <= "+this.buffer.byteLength);
652         }
653         var value = this.view[offset];
654         if (relative) this.offset += 1;
655         return value;
656     };
658     /**
659      * Reads an 8bit unsigned integer. This is an alias of {@link ByteBuffer#readUint8}.
660      * @function
661      * @param {number=} offset Offset to read from. Will use and advance {@link ByteBuffer#offset} by `1` if omitted.
662      * @returns {number} Value read
663      * @expose
664      */
665     ByteBufferPrototype.readUInt8 = ByteBufferPrototype.readUint8;
667     // types/ints/int16
669     /**
670      * Writes a 16bit signed integer.
671      * @param {number} value Value to write
672      * @param {number=} offset Offset to write to. Will use and advance {@link ByteBuffer#offset} by `2` if omitted.
673      * @throws {TypeError} If `offset` or `value` is not a valid number
674      * @throws {RangeError} If `offset` is out of bounds
675      * @expose
676      */
677     ByteBufferPrototype.writeInt16 = function(value, offset) {
678         var relative = typeof offset === 'undefined';
679         if (relative) offset = this.offset;
680         if (!this.noAssert) {
681             if (typeof value !== 'number' || value % 1 !== 0)
682                 throw TypeError("Illegal value: "+value+" (not an integer)");
683             value |= 0;
684             if (typeof offset !== 'number' || offset % 1 !== 0)
685                 throw TypeError("Illegal offset: "+offset+" (not an integer)");
686             offset >>>= 0;
687             if (offset < 0 || offset + 0 > this.buffer.byteLength)
688                 throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength);
689         }
690         offset += 2;
691         var capacity2 = this.buffer.byteLength;
692         if (offset > capacity2)
693             this.resize((capacity2 *= 2) > offset ? capacity2 : offset);
694         offset -= 2;
695         if (this.littleEndian) {
696             this.view[offset+1] = (value & 0xFF00) >>> 8;
697             this.view[offset  ] =  value & 0x00FF;
698         } else {
699             this.view[offset]   = (value & 0xFF00) >>> 8;
700             this.view[offset+1] =  value & 0x00FF;
701         }
702         if (relative) this.offset += 2;
703         return this;
704     };
706     /**
707      * Writes a 16bit signed integer. This is an alias of {@link ByteBuffer#writeInt16}.
708      * @function
709      * @param {number} value Value to write
710      * @param {number=} offset Offset to write to. Will use and advance {@link ByteBuffer#offset} by `2` if omitted.
711      * @throws {TypeError} If `offset` or `value` is not a valid number
712      * @throws {RangeError} If `offset` is out of bounds
713      * @expose
714      */
715     ByteBufferPrototype.writeShort = ByteBufferPrototype.writeInt16;
717     /**
718      * Reads a 16bit signed integer.
719      * @param {number=} offset Offset to read from. Will use and advance {@link ByteBuffer#offset} by `2` if omitted.
720      * @returns {number} Value read
721      * @throws {TypeError} If `offset` is not a valid number
722      * @throws {RangeError} If `offset` is out of bounds
723      * @expose
724      */
725     ByteBufferPrototype.readInt16 = function(offset) {
726         var relative = typeof offset === 'undefined';
727         if (relative) offset = this.offset;
728         if (!this.noAssert) {
729             if (typeof offset !== 'number' || offset % 1 !== 0)
730                 throw TypeError("Illegal offset: "+offset+" (not an integer)");
731             offset >>>= 0;
732             if (offset < 0 || offset + 2 > this.buffer.byteLength)
733                 throw RangeError("Illegal offset: 0 <= "+offset+" (+"+2+") <= "+this.buffer.byteLength);
734         }
735         var value = 0;
736         if (this.littleEndian) {
737             value  = this.view[offset  ];
738             value |= this.view[offset+1] << 8;
739         } else {
740             value  = this.view[offset  ] << 8;
741             value |= this.view[offset+1];
742         }
743         if ((value & 0x8000) === 0x8000) value = -(0xFFFF - value + 1); // Cast to signed
744         if (relative) this.offset += 2;
745         return value;
746     };
748     /**
749      * Reads a 16bit signed integer. This is an alias of {@link ByteBuffer#readInt16}.
750      * @function
751      * @param {number=} offset Offset to read from. Will use and advance {@link ByteBuffer#offset} by `2` if omitted.
752      * @returns {number} Value read
753      * @throws {TypeError} If `offset` is not a valid number
754      * @throws {RangeError} If `offset` is out of bounds
755      * @expose
756      */
757     ByteBufferPrototype.readShort = ByteBufferPrototype.readInt16;
759     /**
760      * Writes a 16bit unsigned integer.
761      * @param {number} value Value to write
762      * @param {number=} offset Offset to write to. Will use and advance {@link ByteBuffer#offset} by `2` if omitted.
763      * @throws {TypeError} If `offset` or `value` is not a valid number
764      * @throws {RangeError} If `offset` is out of bounds
765      * @expose
766      */
767     ByteBufferPrototype.writeUint16 = function(value, offset) {
768         var relative = typeof offset === 'undefined';
769         if (relative) offset = this.offset;
770         if (!this.noAssert) {
771             if (typeof value !== 'number' || value % 1 !== 0)
772                 throw TypeError("Illegal value: "+value+" (not an integer)");
773             value >>>= 0;
774             if (typeof offset !== 'number' || offset % 1 !== 0)
775                 throw TypeError("Illegal offset: "+offset+" (not an integer)");
776             offset >>>= 0;
777             if (offset < 0 || offset + 0 > this.buffer.byteLength)
778                 throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength);
779         }
780         offset += 2;
781         var capacity3 = this.buffer.byteLength;
782         if (offset > capacity3)
783             this.resize((capacity3 *= 2) > offset ? capacity3 : offset);
784         offset -= 2;
785         if (this.littleEndian) {
786             this.view[offset+1] = (value & 0xFF00) >>> 8;
787             this.view[offset  ] =  value & 0x00FF;
788         } else {
789             this.view[offset]   = (value & 0xFF00) >>> 8;
790             this.view[offset+1] =  value & 0x00FF;
791         }
792         if (relative) this.offset += 2;
793         return this;
794     };
796     /**
797      * Writes a 16bit unsigned integer. This is an alias of {@link ByteBuffer#writeUint16}.
798      * @function
799      * @param {number} value Value to write
800      * @param {number=} offset Offset to write to. Will use and advance {@link ByteBuffer#offset} by `2` if omitted.
801      * @throws {TypeError} If `offset` or `value` is not a valid number
802      * @throws {RangeError} If `offset` is out of bounds
803      * @expose
804      */
805     ByteBufferPrototype.writeUInt16 = ByteBufferPrototype.writeUint16;
807     /**
808      * Reads a 16bit unsigned integer.
809      * @param {number=} offset Offset to read from. Will use and advance {@link ByteBuffer#offset} by `2` if omitted.
810      * @returns {number} Value read
811      * @throws {TypeError} If `offset` is not a valid number
812      * @throws {RangeError} If `offset` is out of bounds
813      * @expose
814      */
815     ByteBufferPrototype.readUint16 = function(offset) {
816         var relative = typeof offset === 'undefined';
817         if (relative) offset = this.offset;
818         if (!this.noAssert) {
819             if (typeof offset !== 'number' || offset % 1 !== 0)
820                 throw TypeError("Illegal offset: "+offset+" (not an integer)");
821             offset >>>= 0;
822             if (offset < 0 || offset + 2 > this.buffer.byteLength)
823                 throw RangeError("Illegal offset: 0 <= "+offset+" (+"+2+") <= "+this.buffer.byteLength);
824         }
825         var value = 0;
826         if (this.littleEndian) {
827             value  = this.view[offset  ];
828             value |= this.view[offset+1] << 8;
829         } else {
830             value  = this.view[offset  ] << 8;
831             value |= this.view[offset+1];
832         }
833         if (relative) this.offset += 2;
834         return value;
835     };
837     /**
838      * Reads a 16bit unsigned integer. This is an alias of {@link ByteBuffer#readUint16}.
839      * @function
840      * @param {number=} offset Offset to read from. Will use and advance {@link ByteBuffer#offset} by `2` if omitted.
841      * @returns {number} Value read
842      * @throws {TypeError} If `offset` is not a valid number
843      * @throws {RangeError} If `offset` is out of bounds
844      * @expose
845      */
846     ByteBufferPrototype.readUInt16 = ByteBufferPrototype.readUint16;
848     // types/ints/int32
850     /**
851      * Writes a 32bit signed integer.
852      * @param {number} value Value to write
853      * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by `4` if omitted.
854      * @expose
855      */
856     ByteBufferPrototype.writeInt32 = function(value, offset) {
857         var relative = typeof offset === 'undefined';
858         if (relative) offset = this.offset;
859         if (!this.noAssert) {
860             if (typeof value !== 'number' || value % 1 !== 0)
861                 throw TypeError("Illegal value: "+value+" (not an integer)");
862             value |= 0;
863             if (typeof offset !== 'number' || offset % 1 !== 0)
864                 throw TypeError("Illegal offset: "+offset+" (not an integer)");
865             offset >>>= 0;
866             if (offset < 0 || offset + 0 > this.buffer.byteLength)
867                 throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength);
868         }
869         offset += 4;
870         var capacity4 = this.buffer.byteLength;
871         if (offset > capacity4)
872             this.resize((capacity4 *= 2) > offset ? capacity4 : offset);
873         offset -= 4;
874         if (this.littleEndian) {
875             this.view[offset+3] = (value >>> 24) & 0xFF;
876             this.view[offset+2] = (value >>> 16) & 0xFF;
877             this.view[offset+1] = (value >>>  8) & 0xFF;
878             this.view[offset  ] =  value         & 0xFF;
879         } else {
880             this.view[offset  ] = (value >>> 24) & 0xFF;
881             this.view[offset+1] = (value >>> 16) & 0xFF;
882             this.view[offset+2] = (value >>>  8) & 0xFF;
883             this.view[offset+3] =  value         & 0xFF;
884         }
885         if (relative) this.offset += 4;
886         return this;
887     };
889     /**
890      * Writes a 32bit signed integer. This is an alias of {@link ByteBuffer#writeInt32}.
891      * @param {number} value Value to write
892      * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by `4` if omitted.
893      * @expose
894      */
895     ByteBufferPrototype.writeInt = ByteBufferPrototype.writeInt32;
897     /**
898      * Reads a 32bit signed integer.
899      * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by `4` if omitted.
900      * @returns {number} Value read
901      * @expose
902      */
903     ByteBufferPrototype.readInt32 = function(offset) {
904         var relative = typeof offset === 'undefined';
905         if (relative) offset = this.offset;
906         if (!this.noAssert) {
907             if (typeof offset !== 'number' || offset % 1 !== 0)
908                 throw TypeError("Illegal offset: "+offset+" (not an integer)");
909             offset >>>= 0;
910             if (offset < 0 || offset + 4 > this.buffer.byteLength)
911                 throw RangeError("Illegal offset: 0 <= "+offset+" (+"+4+") <= "+this.buffer.byteLength);
912         }
913         var value = 0;
914         if (this.littleEndian) {
915             value  = this.view[offset+2] << 16;
916             value |= this.view[offset+1] <<  8;
917             value |= this.view[offset  ];
918             value += this.view[offset+3] << 24 >>> 0;
919         } else {
920             value  = this.view[offset+1] << 16;
921             value |= this.view[offset+2] <<  8;
922             value |= this.view[offset+3];
923             value += this.view[offset  ] << 24 >>> 0;
924         }
925         value |= 0; // Cast to signed
926         if (relative) this.offset += 4;
927         return value;
928     };
930     /**
931      * Reads a 32bit signed integer. This is an alias of {@link ByteBuffer#readInt32}.
932      * @param {number=} offset Offset to read from. Will use and advance {@link ByteBuffer#offset} by `4` if omitted.
933      * @returns {number} Value read
934      * @expose
935      */
936     ByteBufferPrototype.readInt = ByteBufferPrototype.readInt32;
938     /**
939      * Writes a 32bit unsigned integer.
940      * @param {number} value Value to write
941      * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by `4` if omitted.
942      * @expose
943      */
944     ByteBufferPrototype.writeUint32 = function(value, offset) {
945         var relative = typeof offset === 'undefined';
946         if (relative) offset = this.offset;
947         if (!this.noAssert) {
948             if (typeof value !== 'number' || value % 1 !== 0)
949                 throw TypeError("Illegal value: "+value+" (not an integer)");
950             value >>>= 0;
951             if (typeof offset !== 'number' || offset % 1 !== 0)
952                 throw TypeError("Illegal offset: "+offset+" (not an integer)");
953             offset >>>= 0;
954             if (offset < 0 || offset + 0 > this.buffer.byteLength)
955                 throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength);
956         }
957         offset += 4;
958         var capacity5 = this.buffer.byteLength;
959         if (offset > capacity5)
960             this.resize((capacity5 *= 2) > offset ? capacity5 : offset);
961         offset -= 4;
962         if (this.littleEndian) {
963             this.view[offset+3] = (value >>> 24) & 0xFF;
964             this.view[offset+2] = (value >>> 16) & 0xFF;
965             this.view[offset+1] = (value >>>  8) & 0xFF;
966             this.view[offset  ] =  value         & 0xFF;
967         } else {
968             this.view[offset  ] = (value >>> 24) & 0xFF;
969             this.view[offset+1] = (value >>> 16) & 0xFF;
970             this.view[offset+2] = (value >>>  8) & 0xFF;
971             this.view[offset+3] =  value         & 0xFF;
972         }
973         if (relative) this.offset += 4;
974         return this;
975     };
977     /**
978      * Writes a 32bit unsigned integer. This is an alias of {@link ByteBuffer#writeUint32}.
979      * @function
980      * @param {number} value Value to write
981      * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by `4` if omitted.
982      * @expose
983      */
984     ByteBufferPrototype.writeUInt32 = ByteBufferPrototype.writeUint32;
986     /**
987      * Reads a 32bit unsigned integer.
988      * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by `4` if omitted.
989      * @returns {number} Value read
990      * @expose
991      */
992     ByteBufferPrototype.readUint32 = function(offset) {
993         var relative = typeof offset === 'undefined';
994         if (relative) offset = this.offset;
995         if (!this.noAssert) {
996             if (typeof offset !== 'number' || offset % 1 !== 0)
997                 throw TypeError("Illegal offset: "+offset+" (not an integer)");
998             offset >>>= 0;
999             if (offset < 0 || offset + 4 > this.buffer.byteLength)
1000                 throw RangeError("Illegal offset: 0 <= "+offset+" (+"+4+") <= "+this.buffer.byteLength);
1001         }
1002         var value = 0;
1003         if (this.littleEndian) {
1004             value  = this.view[offset+2] << 16;
1005             value |= this.view[offset+1] <<  8;
1006             value |= this.view[offset  ];
1007             value += this.view[offset+3] << 24 >>> 0;
1008         } else {
1009             value  = this.view[offset+1] << 16;
1010             value |= this.view[offset+2] <<  8;
1011             value |= this.view[offset+3];
1012             value += this.view[offset  ] << 24 >>> 0;
1013         }
1014         if (relative) this.offset += 4;
1015         return value;
1016     };
1018     /**
1019      * Reads a 32bit unsigned integer. This is an alias of {@link ByteBuffer#readUint32}.
1020      * @function
1021      * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by `4` if omitted.
1022      * @returns {number} Value read
1023      * @expose
1024      */
1025     ByteBufferPrototype.readUInt32 = ByteBufferPrototype.readUint32;
1027     // types/ints/int64
1029     if (Long) {
1031         /**
1032          * Writes a 64bit signed integer.
1033          * @param {number|!Long} value Value to write
1034          * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by `8` if omitted.
1035          * @returns {!ByteBuffer} this
1036          * @expose
1037          */
1038         ByteBufferPrototype.writeInt64 = function(value, offset) {
1039             var relative = typeof offset === 'undefined';
1040             if (relative) offset = this.offset;
1041             if (!this.noAssert) {
1042                 if (typeof value === 'number')
1043                     value = Long.fromNumber(value);
1044                 else if (typeof value === 'string')
1045                     value = Long.fromString(value);
1046                 else if (!(value && value instanceof Long))
1047                     throw TypeError("Illegal value: "+value+" (not an integer or Long)");
1048                 if (typeof offset !== 'number' || offset % 1 !== 0)
1049                     throw TypeError("Illegal offset: "+offset+" (not an integer)");
1050                 offset >>>= 0;
1051                 if (offset < 0 || offset + 0 > this.buffer.byteLength)
1052                     throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength);
1053             }
1054             if (typeof value === 'number')
1055                 value = Long.fromNumber(value);
1056             else if (typeof value === 'string')
1057                 value = Long.fromString(value);
1058             offset += 8;
1059             var capacity6 = this.buffer.byteLength;
1060             if (offset > capacity6)
1061                 this.resize((capacity6 *= 2) > offset ? capacity6 : offset);
1062             offset -= 8;
1063             var lo = value.low,
1064                 hi = value.high;
1065             if (this.littleEndian) {
1066                 this.view[offset+3] = (lo >>> 24) & 0xFF;
1067                 this.view[offset+2] = (lo >>> 16) & 0xFF;
1068                 this.view[offset+1] = (lo >>>  8) & 0xFF;
1069                 this.view[offset  ] =  lo         & 0xFF;
1070                 offset += 4;
1071                 this.view[offset+3] = (hi >>> 24) & 0xFF;
1072                 this.view[offset+2] = (hi >>> 16) & 0xFF;
1073                 this.view[offset+1] = (hi >>>  8) & 0xFF;
1074                 this.view[offset  ] =  hi         & 0xFF;
1075             } else {
1076                 this.view[offset  ] = (hi >>> 24) & 0xFF;
1077                 this.view[offset+1] = (hi >>> 16) & 0xFF;
1078                 this.view[offset+2] = (hi >>>  8) & 0xFF;
1079                 this.view[offset+3] =  hi         & 0xFF;
1080                 offset += 4;
1081                 this.view[offset  ] = (lo >>> 24) & 0xFF;
1082                 this.view[offset+1] = (lo >>> 16) & 0xFF;
1083                 this.view[offset+2] = (lo >>>  8) & 0xFF;
1084                 this.view[offset+3] =  lo         & 0xFF;
1085             }
1086             if (relative) this.offset += 8;
1087             return this;
1088         };
1090         /**
1091          * Writes a 64bit signed integer. This is an alias of {@link ByteBuffer#writeInt64}.
1092          * @param {number|!Long} value Value to write
1093          * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by `8` if omitted.
1094          * @returns {!ByteBuffer} this
1095          * @expose
1096          */
1097         ByteBufferPrototype.writeLong = ByteBufferPrototype.writeInt64;
1099         /**
1100          * Reads a 64bit signed integer.
1101          * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by `8` if omitted.
1102          * @returns {!Long}
1103          * @expose
1104          */
1105         ByteBufferPrototype.readInt64 = function(offset) {
1106             var relative = typeof offset === 'undefined';
1107             if (relative) offset = this.offset;
1108             if (!this.noAssert) {
1109                 if (typeof offset !== 'number' || offset % 1 !== 0)
1110                     throw TypeError("Illegal offset: "+offset+" (not an integer)");
1111                 offset >>>= 0;
1112                 if (offset < 0 || offset + 8 > this.buffer.byteLength)
1113                     throw RangeError("Illegal offset: 0 <= "+offset+" (+"+8+") <= "+this.buffer.byteLength);
1114             }
1115             var lo = 0,
1116                 hi = 0;
1117             if (this.littleEndian) {
1118                 lo  = this.view[offset+2] << 16;
1119                 lo |= this.view[offset+1] <<  8;
1120                 lo |= this.view[offset  ];
1121                 lo += this.view[offset+3] << 24 >>> 0;
1122                 offset += 4;
1123                 hi  = this.view[offset+2] << 16;
1124                 hi |= this.view[offset+1] <<  8;
1125                 hi |= this.view[offset  ];
1126                 hi += this.view[offset+3] << 24 >>> 0;
1127             } else {
1128                 hi  = this.view[offset+1] << 16;
1129                 hi |= this.view[offset+2] <<  8;
1130                 hi |= this.view[offset+3];
1131                 hi += this.view[offset  ] << 24 >>> 0;
1132                 offset += 4;
1133                 lo  = this.view[offset+1] << 16;
1134                 lo |= this.view[offset+2] <<  8;
1135                 lo |= this.view[offset+3];
1136                 lo += this.view[offset  ] << 24 >>> 0;
1137             }
1138             var value = new Long(lo, hi, false);
1139             if (relative) this.offset += 8;
1140             return value;
1141         };
1143         /**
1144          * Reads a 64bit signed integer. This is an alias of {@link ByteBuffer#readInt64}.
1145          * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by `8` if omitted.
1146          * @returns {!Long}
1147          * @expose
1148          */
1149         ByteBufferPrototype.readLong = ByteBufferPrototype.readInt64;
1151         /**
1152          * Writes a 64bit unsigned integer.
1153          * @param {number|!Long} value Value to write
1154          * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by `8` if omitted.
1155          * @returns {!ByteBuffer} this
1156          * @expose
1157          */
1158         ByteBufferPrototype.writeUint64 = function(value, offset) {
1159             var relative = typeof offset === 'undefined';
1160             if (relative) offset = this.offset;
1161             if (!this.noAssert) {
1162                 if (typeof value === 'number')
1163                     value = Long.fromNumber(value);
1164                 else if (typeof value === 'string')
1165                     value = Long.fromString(value);
1166                 else if (!(value && value instanceof Long))
1167                     throw TypeError("Illegal value: "+value+" (not an integer or Long)");
1168                 if (typeof offset !== 'number' || offset % 1 !== 0)
1169                     throw TypeError("Illegal offset: "+offset+" (not an integer)");
1170                 offset >>>= 0;
1171                 if (offset < 0 || offset + 0 > this.buffer.byteLength)
1172                     throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength);
1173             }
1174             if (typeof value === 'number')
1175                 value = Long.fromNumber(value);
1176             else if (typeof value === 'string')
1177                 value = Long.fromString(value);
1178             offset += 8;
1179             var capacity7 = this.buffer.byteLength;
1180             if (offset > capacity7)
1181                 this.resize((capacity7 *= 2) > offset ? capacity7 : offset);
1182             offset -= 8;
1183             var lo = value.low,
1184                 hi = value.high;
1185             if (this.littleEndian) {
1186                 this.view[offset+3] = (lo >>> 24) & 0xFF;
1187                 this.view[offset+2] = (lo >>> 16) & 0xFF;
1188                 this.view[offset+1] = (lo >>>  8) & 0xFF;
1189                 this.view[offset  ] =  lo         & 0xFF;
1190                 offset += 4;
1191                 this.view[offset+3] = (hi >>> 24) & 0xFF;
1192                 this.view[offset+2] = (hi >>> 16) & 0xFF;
1193                 this.view[offset+1] = (hi >>>  8) & 0xFF;
1194                 this.view[offset  ] =  hi         & 0xFF;
1195             } else {
1196                 this.view[offset  ] = (hi >>> 24) & 0xFF;
1197                 this.view[offset+1] = (hi >>> 16) & 0xFF;
1198                 this.view[offset+2] = (hi >>>  8) & 0xFF;
1199                 this.view[offset+3] =  hi         & 0xFF;
1200                 offset += 4;
1201                 this.view[offset  ] = (lo >>> 24) & 0xFF;
1202                 this.view[offset+1] = (lo >>> 16) & 0xFF;
1203                 this.view[offset+2] = (lo >>>  8) & 0xFF;
1204                 this.view[offset+3] =  lo         & 0xFF;
1205             }
1206             if (relative) this.offset += 8;
1207             return this;
1208         };
1210         /**
1211          * Writes a 64bit unsigned integer. This is an alias of {@link ByteBuffer#writeUint64}.
1212          * @function
1213          * @param {number|!Long} value Value to write
1214          * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by `8` if omitted.
1215          * @returns {!ByteBuffer} this
1216          * @expose
1217          */
1218         ByteBufferPrototype.writeUInt64 = ByteBufferPrototype.writeUint64;
1220         /**
1221          * Reads a 64bit unsigned integer.
1222          * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by `8` if omitted.
1223          * @returns {!Long}
1224          * @expose
1225          */
1226         ByteBufferPrototype.readUint64 = function(offset) {
1227             var relative = typeof offset === 'undefined';
1228             if (relative) offset = this.offset;
1229             if (!this.noAssert) {
1230                 if (typeof offset !== 'number' || offset % 1 !== 0)
1231                     throw TypeError("Illegal offset: "+offset+" (not an integer)");
1232                 offset >>>= 0;
1233                 if (offset < 0 || offset + 8 > this.buffer.byteLength)
1234                     throw RangeError("Illegal offset: 0 <= "+offset+" (+"+8+") <= "+this.buffer.byteLength);
1235             }
1236             var lo = 0,
1237                 hi = 0;
1238             if (this.littleEndian) {
1239                 lo  = this.view[offset+2] << 16;
1240                 lo |= this.view[offset+1] <<  8;
1241                 lo |= this.view[offset  ];
1242                 lo += this.view[offset+3] << 24 >>> 0;
1243                 offset += 4;
1244                 hi  = this.view[offset+2] << 16;
1245                 hi |= this.view[offset+1] <<  8;
1246                 hi |= this.view[offset  ];
1247                 hi += this.view[offset+3] << 24 >>> 0;
1248             } else {
1249                 hi  = this.view[offset+1] << 16;
1250                 hi |= this.view[offset+2] <<  8;
1251                 hi |= this.view[offset+3];
1252                 hi += this.view[offset  ] << 24 >>> 0;
1253                 offset += 4;
1254                 lo  = this.view[offset+1] << 16;
1255                 lo |= this.view[offset+2] <<  8;
1256                 lo |= this.view[offset+3];
1257                 lo += this.view[offset  ] << 24 >>> 0;
1258             }
1259             var value = new Long(lo, hi, true);
1260             if (relative) this.offset += 8;
1261             return value;
1262         };
1264         /**
1265          * Reads a 64bit unsigned integer. This is an alias of {@link ByteBuffer#readUint64}.
1266          * @function
1267          * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by `8` if omitted.
1268          * @returns {!Long}
1269          * @expose
1270          */
1271         ByteBufferPrototype.readUInt64 = ByteBufferPrototype.readUint64;
1273     } // Long
1276     // types/floats/float32
1278     /*
1279      ieee754 - https://github.com/feross/ieee754
1281      The MIT License (MIT)
1283      Copyright (c) Feross Aboukhadijeh
1285      Permission is hereby granted, free of charge, to any person obtaining a copy
1286      of this software and associated documentation files (the "Software"), to deal
1287      in the Software without restriction, including without limitation the rights
1288      to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
1289      copies of the Software, and to permit persons to whom the Software is
1290      furnished to do so, subject to the following conditions:
1292      The above copyright notice and this permission notice shall be included in
1293      all copies or substantial portions of the Software.
1295      THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1296      IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1297      FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1298      AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1299      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
1300      OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
1301      THE SOFTWARE.
1302     */
1304     /**
1305      * Reads an IEEE754 float from a byte array.
1306      * @param {!Array} buffer
1307      * @param {number} offset
1308      * @param {boolean} isLE
1309      * @param {number} mLen
1310      * @param {number} nBytes
1311      * @returns {number}
1312      * @inner
1313      */
1314     function ieee754_read(buffer, offset, isLE, mLen, nBytes) {
1315         var e, m,
1316             eLen = nBytes * 8 - mLen - 1,
1317             eMax = (1 << eLen) - 1,
1318             eBias = eMax >> 1,
1319             nBits = -7,
1320             i = isLE ? (nBytes - 1) : 0,
1321             d = isLE ? -1 : 1,
1322             s = buffer[offset + i];
1324         i += d;
1326         e = s & ((1 << (-nBits)) - 1);
1327         s >>= (-nBits);
1328         nBits += eLen;
1329         for (; nBits > 0; e = e * 256 + buffer[offset + i], i += d, nBits -= 8) {}
1331         m = e & ((1 << (-nBits)) - 1);
1332         e >>= (-nBits);
1333         nBits += mLen;
1334         for (; nBits > 0; m = m * 256 + buffer[offset + i], i += d, nBits -= 8) {}
1336         if (e === 0) {
1337             e = 1 - eBias;
1338         } else if (e === eMax) {
1339             return m ? NaN : ((s ? -1 : 1) * Infinity);
1340         } else {
1341             m = m + Math.pow(2, mLen);
1342             e = e - eBias;
1343         }
1344         return (s ? -1 : 1) * m * Math.pow(2, e - mLen);
1345     }
1347     /**
1348      * Writes an IEEE754 float to a byte array.
1349      * @param {!Array} buffer
1350      * @param {number} value
1351      * @param {number} offset
1352      * @param {boolean} isLE
1353      * @param {number} mLen
1354      * @param {number} nBytes
1355      * @inner
1356      */
1357     function ieee754_write(buffer, value, offset, isLE, mLen, nBytes) {
1358         var e, m, c,
1359             eLen = nBytes * 8 - mLen - 1,
1360             eMax = (1 << eLen) - 1,
1361             eBias = eMax >> 1,
1362             rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0),
1363             i = isLE ? 0 : (nBytes - 1),
1364             d = isLE ? 1 : -1,
1365             s = value < 0 || (value === 0 && 1 / value < 0) ? 1 : 0;
1367         value = Math.abs(value);
1369         if (isNaN(value) || value === Infinity) {
1370             m = isNaN(value) ? 1 : 0;
1371             e = eMax;
1372         } else {
1373             e = Math.floor(Math.log(value) / Math.LN2);
1374             if (value * (c = Math.pow(2, -e)) < 1) {
1375                 e--;
1376                 c *= 2;
1377             }
1378             if (e + eBias >= 1) {
1379                 value += rt / c;
1380             } else {
1381                 value += rt * Math.pow(2, 1 - eBias);
1382             }
1383             if (value * c >= 2) {
1384                 e++;
1385                 c /= 2;
1386             }
1388             if (e + eBias >= eMax) {
1389                 m = 0;
1390                 e = eMax;
1391             } else if (e + eBias >= 1) {
1392                 m = (value * c - 1) * Math.pow(2, mLen);
1393                 e = e + eBias;
1394             } else {
1395                 m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen);
1396                 e = 0;
1397             }
1398         }
1400         for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8) {}
1402         e = (e << mLen) | m;
1403         eLen += mLen;
1404         for (; eLen > 0; buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8) {}
1406         buffer[offset + i - d] |= s * 128;
1407     }
1409     /**
1410      * Writes a 32bit float.
1411      * @param {number} value Value to write
1412      * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by `4` if omitted.
1413      * @returns {!ByteBuffer} this
1414      * @expose
1415      */
1416     ByteBufferPrototype.writeFloat32 = function(value, offset) {
1417         var relative = typeof offset === 'undefined';
1418         if (relative) offset = this.offset;
1419         if (!this.noAssert) {
1420             if (typeof value !== 'number')
1421                 throw TypeError("Illegal value: "+value+" (not a number)");
1422             if (typeof offset !== 'number' || offset % 1 !== 0)
1423                 throw TypeError("Illegal offset: "+offset+" (not an integer)");
1424             offset >>>= 0;
1425             if (offset < 0 || offset + 0 > this.buffer.byteLength)
1426                 throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength);
1427         }
1428         offset += 4;
1429         var capacity8 = this.buffer.byteLength;
1430         if (offset > capacity8)
1431             this.resize((capacity8 *= 2) > offset ? capacity8 : offset);
1432         offset -= 4;
1433         ieee754_write(this.view, value, offset, this.littleEndian, 23, 4);
1434         if (relative) this.offset += 4;
1435         return this;
1436     };
1438     /**
1439      * Writes a 32bit float. This is an alias of {@link ByteBuffer#writeFloat32}.
1440      * @function
1441      * @param {number} value Value to write
1442      * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by `4` if omitted.
1443      * @returns {!ByteBuffer} this
1444      * @expose
1445      */
1446     ByteBufferPrototype.writeFloat = ByteBufferPrototype.writeFloat32;
1448     /**
1449      * Reads a 32bit float.
1450      * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by `4` if omitted.
1451      * @returns {number}
1452      * @expose
1453      */
1454     ByteBufferPrototype.readFloat32 = function(offset) {
1455         var relative = typeof offset === 'undefined';
1456         if (relative) offset = this.offset;
1457         if (!this.noAssert) {
1458             if (typeof offset !== 'number' || offset % 1 !== 0)
1459                 throw TypeError("Illegal offset: "+offset+" (not an integer)");
1460             offset >>>= 0;
1461             if (offset < 0 || offset + 4 > this.buffer.byteLength)
1462                 throw RangeError("Illegal offset: 0 <= "+offset+" (+"+4+") <= "+this.buffer.byteLength);
1463         }
1464         var value = ieee754_read(this.view, offset, this.littleEndian, 23, 4);
1465         if (relative) this.offset += 4;
1466         return value;
1467     };
1469     /**
1470      * Reads a 32bit float. This is an alias of {@link ByteBuffer#readFloat32}.
1471      * @function
1472      * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by `4` if omitted.
1473      * @returns {number}
1474      * @expose
1475      */
1476     ByteBufferPrototype.readFloat = ByteBufferPrototype.readFloat32;
1478     // types/floats/float64
1480     /**
1481      * Writes a 64bit float.
1482      * @param {number} value Value to write
1483      * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by `8` if omitted.
1484      * @returns {!ByteBuffer} this
1485      * @expose
1486      */
1487     ByteBufferPrototype.writeFloat64 = function(value, offset) {
1488         var relative = typeof offset === 'undefined';
1489         if (relative) offset = this.offset;
1490         if (!this.noAssert) {
1491             if (typeof value !== 'number')
1492                 throw TypeError("Illegal value: "+value+" (not a number)");
1493             if (typeof offset !== 'number' || offset % 1 !== 0)
1494                 throw TypeError("Illegal offset: "+offset+" (not an integer)");
1495             offset >>>= 0;
1496             if (offset < 0 || offset + 0 > this.buffer.byteLength)
1497                 throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength);
1498         }
1499         offset += 8;
1500         var capacity9 = this.buffer.byteLength;
1501         if (offset > capacity9)
1502             this.resize((capacity9 *= 2) > offset ? capacity9 : offset);
1503         offset -= 8;
1504         ieee754_write(this.view, value, offset, this.littleEndian, 52, 8);
1505         if (relative) this.offset += 8;
1506         return this;
1507     };
1509     /**
1510      * Writes a 64bit float. This is an alias of {@link ByteBuffer#writeFloat64}.
1511      * @function
1512      * @param {number} value Value to write
1513      * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by `8` if omitted.
1514      * @returns {!ByteBuffer} this
1515      * @expose
1516      */
1517     ByteBufferPrototype.writeDouble = ByteBufferPrototype.writeFloat64;
1519     /**
1520      * Reads a 64bit float.
1521      * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by `8` if omitted.
1522      * @returns {number}
1523      * @expose
1524      */
1525     ByteBufferPrototype.readFloat64 = function(offset) {
1526         var relative = typeof offset === 'undefined';
1527         if (relative) offset = this.offset;
1528         if (!this.noAssert) {
1529             if (typeof offset !== 'number' || offset % 1 !== 0)
1530                 throw TypeError("Illegal offset: "+offset+" (not an integer)");
1531             offset >>>= 0;
1532             if (offset < 0 || offset + 8 > this.buffer.byteLength)
1533                 throw RangeError("Illegal offset: 0 <= "+offset+" (+"+8+") <= "+this.buffer.byteLength);
1534         }
1535         var value = ieee754_read(this.view, offset, this.littleEndian, 52, 8);
1536         if (relative) this.offset += 8;
1537         return value;
1538     };
1540     /**
1541      * Reads a 64bit float. This is an alias of {@link ByteBuffer#readFloat64}.
1542      * @function
1543      * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by `8` if omitted.
1544      * @returns {number}
1545      * @expose
1546      */
1547     ByteBufferPrototype.readDouble = ByteBufferPrototype.readFloat64;
1550     // types/varints/varint32
1552     /**
1553      * Maximum number of bytes required to store a 32bit base 128 variable-length integer.
1554      * @type {number}
1555      * @const
1556      * @expose
1557      */
1558     ByteBuffer.MAX_VARINT32_BYTES = 5;
1560     /**
1561      * Calculates the actual number of bytes required to store a 32bit base 128 variable-length integer.
1562      * @param {number} value Value to encode
1563      * @returns {number} Number of bytes required. Capped to {@link ByteBuffer.MAX_VARINT32_BYTES}
1564      * @expose
1565      */
1566     ByteBuffer.calculateVarint32 = function(value) {
1567         // ref: src/google/protobuf/io/coded_stream.cc
1568         value = value >>> 0;
1569              if (value < 1 << 7 ) return 1;
1570         else if (value < 1 << 14) return 2;
1571         else if (value < 1 << 21) return 3;
1572         else if (value < 1 << 28) return 4;
1573         else                      return 5;
1574     };
1576     /**
1577      * Zigzag encodes a signed 32bit integer so that it can be effectively used with varint encoding.
1578      * @param {number} n Signed 32bit integer
1579      * @returns {number} Unsigned zigzag encoded 32bit integer
1580      * @expose
1581      */
1582     ByteBuffer.zigZagEncode32 = function(n) {
1583         return (((n |= 0) << 1) ^ (n >> 31)) >>> 0; // ref: src/google/protobuf/wire_format_lite.h
1584     };
1586     /**
1587      * Decodes a zigzag encoded signed 32bit integer.
1588      * @param {number} n Unsigned zigzag encoded 32bit integer
1589      * @returns {number} Signed 32bit integer
1590      * @expose
1591      */
1592     ByteBuffer.zigZagDecode32 = function(n) {
1593         return ((n >>> 1) ^ -(n & 1)) | 0; // // ref: src/google/protobuf/wire_format_lite.h
1594     };
1596     /**
1597      * Writes a 32bit base 128 variable-length integer.
1598      * @param {number} value Value to write
1599      * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by the number of bytes
1600      *  written if omitted.
1601      * @returns {!ByteBuffer|number} this if `offset` is omitted, else the actual number of bytes written
1602      * @expose
1603      */
1604     ByteBufferPrototype.writeVarint32 = function(value, offset) {
1605         var relative = typeof offset === 'undefined';
1606         if (relative) offset = this.offset;
1607         if (!this.noAssert) {
1608             if (typeof value !== 'number' || value % 1 !== 0)
1609                 throw TypeError("Illegal value: "+value+" (not an integer)");
1610             value |= 0;
1611             if (typeof offset !== 'number' || offset % 1 !== 0)
1612                 throw TypeError("Illegal offset: "+offset+" (not an integer)");
1613             offset >>>= 0;
1614             if (offset < 0 || offset + 0 > this.buffer.byteLength)
1615                 throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength);
1616         }
1617         var size = ByteBuffer.calculateVarint32(value),
1618             b;
1619         offset += size;
1620         var capacity10 = this.buffer.byteLength;
1621         if (offset > capacity10)
1622             this.resize((capacity10 *= 2) > offset ? capacity10 : offset);
1623         offset -= size;
1624         value >>>= 0;
1625         while (value >= 0x80) {
1626             b = (value & 0x7f) | 0x80;
1627             this.view[offset++] = b;
1628             value >>>= 7;
1629         }
1630         this.view[offset++] = value;
1631         if (relative) {
1632             this.offset = offset;
1633             return this;
1634         }
1635         return size;
1636     };
1638     /**
1639      * Writes a zig-zag encoded (signed) 32bit base 128 variable-length integer.
1640      * @param {number} value Value to write
1641      * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by the number of bytes
1642      *  written if omitted.
1643      * @returns {!ByteBuffer|number} this if `offset` is omitted, else the actual number of bytes written
1644      * @expose
1645      */
1646     ByteBufferPrototype.writeVarint32ZigZag = function(value, offset) {
1647         return this.writeVarint32(ByteBuffer.zigZagEncode32(value), offset);
1648     };
1650     /**
1651      * Reads a 32bit base 128 variable-length integer.
1652      * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by the number of bytes
1653      *  written if omitted.
1654      * @returns {number|!{value: number, length: number}} The value read if offset is omitted, else the value read
1655      *  and the actual number of bytes read.
1656      * @throws {Error} If it's not a valid varint. Has a property `truncated = true` if there is not enough data available
1657      *  to fully decode the varint.
1658      * @expose
1659      */
1660     ByteBufferPrototype.readVarint32 = function(offset) {
1661         var relative = typeof offset === 'undefined';
1662         if (relative) offset = this.offset;
1663         if (!this.noAssert) {
1664             if (typeof offset !== 'number' || offset % 1 !== 0)
1665                 throw TypeError("Illegal offset: "+offset+" (not an integer)");
1666             offset >>>= 0;
1667             if (offset < 0 || offset + 1 > this.buffer.byteLength)
1668                 throw RangeError("Illegal offset: 0 <= "+offset+" (+"+1+") <= "+this.buffer.byteLength);
1669         }
1670         var c = 0,
1671             value = 0 >>> 0,
1672             b;
1673         do {
1674             if (!this.noAssert && offset > this.limit) {
1675                 var err = Error("Truncated");
1676                 err['truncated'] = true;
1677                 throw err;
1678             }
1679             b = this.view[offset++];
1680             if (c < 5)
1681                 value |= (b & 0x7f) << (7*c);
1682             ++c;
1683         } while ((b & 0x80) !== 0);
1684         value |= 0;
1685         if (relative) {
1686             this.offset = offset;
1687             return value;
1688         }
1689         return {
1690             "value": value,
1691             "length": c
1692         };
1693     };
1695     /**
1696      * Reads a zig-zag encoded (signed) 32bit base 128 variable-length integer.
1697      * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by the number of bytes
1698      *  written if omitted.
1699      * @returns {number|!{value: number, length: number}} The value read if offset is omitted, else the value read
1700      *  and the actual number of bytes read.
1701      * @throws {Error} If it's not a valid varint
1702      * @expose
1703      */
1704     ByteBufferPrototype.readVarint32ZigZag = function(offset) {
1705         var val = this.readVarint32(offset);
1706         if (typeof val === 'object')
1707             val["value"] = ByteBuffer.zigZagDecode32(val["value"]);
1708         else
1709             val = ByteBuffer.zigZagDecode32(val);
1710         return val;
1711     };
1713     // types/varints/varint64
1715     if (Long) {
1717         /**
1718          * Maximum number of bytes required to store a 64bit base 128 variable-length integer.
1719          * @type {number}
1720          * @const
1721          * @expose
1722          */
1723         ByteBuffer.MAX_VARINT64_BYTES = 10;
1725         /**
1726          * Calculates the actual number of bytes required to store a 64bit base 128 variable-length integer.
1727          * @param {number|!Long} value Value to encode
1728          * @returns {number} Number of bytes required. Capped to {@link ByteBuffer.MAX_VARINT64_BYTES}
1729          * @expose
1730          */
1731         ByteBuffer.calculateVarint64 = function(value) {
1732             if (typeof value === 'number')
1733                 value = Long.fromNumber(value);
1734             else if (typeof value === 'string')
1735                 value = Long.fromString(value);
1736             // ref: src/google/protobuf/io/coded_stream.cc
1737             var part0 = value.toInt() >>> 0,
1738                 part1 = value.shiftRightUnsigned(28).toInt() >>> 0,
1739                 part2 = value.shiftRightUnsigned(56).toInt() >>> 0;
1740             if (part2 == 0) {
1741                 if (part1 == 0) {
1742                     if (part0 < 1 << 14)
1743                         return part0 < 1 << 7 ? 1 : 2;
1744                     else
1745                         return part0 < 1 << 21 ? 3 : 4;
1746                 } else {
1747                     if (part1 < 1 << 14)
1748                         return part1 < 1 << 7 ? 5 : 6;
1749                     else
1750                         return part1 < 1 << 21 ? 7 : 8;
1751                 }
1752             } else
1753                 return part2 < 1 << 7 ? 9 : 10;
1754         };
1756         /**
1757          * Zigzag encodes a signed 64bit integer so that it can be effectively used with varint encoding.
1758          * @param {number|!Long} value Signed long
1759          * @returns {!Long} Unsigned zigzag encoded long
1760          * @expose
1761          */
1762         ByteBuffer.zigZagEncode64 = function(value) {
1763             if (typeof value === 'number')
1764                 value = Long.fromNumber(value, false);
1765             else if (typeof value === 'string')
1766                 value = Long.fromString(value, false);
1767             else if (value.unsigned !== false) value = value.toSigned();
1768             // ref: src/google/protobuf/wire_format_lite.h
1769             return value.shiftLeft(1).xor(value.shiftRight(63)).toUnsigned();
1770         };
1772         /**
1773          * Decodes a zigzag encoded signed 64bit integer.
1774          * @param {!Long|number} value Unsigned zigzag encoded long or JavaScript number
1775          * @returns {!Long} Signed long
1776          * @expose
1777          */
1778         ByteBuffer.zigZagDecode64 = function(value) {
1779             if (typeof value === 'number')
1780                 value = Long.fromNumber(value, false);
1781             else if (typeof value === 'string')
1782                 value = Long.fromString(value, false);
1783             else if (value.unsigned !== false) value = value.toSigned();
1784             // ref: src/google/protobuf/wire_format_lite.h
1785             return value.shiftRightUnsigned(1).xor(value.and(Long.ONE).toSigned().negate()).toSigned();
1786         };
1788         /**
1789          * Writes a 64bit base 128 variable-length integer.
1790          * @param {number|Long} value Value to write
1791          * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by the number of bytes
1792          *  written if omitted.
1793          * @returns {!ByteBuffer|number} `this` if offset is omitted, else the actual number of bytes written.
1794          * @expose
1795          */
1796         ByteBufferPrototype.writeVarint64 = function(value, offset) {
1797             var relative = typeof offset === 'undefined';
1798             if (relative) offset = this.offset;
1799             if (!this.noAssert) {
1800                 if (typeof value === 'number')
1801                     value = Long.fromNumber(value);
1802                 else if (typeof value === 'string')
1803                     value = Long.fromString(value);
1804                 else if (!(value && value instanceof Long))
1805                     throw TypeError("Illegal value: "+value+" (not an integer or Long)");
1806                 if (typeof offset !== 'number' || offset % 1 !== 0)
1807                     throw TypeError("Illegal offset: "+offset+" (not an integer)");
1808                 offset >>>= 0;
1809                 if (offset < 0 || offset + 0 > this.buffer.byteLength)
1810                     throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength);
1811             }
1812             if (typeof value === 'number')
1813                 value = Long.fromNumber(value, false);
1814             else if (typeof value === 'string')
1815                 value = Long.fromString(value, false);
1816             else if (value.unsigned !== false) value = value.toSigned();
1817             var size = ByteBuffer.calculateVarint64(value),
1818                 part0 = value.toInt() >>> 0,
1819                 part1 = value.shiftRightUnsigned(28).toInt() >>> 0,
1820                 part2 = value.shiftRightUnsigned(56).toInt() >>> 0;
1821             offset += size;
1822             var capacity11 = this.buffer.byteLength;
1823             if (offset > capacity11)
1824                 this.resize((capacity11 *= 2) > offset ? capacity11 : offset);
1825             offset -= size;
1826             switch (size) {
1827                 case 10: this.view[offset+9] = (part2 >>>  7) & 0x01;
1828                 case 9 : this.view[offset+8] = size !== 9 ? (part2       ) | 0x80 : (part2       ) & 0x7F;
1829                 case 8 : this.view[offset+7] = size !== 8 ? (part1 >>> 21) | 0x80 : (part1 >>> 21) & 0x7F;
1830                 case 7 : this.view[offset+6] = size !== 7 ? (part1 >>> 14) | 0x80 : (part1 >>> 14) & 0x7F;
1831                 case 6 : this.view[offset+5] = size !== 6 ? (part1 >>>  7) | 0x80 : (part1 >>>  7) & 0x7F;
1832                 case 5 : this.view[offset+4] = size !== 5 ? (part1       ) | 0x80 : (part1       ) & 0x7F;
1833                 case 4 : this.view[offset+3] = size !== 4 ? (part0 >>> 21) | 0x80 : (part0 >>> 21) & 0x7F;
1834                 case 3 : this.view[offset+2] = size !== 3 ? (part0 >>> 14) | 0x80 : (part0 >>> 14) & 0x7F;
1835                 case 2 : this.view[offset+1] = size !== 2 ? (part0 >>>  7) | 0x80 : (part0 >>>  7) & 0x7F;
1836                 case 1 : this.view[offset  ] = size !== 1 ? (part0       ) | 0x80 : (part0       ) & 0x7F;
1837             }
1838             if (relative) {
1839                 this.offset += size;
1840                 return this;
1841             } else {
1842                 return size;
1843             }
1844         };
1846         /**
1847          * Writes a zig-zag encoded 64bit base 128 variable-length integer.
1848          * @param {number|Long} value Value to write
1849          * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by the number of bytes
1850          *  written if omitted.
1851          * @returns {!ByteBuffer|number} `this` if offset is omitted, else the actual number of bytes written.
1852          * @expose
1853          */
1854         ByteBufferPrototype.writeVarint64ZigZag = function(value, offset) {
1855             return this.writeVarint64(ByteBuffer.zigZagEncode64(value), offset);
1856         };
1858         /**
1859          * Reads a 64bit base 128 variable-length integer. Requires Long.js.
1860          * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by the number of bytes
1861          *  read if omitted.
1862          * @returns {!Long|!{value: Long, length: number}} The value read if offset is omitted, else the value read and
1863          *  the actual number of bytes read.
1864          * @throws {Error} If it's not a valid varint
1865          * @expose
1866          */
1867         ByteBufferPrototype.readVarint64 = function(offset) {
1868             var relative = typeof offset === 'undefined';
1869             if (relative) offset = this.offset;
1870             if (!this.noAssert) {
1871                 if (typeof offset !== 'number' || offset % 1 !== 0)
1872                     throw TypeError("Illegal offset: "+offset+" (not an integer)");
1873                 offset >>>= 0;
1874                 if (offset < 0 || offset + 1 > this.buffer.byteLength)
1875                     throw RangeError("Illegal offset: 0 <= "+offset+" (+"+1+") <= "+this.buffer.byteLength);
1876             }
1877             // ref: src/google/protobuf/io/coded_stream.cc
1878             var start = offset,
1879                 part0 = 0,
1880                 part1 = 0,
1881                 part2 = 0,
1882                 b  = 0;
1883             b = this.view[offset++]; part0  = (b & 0x7F)      ; if ( b & 0x80                                                   ) {
1884             b = this.view[offset++]; part0 |= (b & 0x7F) <<  7; if ((b & 0x80) || (this.noAssert && typeof b === 'undefined')) {
1885             b = this.view[offset++]; part0 |= (b & 0x7F) << 14; if ((b & 0x80) || (this.noAssert && typeof b === 'undefined')) {
1886             b = this.view[offset++]; part0 |= (b & 0x7F) << 21; if ((b & 0x80) || (this.noAssert && typeof b === 'undefined')) {
1887             b = this.view[offset++]; part1  = (b & 0x7F)      ; if ((b & 0x80) || (this.noAssert && typeof b === 'undefined')) {
1888             b = this.view[offset++]; part1 |= (b & 0x7F) <<  7; if ((b & 0x80) || (this.noAssert && typeof b === 'undefined')) {
1889             b = this.view[offset++]; part1 |= (b & 0x7F) << 14; if ((b & 0x80) || (this.noAssert && typeof b === 'undefined')) {
1890             b = this.view[offset++]; part1 |= (b & 0x7F) << 21; if ((b & 0x80) || (this.noAssert && typeof b === 'undefined')) {
1891             b = this.view[offset++]; part2  = (b & 0x7F)      ; if ((b & 0x80) || (this.noAssert && typeof b === 'undefined')) {
1892             b = this.view[offset++]; part2 |= (b & 0x7F) <<  7; if ((b & 0x80) || (this.noAssert && typeof b === 'undefined')) {
1893             throw Error("Buffer overrun"); }}}}}}}}}}
1894             var value = Long.fromBits(part0 | (part1 << 28), (part1 >>> 4) | (part2) << 24, false);
1895             if (relative) {
1896                 this.offset = offset;
1897                 return value;
1898             } else {
1899                 return {
1900                     'value': value,
1901                     'length': offset-start
1902                 };
1903             }
1904         };
1906         /**
1907          * Reads a zig-zag encoded 64bit base 128 variable-length integer. Requires Long.js.
1908          * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by the number of bytes
1909          *  read if omitted.
1910          * @returns {!Long|!{value: Long, length: number}} The value read if offset is omitted, else the value read and
1911          *  the actual number of bytes read.
1912          * @throws {Error} If it's not a valid varint
1913          * @expose
1914          */
1915         ByteBufferPrototype.readVarint64ZigZag = function(offset) {
1916             var val = this.readVarint64(offset);
1917             if (val && val['value'] instanceof Long)
1918                 val["value"] = ByteBuffer.zigZagDecode64(val["value"]);
1919             else
1920                 val = ByteBuffer.zigZagDecode64(val);
1921             return val;
1922         };
1924     } // Long
1927     // types/strings/cstring
1929     /**
1930      * Writes a NULL-terminated UTF8 encoded string. For this to work the specified string must not contain any NULL
1931      *  characters itself.
1932      * @param {string} str String to write
1933      * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by the number of bytes
1934      *  contained in `str` + 1 if omitted.
1935      * @returns {!ByteBuffer|number} this if offset is omitted, else the actual number of bytes written
1936      * @expose
1937      */
1938     ByteBufferPrototype.writeCString = function(str, offset) {
1939         var relative = typeof offset === 'undefined';
1940         if (relative) offset = this.offset;
1941         var i,
1942             k = str.length;
1943         if (!this.noAssert) {
1944             if (typeof str !== 'string')
1945                 throw TypeError("Illegal str: Not a string");
1946             for (i=0; i<k; ++i) {
1947                 if (str.charCodeAt(i) === 0)
1948                     throw RangeError("Illegal str: Contains NULL-characters");
1949             }
1950             if (typeof offset !== 'number' || offset % 1 !== 0)
1951                 throw TypeError("Illegal offset: "+offset+" (not an integer)");
1952             offset >>>= 0;
1953             if (offset < 0 || offset + 0 > this.buffer.byteLength)
1954                 throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength);
1955         }
1956         // UTF8 strings do not contain zero bytes in between except for the zero character, so:
1957         k = utfx.calculateUTF16asUTF8(stringSource(str))[1];
1958         offset += k+1;
1959         var capacity12 = this.buffer.byteLength;
1960         if (offset > capacity12)
1961             this.resize((capacity12 *= 2) > offset ? capacity12 : offset);
1962         offset -= k+1;
1963         utfx.encodeUTF16toUTF8(stringSource(str), function(b) {
1964             this.view[offset++] = b;
1965         }.bind(this));
1966         this.view[offset++] = 0;
1967         if (relative) {
1968             this.offset = offset;
1969             return this;
1970         }
1971         return k;
1972     };
1974     /**
1975      * Reads a NULL-terminated UTF8 encoded string. For this to work the string read must not contain any NULL characters
1976      *  itself.
1977      * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by the number of bytes
1978      *  read if omitted.
1979      * @returns {string|!{string: string, length: number}} The string read if offset is omitted, else the string
1980      *  read and the actual number of bytes read.
1981      * @expose
1982      */
1983     ByteBufferPrototype.readCString = function(offset) {
1984         var relative = typeof offset === 'undefined';
1985         if (relative) offset = this.offset;
1986         if (!this.noAssert) {
1987             if (typeof offset !== 'number' || offset % 1 !== 0)
1988                 throw TypeError("Illegal offset: "+offset+" (not an integer)");
1989             offset >>>= 0;
1990             if (offset < 0 || offset + 1 > this.buffer.byteLength)
1991                 throw RangeError("Illegal offset: 0 <= "+offset+" (+"+1+") <= "+this.buffer.byteLength);
1992         }
1993         var start = offset,
1994             temp;
1995         // UTF8 strings do not contain zero bytes in between except for the zero character itself, so:
1996         var sd, b = -1;
1997         utfx.decodeUTF8toUTF16(function() {
1998             if (b === 0) return null;
1999             if (offset >= this.limit)
2000                 throw RangeError("Illegal range: Truncated data, "+offset+" < "+this.limit);
2001             b = this.view[offset++];
2002             return b === 0 ? null : b;
2003         }.bind(this), sd = stringDestination(), true);
2004         if (relative) {
2005             this.offset = offset;
2006             return sd();
2007         } else {
2008             return {
2009                 "string": sd(),
2010                 "length": offset - start
2011             };
2012         }
2013     };
2015     // types/strings/istring
2017     /**
2018      * Writes a length as uint32 prefixed UTF8 encoded string.
2019      * @param {string} str String to write
2020      * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by the number of bytes
2021      *  written if omitted.
2022      * @returns {!ByteBuffer|number} `this` if `offset` is omitted, else the actual number of bytes written
2023      * @expose
2024      * @see ByteBuffer#writeVarint32
2025      */
2026     ByteBufferPrototype.writeIString = function(str, offset) {
2027         var relative = typeof offset === 'undefined';
2028         if (relative) offset = this.offset;
2029         if (!this.noAssert) {
2030             if (typeof str !== 'string')
2031                 throw TypeError("Illegal str: Not a string");
2032             if (typeof offset !== 'number' || offset % 1 !== 0)
2033                 throw TypeError("Illegal offset: "+offset+" (not an integer)");
2034             offset >>>= 0;
2035             if (offset < 0 || offset + 0 > this.buffer.byteLength)
2036                 throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength);
2037         }
2038         var start = offset,
2039             k;
2040         k = utfx.calculateUTF16asUTF8(stringSource(str), this.noAssert)[1];
2041         offset += 4+k;
2042         var capacity13 = this.buffer.byteLength;
2043         if (offset > capacity13)
2044             this.resize((capacity13 *= 2) > offset ? capacity13 : offset);
2045         offset -= 4+k;
2046         if (this.littleEndian) {
2047             this.view[offset+3] = (k >>> 24) & 0xFF;
2048             this.view[offset+2] = (k >>> 16) & 0xFF;
2049             this.view[offset+1] = (k >>>  8) & 0xFF;
2050             this.view[offset  ] =  k         & 0xFF;
2051         } else {
2052             this.view[offset  ] = (k >>> 24) & 0xFF;
2053             this.view[offset+1] = (k >>> 16) & 0xFF;
2054             this.view[offset+2] = (k >>>  8) & 0xFF;
2055             this.view[offset+3] =  k         & 0xFF;
2056         }
2057         offset += 4;
2058         utfx.encodeUTF16toUTF8(stringSource(str), function(b) {
2059             this.view[offset++] = b;
2060         }.bind(this));
2061         if (offset !== start + 4 + k)
2062             throw RangeError("Illegal range: Truncated data, "+offset+" == "+(offset+4+k));
2063         if (relative) {
2064             this.offset = offset;
2065             return this;
2066         }
2067         return offset - start;
2068     };
2070     /**
2071      * Reads a length as uint32 prefixed UTF8 encoded string.
2072      * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by the number of bytes
2073      *  read if omitted.
2074      * @returns {string|!{string: string, length: number}} The string read if offset is omitted, else the string
2075      *  read and the actual number of bytes read.
2076      * @expose
2077      * @see ByteBuffer#readVarint32
2078      */
2079     ByteBufferPrototype.readIString = function(offset) {
2080         var relative = typeof offset === 'undefined';
2081         if (relative) offset = this.offset;
2082         if (!this.noAssert) {
2083             if (typeof offset !== 'number' || offset % 1 !== 0)
2084                 throw TypeError("Illegal offset: "+offset+" (not an integer)");
2085             offset >>>= 0;
2086             if (offset < 0 || offset + 4 > this.buffer.byteLength)
2087                 throw RangeError("Illegal offset: 0 <= "+offset+" (+"+4+") <= "+this.buffer.byteLength);
2088         }
2089         var start = offset;
2090         var len = this.readUint32(offset);
2091         var str = this.readUTF8String(len, ByteBuffer.METRICS_BYTES, offset += 4);
2092         offset += str['length'];
2093         if (relative) {
2094             this.offset = offset;
2095             return str['string'];
2096         } else {
2097             return {
2098                 'string': str['string'],
2099                 'length': offset - start
2100             };
2101         }
2102     };
2104     // types/strings/utf8string
2106     /**
2107      * Metrics representing number of UTF8 characters. Evaluates to `c`.
2108      * @type {string}
2109      * @const
2110      * @expose
2111      */
2112     ByteBuffer.METRICS_CHARS = 'c';
2114     /**
2115      * Metrics representing number of bytes. Evaluates to `b`.
2116      * @type {string}
2117      * @const
2118      * @expose
2119      */
2120     ByteBuffer.METRICS_BYTES = 'b';
2122     /**
2123      * Writes an UTF8 encoded string.
2124      * @param {string} str String to write
2125      * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} if omitted.
2126      * @returns {!ByteBuffer|number} this if offset is omitted, else the actual number of bytes written.
2127      * @expose
2128      */
2129     ByteBufferPrototype.writeUTF8String = function(str, offset) {
2130         var relative = typeof offset === 'undefined';
2131         if (relative) offset = this.offset;
2132         if (!this.noAssert) {
2133             if (typeof offset !== 'number' || offset % 1 !== 0)
2134                 throw TypeError("Illegal offset: "+offset+" (not an integer)");
2135             offset >>>= 0;
2136             if (offset < 0 || offset + 0 > this.buffer.byteLength)
2137                 throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength);
2138         }
2139         var k;
2140         var start = offset;
2141         k = utfx.calculateUTF16asUTF8(stringSource(str))[1];
2142         offset += k;
2143         var capacity14 = this.buffer.byteLength;
2144         if (offset > capacity14)
2145             this.resize((capacity14 *= 2) > offset ? capacity14 : offset);
2146         offset -= k;
2147         utfx.encodeUTF16toUTF8(stringSource(str), function(b) {
2148             this.view[offset++] = b;
2149         }.bind(this));
2150         if (relative) {
2151             this.offset = offset;
2152             return this;
2153         }
2154         return offset - start;
2155     };
2157     /**
2158      * Writes an UTF8 encoded string. This is an alias of {@link ByteBuffer#writeUTF8String}.
2159      * @function
2160      * @param {string} str String to write
2161      * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} if omitted.
2162      * @returns {!ByteBuffer|number} this if offset is omitted, else the actual number of bytes written.
2163      * @expose
2164      */
2165     ByteBufferPrototype.writeString = ByteBufferPrototype.writeUTF8String;
2167     /**
2168      * Calculates the number of UTF8 characters of a string. JavaScript itself uses UTF-16, so that a string's
2169      *  `length` property does not reflect its actual UTF8 size if it contains code points larger than 0xFFFF.
2170      * @param {string} str String to calculate
2171      * @returns {number} Number of UTF8 characters
2172      * @expose
2173      */
2174     ByteBuffer.calculateUTF8Chars = function(str) {
2175         return utfx.calculateUTF16asUTF8(stringSource(str))[0];
2176     };
2178     /**
2179      * Calculates the number of UTF8 bytes of a string.
2180      * @param {string} str String to calculate
2181      * @returns {number} Number of UTF8 bytes
2182      * @expose
2183      */
2184     ByteBuffer.calculateUTF8Bytes = function(str) {
2185         return utfx.calculateUTF16asUTF8(stringSource(str))[1];
2186     };
2188     /**
2189      * Calculates the number of UTF8 bytes of a string. This is an alias of {@link ByteBuffer.calculateUTF8Bytes}.
2190      * @function
2191      * @param {string} str String to calculate
2192      * @returns {number} Number of UTF8 bytes
2193      * @expose
2194      */
2195     ByteBuffer.calculateString = ByteBuffer.calculateUTF8Bytes;
2197     /**
2198      * Reads an UTF8 encoded string.
2199      * @param {number} length Number of characters or bytes to read.
2200      * @param {string=} metrics Metrics specifying what `length` is meant to count. Defaults to
2201      *  {@link ByteBuffer.METRICS_CHARS}.
2202      * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by the number of bytes
2203      *  read if omitted.
2204      * @returns {string|!{string: string, length: number}} The string read if offset is omitted, else the string
2205      *  read and the actual number of bytes read.
2206      * @expose
2207      */
2208     ByteBufferPrototype.readUTF8String = function(length, metrics, offset) {
2209         if (typeof metrics === 'number') {
2210             offset = metrics;
2211             metrics = undefined;
2212         }
2213         var relative = typeof offset === 'undefined';
2214         if (relative) offset = this.offset;
2215         if (typeof metrics === 'undefined') metrics = ByteBuffer.METRICS_CHARS;
2216         if (!this.noAssert) {
2217             if (typeof length !== 'number' || length % 1 !== 0)
2218                 throw TypeError("Illegal length: "+length+" (not an integer)");
2219             length |= 0;
2220             if (typeof offset !== 'number' || offset % 1 !== 0)
2221                 throw TypeError("Illegal offset: "+offset+" (not an integer)");
2222             offset >>>= 0;
2223             if (offset < 0 || offset + 0 > this.buffer.byteLength)
2224                 throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength);
2225         }
2226         var i = 0,
2227             start = offset,
2228             sd;
2229         if (metrics === ByteBuffer.METRICS_CHARS) { // The same for node and the browser
2230             sd = stringDestination();
2231             utfx.decodeUTF8(function() {
2232                 return i < length && offset < this.limit ? this.view[offset++] : null;
2233             }.bind(this), function(cp) {
2234                 ++i; utfx.UTF8toUTF16(cp, sd);
2235             });
2236             if (i !== length)
2237                 throw RangeError("Illegal range: Truncated data, "+i+" == "+length);
2238             if (relative) {
2239                 this.offset = offset;
2240                 return sd();
2241             } else {
2242                 return {
2243                     "string": sd(),
2244                     "length": offset - start
2245                 };
2246             }
2247         } else if (metrics === ByteBuffer.METRICS_BYTES) {
2248             if (!this.noAssert) {
2249                 if (typeof offset !== 'number' || offset % 1 !== 0)
2250                     throw TypeError("Illegal offset: "+offset+" (not an integer)");
2251                 offset >>>= 0;
2252                 if (offset < 0 || offset + length > this.buffer.byteLength)
2253                     throw RangeError("Illegal offset: 0 <= "+offset+" (+"+length+") <= "+this.buffer.byteLength);
2254             }
2255             var k = offset + length;
2256             utfx.decodeUTF8toUTF16(function() {
2257                 return offset < k ? this.view[offset++] : null;
2258             }.bind(this), sd = stringDestination(), this.noAssert);
2259             if (offset !== k)
2260                 throw RangeError("Illegal range: Truncated data, "+offset+" == "+k);
2261             if (relative) {
2262                 this.offset = offset;
2263                 return sd();
2264             } else {
2265                 return {
2266                     'string': sd(),
2267                     'length': offset - start
2268                 };
2269             }
2270         } else
2271             throw TypeError("Unsupported metrics: "+metrics);
2272     };
2274     /**
2275      * Reads an UTF8 encoded string. This is an alias of {@link ByteBuffer#readUTF8String}.
2276      * @function
2277      * @param {number} length Number of characters or bytes to read
2278      * @param {number=} metrics Metrics specifying what `n` is meant to count. Defaults to
2279      *  {@link ByteBuffer.METRICS_CHARS}.
2280      * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by the number of bytes
2281      *  read if omitted.
2282      * @returns {string|!{string: string, length: number}} The string read if offset is omitted, else the string
2283      *  read and the actual number of bytes read.
2284      * @expose
2285      */
2286     ByteBufferPrototype.readString = ByteBufferPrototype.readUTF8String;
2288     // types/strings/vstring
2290     /**
2291      * Writes a length as varint32 prefixed UTF8 encoded string.
2292      * @param {string} str String to write
2293      * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by the number of bytes
2294      *  written if omitted.
2295      * @returns {!ByteBuffer|number} `this` if `offset` is omitted, else the actual number of bytes written
2296      * @expose
2297      * @see ByteBuffer#writeVarint32
2298      */
2299     ByteBufferPrototype.writeVString = function(str, offset) {
2300         var relative = typeof offset === 'undefined';
2301         if (relative) offset = this.offset;
2302         if (!this.noAssert) {
2303             if (typeof str !== 'string')
2304                 throw TypeError("Illegal str: Not a string");
2305             if (typeof offset !== 'number' || offset % 1 !== 0)
2306                 throw TypeError("Illegal offset: "+offset+" (not an integer)");
2307             offset >>>= 0;
2308             if (offset < 0 || offset + 0 > this.buffer.byteLength)
2309                 throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength);
2310         }
2311         var start = offset,
2312             k, l;
2313         k = utfx.calculateUTF16asUTF8(stringSource(str), this.noAssert)[1];
2314         l = ByteBuffer.calculateVarint32(k);
2315         offset += l+k;
2316         var capacity15 = this.buffer.byteLength;
2317         if (offset > capacity15)
2318             this.resize((capacity15 *= 2) > offset ? capacity15 : offset);
2319         offset -= l+k;
2320         offset += this.writeVarint32(k, offset);
2321         utfx.encodeUTF16toUTF8(stringSource(str), function(b) {
2322             this.view[offset++] = b;
2323         }.bind(this));
2324         if (offset !== start+k+l)
2325             throw RangeError("Illegal range: Truncated data, "+offset+" == "+(offset+k+l));
2326         if (relative) {
2327             this.offset = offset;
2328             return this;
2329         }
2330         return offset - start;
2331     };
2333     /**
2334      * Reads a length as varint32 prefixed UTF8 encoded string.
2335      * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by the number of bytes
2336      *  read if omitted.
2337      * @returns {string|!{string: string, length: number}} The string read if offset is omitted, else the string
2338      *  read and the actual number of bytes read.
2339      * @expose
2340      * @see ByteBuffer#readVarint32
2341      */
2342     ByteBufferPrototype.readVString = function(offset) {
2343         var relative = typeof offset === 'undefined';
2344         if (relative) offset = this.offset;
2345         if (!this.noAssert) {
2346             if (typeof offset !== 'number' || offset % 1 !== 0)
2347                 throw TypeError("Illegal offset: "+offset+" (not an integer)");
2348             offset >>>= 0;
2349             if (offset < 0 || offset + 1 > this.buffer.byteLength)
2350                 throw RangeError("Illegal offset: 0 <= "+offset+" (+"+1+") <= "+this.buffer.byteLength);
2351         }
2352         var start = offset;
2353         var len = this.readVarint32(offset);
2354         var str = this.readUTF8String(len['value'], ByteBuffer.METRICS_BYTES, offset += len['length']);
2355         offset += str['length'];
2356         if (relative) {
2357             this.offset = offset;
2358             return str['string'];
2359         } else {
2360             return {
2361                 'string': str['string'],
2362                 'length': offset - start
2363             };
2364         }
2365     };
2368     /**
2369      * Appends some data to this ByteBuffer. This will overwrite any contents behind the specified offset up to the appended
2370      *  data's length.
2371      * @param {!ByteBuffer|!ArrayBuffer|!Uint8Array|string} source Data to append. If `source` is a ByteBuffer, its offsets
2372      *  will be modified according to the performed read operation.
2373      * @param {(string|number)=} encoding Encoding if `data` is a string ("base64", "hex", "binary", defaults to "utf8")
2374      * @param {number=} offset Offset to append at. Will use and increase {@link ByteBuffer#offset} by the number of bytes
2375      *  written if omitted.
2376      * @returns {!ByteBuffer} this
2377      * @expose
2378      * @example A relative `<01 02>03.append(<04 05>)` will result in `<01 02 04 05>, 04 05|`
2379      * @example An absolute `<01 02>03.append(04 05>, 1)` will result in `<01 04>05, 04 05|`
2380      */
2381     ByteBufferPrototype.append = function(source, encoding, offset) {
2382         if (typeof encoding === 'number' || typeof encoding !== 'string') {
2383             offset = encoding;
2384             encoding = undefined;
2385         }
2386         var relative = typeof offset === 'undefined';
2387         if (relative) offset = this.offset;
2388         if (!this.noAssert) {
2389             if (typeof offset !== 'number' || offset % 1 !== 0)
2390                 throw TypeError("Illegal offset: "+offset+" (not an integer)");
2391             offset >>>= 0;
2392             if (offset < 0 || offset + 0 > this.buffer.byteLength)
2393                 throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength);
2394         }
2395         if (!(source instanceof ByteBuffer))
2396             source = ByteBuffer.wrap(source, encoding);
2397         var length = source.limit - source.offset;
2398         if (length <= 0) return this; // Nothing to append
2399         offset += length;
2400         var capacity16 = this.buffer.byteLength;
2401         if (offset > capacity16)
2402             this.resize((capacity16 *= 2) > offset ? capacity16 : offset);
2403         offset -= length;
2404         this.view.set(source.view.subarray(source.offset, source.limit), offset);
2405         source.offset += length;
2406         if (relative) this.offset += length;
2407         return this;
2408     };
2410     /**
2411      * Appends this ByteBuffer's contents to another ByteBuffer. This will overwrite any contents at and after the
2412         specified offset up to the length of this ByteBuffer's data.
2413      * @param {!ByteBuffer} target Target ByteBuffer
2414      * @param {number=} offset Offset to append to. Will use and increase {@link ByteBuffer#offset} by the number of bytes
2415      *  read if omitted.
2416      * @returns {!ByteBuffer} this
2417      * @expose
2418      * @see ByteBuffer#append
2419      */
2420     ByteBufferPrototype.appendTo = function(target, offset) {
2421         target.append(this, offset);
2422         return this;
2423     };
2425     /**
2426      * Enables or disables assertions of argument types and offsets. Assertions are enabled by default but you can opt to
2427      *  disable them if your code already makes sure that everything is valid.
2428      * @param {boolean} assert `true` to enable assertions, otherwise `false`
2429      * @returns {!ByteBuffer} this
2430      * @expose
2431      */
2432     ByteBufferPrototype.assert = function(assert) {
2433         this.noAssert = !assert;
2434         return this;
2435     };
2437     /**
2438      * Gets the capacity of this ByteBuffer's backing buffer.
2439      * @returns {number} Capacity of the backing buffer
2440      * @expose
2441      */
2442     ByteBufferPrototype.capacity = function() {
2443         return this.buffer.byteLength;
2444     };
2445     /**
2446      * Clears this ByteBuffer's offsets by setting {@link ByteBuffer#offset} to `0` and {@link ByteBuffer#limit} to the
2447      *  backing buffer's capacity. Discards {@link ByteBuffer#markedOffset}.
2448      * @returns {!ByteBuffer} this
2449      * @expose
2450      */
2451     ByteBufferPrototype.clear = function() {
2452         this.offset = 0;
2453         this.limit = this.buffer.byteLength;
2454         this.markedOffset = -1;
2455         return this;
2456     };
2458     /**
2459      * Creates a cloned instance of this ByteBuffer, preset with this ByteBuffer's values for {@link ByteBuffer#offset},
2460      *  {@link ByteBuffer#markedOffset} and {@link ByteBuffer#limit}.
2461      * @param {boolean=} copy Whether to copy the backing buffer or to return another view on the same, defaults to `false`
2462      * @returns {!ByteBuffer} Cloned instance
2463      * @expose
2464      */
2465     ByteBufferPrototype.clone = function(copy) {
2466         var bb = new ByteBuffer(0, this.littleEndian, this.noAssert);
2467         if (copy) {
2468             bb.buffer = new ArrayBuffer(this.buffer.byteLength);
2469             bb.view = new Uint8Array(bb.buffer);
2470         } else {
2471             bb.buffer = this.buffer;
2472             bb.view = this.view;
2473         }
2474         bb.offset = this.offset;
2475         bb.markedOffset = this.markedOffset;
2476         bb.limit = this.limit;
2477         return bb;
2478     };
2480     /**
2481      * Compacts this ByteBuffer to be backed by a {@link ByteBuffer#buffer} of its contents' length. Contents are the bytes
2482      *  between {@link ByteBuffer#offset} and {@link ByteBuffer#limit}. Will set `offset = 0` and `limit = capacity` and
2483      *  adapt {@link ByteBuffer#markedOffset} to the same relative position if set.
2484      * @param {number=} begin Offset to start at, defaults to {@link ByteBuffer#offset}
2485      * @param {number=} end Offset to end at, defaults to {@link ByteBuffer#limit}
2486      * @returns {!ByteBuffer} this
2487      * @expose
2488      */
2489     ByteBufferPrototype.compact = function(begin, end) {
2490         if (typeof begin === 'undefined') begin = this.offset;
2491         if (typeof end === 'undefined') end = this.limit;
2492         if (!this.noAssert) {
2493             if (typeof begin !== 'number' || begin % 1 !== 0)
2494                 throw TypeError("Illegal begin: Not an integer");
2495             begin >>>= 0;
2496             if (typeof end !== 'number' || end % 1 !== 0)
2497                 throw TypeError("Illegal end: Not an integer");
2498             end >>>= 0;
2499             if (begin < 0 || begin > end || end > this.buffer.byteLength)
2500                 throw RangeError("Illegal range: 0 <= "+begin+" <= "+end+" <= "+this.buffer.byteLength);
2501         }
2502         if (begin === 0 && end === this.buffer.byteLength)
2503             return this; // Already compacted
2504         var len = end - begin;
2505         if (len === 0) {
2506             this.buffer = EMPTY_BUFFER;
2507             this.view = null;
2508             if (this.markedOffset >= 0) this.markedOffset -= begin;
2509             this.offset = 0;
2510             this.limit = 0;
2511             return this;
2512         }
2513         var buffer = new ArrayBuffer(len);
2514         var view = new Uint8Array(buffer);
2515         view.set(this.view.subarray(begin, end));
2516         this.buffer = buffer;
2517         this.view = view;
2518         if (this.markedOffset >= 0) this.markedOffset -= begin;
2519         this.offset = 0;
2520         this.limit = len;
2521         return this;
2522     };
2524     /**
2525      * Creates a copy of this ByteBuffer's contents. Contents are the bytes between {@link ByteBuffer#offset} and
2526      *  {@link ByteBuffer#limit}.
2527      * @param {number=} begin Begin offset, defaults to {@link ByteBuffer#offset}.
2528      * @param {number=} end End offset, defaults to {@link ByteBuffer#limit}.
2529      * @returns {!ByteBuffer} Copy
2530      * @expose
2531      */
2532     ByteBufferPrototype.copy = function(begin, end) {
2533         if (typeof begin === 'undefined') begin = this.offset;
2534         if (typeof end === 'undefined') end = this.limit;
2535         if (!this.noAssert) {
2536             if (typeof begin !== 'number' || begin % 1 !== 0)
2537                 throw TypeError("Illegal begin: Not an integer");
2538             begin >>>= 0;
2539             if (typeof end !== 'number' || end % 1 !== 0)
2540                 throw TypeError("Illegal end: Not an integer");
2541             end >>>= 0;
2542             if (begin < 0 || begin > end || end > this.buffer.byteLength)
2543                 throw RangeError("Illegal range: 0 <= "+begin+" <= "+end+" <= "+this.buffer.byteLength);
2544         }
2545         if (begin === end)
2546             return new ByteBuffer(0, this.littleEndian, this.noAssert);
2547         var capacity = end - begin,
2548             bb = new ByteBuffer(capacity, this.littleEndian, this.noAssert);
2549         bb.offset = 0;
2550         bb.limit = capacity;
2551         if (bb.markedOffset >= 0) bb.markedOffset -= begin;
2552         this.copyTo(bb, 0, begin, end);
2553         return bb;
2554     };
2556     /**
2557      * Copies this ByteBuffer's contents to another ByteBuffer. Contents are the bytes between {@link ByteBuffer#offset} and
2558      *  {@link ByteBuffer#limit}.
2559      * @param {!ByteBuffer} target Target ByteBuffer
2560      * @param {number=} targetOffset Offset to copy to. Will use and increase the target's {@link ByteBuffer#offset}
2561      *  by the number of bytes copied if omitted.
2562      * @param {number=} sourceOffset Offset to start copying from. Will use and increase {@link ByteBuffer#offset} by the
2563      *  number of bytes copied if omitted.
2564      * @param {number=} sourceLimit Offset to end copying from, defaults to {@link ByteBuffer#limit}
2565      * @returns {!ByteBuffer} this
2566      * @expose
2567      */
2568     ByteBufferPrototype.copyTo = function(target, targetOffset, sourceOffset, sourceLimit) {
2569         var relative,
2570             targetRelative;
2571         if (!this.noAssert) {
2572             if (!ByteBuffer.isByteBuffer(target))
2573                 throw TypeError("Illegal target: Not a ByteBuffer");
2574         }
2575         targetOffset = (targetRelative = typeof targetOffset === 'undefined') ? target.offset : targetOffset | 0;
2576         sourceOffset = (relative = typeof sourceOffset === 'undefined') ? this.offset : sourceOffset | 0;
2577         sourceLimit = typeof sourceLimit === 'undefined' ? this.limit : sourceLimit | 0;
2579         if (targetOffset < 0 || targetOffset > target.buffer.byteLength)
2580             throw RangeError("Illegal target range: 0 <= "+targetOffset+" <= "+target.buffer.byteLength);
2581         if (sourceOffset < 0 || sourceLimit > this.buffer.byteLength)
2582             throw RangeError("Illegal source range: 0 <= "+sourceOffset+" <= "+this.buffer.byteLength);
2584         var len = sourceLimit - sourceOffset;
2585         if (len === 0)
2586             return target; // Nothing to copy
2588         target.ensureCapacity(targetOffset + len);
2590         target.view.set(this.view.subarray(sourceOffset, sourceLimit), targetOffset);
2592         if (relative) this.offset += len;
2593         if (targetRelative) target.offset += len;
2595         return this;
2596     };
2598     /**
2599      * Makes sure that this ByteBuffer is backed by a {@link ByteBuffer#buffer} of at least the specified capacity. If the
2600      *  current capacity is exceeded, it will be doubled. If double the current capacity is less than the required capacity,
2601      *  the required capacity will be used instead.
2602      * @param {number} capacity Required capacity
2603      * @returns {!ByteBuffer} this
2604      * @expose
2605      */
2606     ByteBufferPrototype.ensureCapacity = function(capacity) {
2607         var current = this.buffer.byteLength;
2608         if (current < capacity)
2609             return this.resize((current *= 2) > capacity ? current : capacity);
2610         return this;
2611     };
2613     /**
2614      * Overwrites this ByteBuffer's contents with the specified value. Contents are the bytes between
2615      *  {@link ByteBuffer#offset} and {@link ByteBuffer#limit}.
2616      * @param {number|string} value Byte value to fill with. If given as a string, the first character is used.
2617      * @param {number=} begin Begin offset. Will use and increase {@link ByteBuffer#offset} by the number of bytes
2618      *  written if omitted. defaults to {@link ByteBuffer#offset}.
2619      * @param {number=} end End offset, defaults to {@link ByteBuffer#limit}.
2620      * @returns {!ByteBuffer} this
2621      * @expose
2622      * @example `someByteBuffer.clear().fill(0)` fills the entire backing buffer with zeroes
2623      */
2624     ByteBufferPrototype.fill = function(value, begin, end) {
2625         var relative = typeof begin === 'undefined';
2626         if (relative) begin = this.offset;
2627         if (typeof value === 'string' && value.length > 0)
2628             value = value.charCodeAt(0);
2629         if (typeof begin === 'undefined') begin = this.offset;
2630         if (typeof end === 'undefined') end = this.limit;
2631         if (!this.noAssert) {
2632             if (typeof value !== 'number' || value % 1 !== 0)
2633                 throw TypeError("Illegal value: "+value+" (not an integer)");
2634             value |= 0;
2635             if (typeof begin !== 'number' || begin % 1 !== 0)
2636                 throw TypeError("Illegal begin: Not an integer");
2637             begin >>>= 0;
2638             if (typeof end !== 'number' || end % 1 !== 0)
2639                 throw TypeError("Illegal end: Not an integer");
2640             end >>>= 0;
2641             if (begin < 0 || begin > end || end > this.buffer.byteLength)
2642                 throw RangeError("Illegal range: 0 <= "+begin+" <= "+end+" <= "+this.buffer.byteLength);
2643         }
2644         if (begin >= end)
2645             return this; // Nothing to fill
2646         while (begin < end) this.view[begin++] = value;
2647         if (relative) this.offset = begin;
2648         return this;
2649     };
2651     /**
2652      * Makes this ByteBuffer ready for a new sequence of write or relative read operations. Sets `limit = offset` and
2653      *  `offset = 0`. Make sure always to flip a ByteBuffer when all relative read or write operations are complete.
2654      * @returns {!ByteBuffer} this
2655      * @expose
2656      */
2657     ByteBufferPrototype.flip = function() {
2658         this.limit = this.offset;
2659         this.offset = 0;
2660         return this;
2661     };
2662     /**
2663      * Marks an offset on this ByteBuffer to be used later.
2664      * @param {number=} offset Offset to mark. Defaults to {@link ByteBuffer#offset}.
2665      * @returns {!ByteBuffer} this
2666      * @throws {TypeError} If `offset` is not a valid number
2667      * @throws {RangeError} If `offset` is out of bounds
2668      * @see ByteBuffer#reset
2669      * @expose
2670      */
2671     ByteBufferPrototype.mark = function(offset) {
2672         offset = typeof offset === 'undefined' ? this.offset : offset;
2673         if (!this.noAssert) {
2674             if (typeof offset !== 'number' || offset % 1 !== 0)
2675                 throw TypeError("Illegal offset: "+offset+" (not an integer)");
2676             offset >>>= 0;
2677             if (offset < 0 || offset + 0 > this.buffer.byteLength)
2678                 throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength);
2679         }
2680         this.markedOffset = offset;
2681         return this;
2682     };
2683     /**
2684      * Sets the byte order.
2685      * @param {boolean} littleEndian `true` for little endian byte order, `false` for big endian
2686      * @returns {!ByteBuffer} this
2687      * @expose
2688      */
2689     ByteBufferPrototype.order = function(littleEndian) {
2690         if (!this.noAssert) {
2691             if (typeof littleEndian !== 'boolean')
2692                 throw TypeError("Illegal littleEndian: Not a boolean");
2693         }
2694         this.littleEndian = !!littleEndian;
2695         return this;
2696     };
2698     /**
2699      * Switches (to) little endian byte order.
2700      * @param {boolean=} littleEndian Defaults to `true`, otherwise uses big endian
2701      * @returns {!ByteBuffer} this
2702      * @expose
2703      */
2704     ByteBufferPrototype.LE = function(littleEndian) {
2705         this.littleEndian = typeof littleEndian !== 'undefined' ? !!littleEndian : true;
2706         return this;
2707     };
2709     /**
2710      * Switches (to) big endian byte order.
2711      * @param {boolean=} bigEndian Defaults to `true`, otherwise uses little endian
2712      * @returns {!ByteBuffer} this
2713      * @expose
2714      */
2715     ByteBufferPrototype.BE = function(bigEndian) {
2716         this.littleEndian = typeof bigEndian !== 'undefined' ? !bigEndian : false;
2717         return this;
2718     };
2719     /**
2720      * Prepends some data to this ByteBuffer. This will overwrite any contents before the specified offset up to the
2721      *  prepended data's length. If there is not enough space available before the specified `offset`, the backing buffer
2722      *  will be resized and its contents moved accordingly.
2723      * @param {!ByteBuffer|string|!ArrayBuffer} source Data to prepend. If `source` is a ByteBuffer, its offset will be
2724      *  modified according to the performed read operation.
2725      * @param {(string|number)=} encoding Encoding if `data` is a string ("base64", "hex", "binary", defaults to "utf8")
2726      * @param {number=} offset Offset to prepend at. Will use and decrease {@link ByteBuffer#offset} by the number of bytes
2727      *  prepended if omitted.
2728      * @returns {!ByteBuffer} this
2729      * @expose
2730      * @example A relative `00<01 02 03>.prepend(<04 05>)` results in `<04 05 01 02 03>, 04 05|`
2731      * @example An absolute `00<01 02 03>.prepend(<04 05>, 2)` results in `04<05 02 03>, 04 05|`
2732      */
2733     ByteBufferPrototype.prepend = function(source, encoding, offset) {
2734         if (typeof encoding === 'number' || typeof encoding !== 'string') {
2735             offset = encoding;
2736             encoding = undefined;
2737         }
2738         var relative = typeof offset === 'undefined';
2739         if (relative) offset = this.offset;
2740         if (!this.noAssert) {
2741             if (typeof offset !== 'number' || offset % 1 !== 0)
2742                 throw TypeError("Illegal offset: "+offset+" (not an integer)");
2743             offset >>>= 0;
2744             if (offset < 0 || offset + 0 > this.buffer.byteLength)
2745                 throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength);
2746         }
2747         if (!(source instanceof ByteBuffer))
2748             source = ByteBuffer.wrap(source, encoding);
2749         var len = source.limit - source.offset;
2750         if (len <= 0) return this; // Nothing to prepend
2751         var diff = len - offset;
2752         if (diff > 0) { // Not enough space before offset, so resize + move
2753             var buffer = new ArrayBuffer(this.buffer.byteLength + diff);
2754             var view = new Uint8Array(buffer);
2755             view.set(this.view.subarray(offset, this.buffer.byteLength), len);
2756             this.buffer = buffer;
2757             this.view = view;
2758             this.offset += diff;
2759             if (this.markedOffset >= 0) this.markedOffset += diff;
2760             this.limit += diff;
2761             offset += diff;
2762         } else {
2763             var arrayView = new Uint8Array(this.buffer);
2764         }
2765         this.view.set(source.view.subarray(source.offset, source.limit), offset - len);
2767         source.offset = source.limit;
2768         if (relative)
2769             this.offset -= len;
2770         return this;
2771     };
2773     /**
2774      * Prepends this ByteBuffer to another ByteBuffer. This will overwrite any contents before the specified offset up to the
2775      *  prepended data's length. If there is not enough space available before the specified `offset`, the backing buffer
2776      *  will be resized and its contents moved accordingly.
2777      * @param {!ByteBuffer} target Target ByteBuffer
2778      * @param {number=} offset Offset to prepend at. Will use and decrease {@link ByteBuffer#offset} by the number of bytes
2779      *  prepended if omitted.
2780      * @returns {!ByteBuffer} this
2781      * @expose
2782      * @see ByteBuffer#prepend
2783      */
2784     ByteBufferPrototype.prependTo = function(target, offset) {
2785         target.prepend(this, offset);
2786         return this;
2787     };
2788     /**
2789      * Prints debug information about this ByteBuffer's contents.
2790      * @param {function(string)=} out Output function to call, defaults to console.log
2791      * @expose
2792      */
2793     ByteBufferPrototype.printDebug = function(out) {
2794         if (typeof out !== 'function') out = console.log.bind(console);
2795         out(
2796             this.toString()+"\n"+
2797             "-------------------------------------------------------------------\n"+
2798             this.toDebug(/* columns */ true)
2799         );
2800     };
2802     /**
2803      * Gets the number of remaining readable bytes. Contents are the bytes between {@link ByteBuffer#offset} and
2804      *  {@link ByteBuffer#limit}, so this returns `limit - offset`.
2805      * @returns {number} Remaining readable bytes. May be negative if `offset > limit`.
2806      * @expose
2807      */
2808     ByteBufferPrototype.remaining = function() {
2809         return this.limit - this.offset;
2810     };
2811     /**
2812      * Resets this ByteBuffer's {@link ByteBuffer#offset}. If an offset has been marked through {@link ByteBuffer#mark}
2813      *  before, `offset` will be set to {@link ByteBuffer#markedOffset}, which will then be discarded. If no offset has been
2814      *  marked, sets `offset = 0`.
2815      * @returns {!ByteBuffer} this
2816      * @see ByteBuffer#mark
2817      * @expose
2818      */
2819     ByteBufferPrototype.reset = function() {
2820         if (this.markedOffset >= 0) {
2821             this.offset = this.markedOffset;
2822             this.markedOffset = -1;
2823         } else {
2824             this.offset = 0;
2825         }
2826         return this;
2827     };
2828     /**
2829      * Resizes this ByteBuffer to be backed by a buffer of at least the given capacity. Will do nothing if already that
2830      *  large or larger.
2831      * @param {number} capacity Capacity required
2832      * @returns {!ByteBuffer} this
2833      * @throws {TypeError} If `capacity` is not a number
2834      * @throws {RangeError} If `capacity < 0`
2835      * @expose
2836      */
2837     ByteBufferPrototype.resize = function(capacity) {
2838         if (!this.noAssert) {
2839             if (typeof capacity !== 'number' || capacity % 1 !== 0)
2840                 throw TypeError("Illegal capacity: "+capacity+" (not an integer)");
2841             capacity |= 0;
2842             if (capacity < 0)
2843                 throw RangeError("Illegal capacity: 0 <= "+capacity);
2844         }
2845         if (this.buffer.byteLength < capacity) {
2846             var buffer = new ArrayBuffer(capacity);
2847             var view = new Uint8Array(buffer);
2848             view.set(this.view);
2849             this.buffer = buffer;
2850             this.view = view;
2851         }
2852         return this;
2853     };
2854     /**
2855      * Reverses this ByteBuffer's contents.
2856      * @param {number=} begin Offset to start at, defaults to {@link ByteBuffer#offset}
2857      * @param {number=} end Offset to end at, defaults to {@link ByteBuffer#limit}
2858      * @returns {!ByteBuffer} this
2859      * @expose
2860      */
2861     ByteBufferPrototype.reverse = function(begin, end) {
2862         if (typeof begin === 'undefined') begin = this.offset;
2863         if (typeof end === 'undefined') end = this.limit;
2864         if (!this.noAssert) {
2865             if (typeof begin !== 'number' || begin % 1 !== 0)
2866                 throw TypeError("Illegal begin: Not an integer");
2867             begin >>>= 0;
2868             if (typeof end !== 'number' || end % 1 !== 0)
2869                 throw TypeError("Illegal end: Not an integer");
2870             end >>>= 0;
2871             if (begin < 0 || begin > end || end > this.buffer.byteLength)
2872                 throw RangeError("Illegal range: 0 <= "+begin+" <= "+end+" <= "+this.buffer.byteLength);
2873         }
2874         if (begin === end)
2875             return this; // Nothing to reverse
2876         Array.prototype.reverse.call(this.view.subarray(begin, end));
2877         return this;
2878     };
2879     /**
2880      * Skips the next `length` bytes. This will just advance
2881      * @param {number} length Number of bytes to skip. May also be negative to move the offset back.
2882      * @returns {!ByteBuffer} this
2883      * @expose
2884      */
2885     ByteBufferPrototype.skip = function(length) {
2886         if (!this.noAssert) {
2887             if (typeof length !== 'number' || length % 1 !== 0)
2888                 throw TypeError("Illegal length: "+length+" (not an integer)");
2889             length |= 0;
2890         }
2891         var offset = this.offset + length;
2892         if (!this.noAssert) {
2893             if (offset < 0 || offset > this.buffer.byteLength)
2894                 throw RangeError("Illegal length: 0 <= "+this.offset+" + "+length+" <= "+this.buffer.byteLength);
2895         }
2896         this.offset = offset;
2897         return this;
2898     };
2900     /**
2901      * Slices this ByteBuffer by creating a cloned instance with `offset = begin` and `limit = end`.
2902      * @param {number=} begin Begin offset, defaults to {@link ByteBuffer#offset}.
2903      * @param {number=} end End offset, defaults to {@link ByteBuffer#limit}.
2904      * @returns {!ByteBuffer} Clone of this ByteBuffer with slicing applied, backed by the same {@link ByteBuffer#buffer}
2905      * @expose
2906      */
2907     ByteBufferPrototype.slice = function(begin, end) {
2908         if (typeof begin === 'undefined') begin = this.offset;
2909         if (typeof end === 'undefined') end = this.limit;
2910         if (!this.noAssert) {
2911             if (typeof begin !== 'number' || begin % 1 !== 0)
2912                 throw TypeError("Illegal begin: Not an integer");
2913             begin >>>= 0;
2914             if (typeof end !== 'number' || end % 1 !== 0)
2915                 throw TypeError("Illegal end: Not an integer");
2916             end >>>= 0;
2917             if (begin < 0 || begin > end || end > this.buffer.byteLength)
2918                 throw RangeError("Illegal range: 0 <= "+begin+" <= "+end+" <= "+this.buffer.byteLength);
2919         }
2920         var bb = this.clone();
2921         bb.offset = begin;
2922         bb.limit = end;
2923         return bb;
2924     };
2925     /**
2926      * Returns a copy of the backing buffer that contains this ByteBuffer's contents. Contents are the bytes between
2927      *  {@link ByteBuffer#offset} and {@link ByteBuffer#limit}.
2928      * @param {boolean=} forceCopy If `true` returns a copy, otherwise returns a view referencing the same memory if
2929      *  possible. Defaults to `false`
2930      * @returns {!ArrayBuffer} Contents as an ArrayBuffer
2931      * @expose
2932      */
2933     ByteBufferPrototype.toBuffer = function(forceCopy) {
2934         var offset = this.offset,
2935             limit = this.limit;
2936         if (!this.noAssert) {
2937             if (typeof offset !== 'number' || offset % 1 !== 0)
2938                 throw TypeError("Illegal offset: Not an integer");
2939             offset >>>= 0;
2940             if (typeof limit !== 'number' || limit % 1 !== 0)
2941                 throw TypeError("Illegal limit: Not an integer");
2942             limit >>>= 0;
2943             if (offset < 0 || offset > limit || limit > this.buffer.byteLength)
2944                 throw RangeError("Illegal range: 0 <= "+offset+" <= "+limit+" <= "+this.buffer.byteLength);
2945         }
2946         // NOTE: It's not possible to have another ArrayBuffer reference the same memory as the backing buffer. This is
2947         // possible with Uint8Array#subarray only, but we have to return an ArrayBuffer by contract. So:
2948         if (!forceCopy && offset === 0 && limit === this.buffer.byteLength)
2949             return this.buffer;
2950         if (offset === limit)
2951             return EMPTY_BUFFER;
2952         var buffer = new ArrayBuffer(limit - offset);
2953         new Uint8Array(buffer).set(new Uint8Array(this.buffer).subarray(offset, limit), 0);
2954         return buffer;
2955     };
2957     /**
2958      * Returns a raw buffer compacted to contain this ByteBuffer's contents. Contents are the bytes between
2959      *  {@link ByteBuffer#offset} and {@link ByteBuffer#limit}. This is an alias of {@link ByteBuffer#toBuffer}.
2960      * @function
2961      * @param {boolean=} forceCopy If `true` returns a copy, otherwise returns a view referencing the same memory.
2962      *  Defaults to `false`
2963      * @returns {!ArrayBuffer} Contents as an ArrayBuffer
2964      * @expose
2965      */
2966     ByteBufferPrototype.toArrayBuffer = ByteBufferPrototype.toBuffer;
2968     /**
2969      * Converts the ByteBuffer's contents to a string.
2970      * @param {string=} encoding Output encoding. Returns an informative string representation if omitted but also allows
2971      *  direct conversion to "utf8", "hex", "base64" and "binary" encoding. "debug" returns a hex representation with
2972      *  highlighted offsets.
2973      * @param {number=} begin Offset to begin at, defaults to {@link ByteBuffer#offset}
2974      * @param {number=} end Offset to end at, defaults to {@link ByteBuffer#limit}
2975      * @returns {string} String representation
2976      * @throws {Error} If `encoding` is invalid
2977      * @expose
2978      */
2979     ByteBufferPrototype.toString = function(encoding, begin, end) {
2980         if (typeof encoding === 'undefined')
2981             return "ByteBufferAB(offset="+this.offset+",markedOffset="+this.markedOffset+",limit="+this.limit+",capacity="+this.capacity()+")";
2982         if (typeof encoding === 'number')
2983             encoding = "utf8",
2984             begin = encoding,
2985             end = begin;
2986         switch (encoding) {
2987             case "utf8":
2988                 return this.toUTF8(begin, end);
2989             case "base64":
2990                 return this.toBase64(begin, end);
2991             case "hex":
2992                 return this.toHex(begin, end);
2993             case "binary":
2994                 return this.toBinary(begin, end);
2995             case "debug":
2996                 return this.toDebug();
2997             case "columns":
2998                 return this.toColumns();
2999             default:
3000                 throw Error("Unsupported encoding: "+encoding);
3001         }
3002     };
3004     // lxiv-embeddable
3006     /**
3007      * lxiv-embeddable (c) 2014 Daniel Wirtz <dcode@dcode.io>
3008      * Released under the Apache License, Version 2.0
3009      * see: https://github.com/dcodeIO/lxiv for details
3010      */
3011     var lxiv = function() {
3012         "use strict";
3014         /**
3015          * lxiv namespace.
3016          * @type {!Object.<string,*>}
3017          * @exports lxiv
3018          */
3019         var lxiv = {};
3021         /**
3022          * Character codes for output.
3023          * @type {!Array.<number>}
3024          * @inner
3025          */
3026         var aout = [
3027             65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80,
3028             81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 97, 98, 99, 100, 101, 102,
3029             103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118,
3030             119, 120, 121, 122, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 43, 47
3031         ];
3033         /**
3034          * Character codes for input.
3035          * @type {!Array.<number>}
3036          * @inner
3037          */
3038         var ain = [];
3039         for (var i=0, k=aout.length; i<k; ++i)
3040             ain[aout[i]] = i;
3042         /**
3043          * Encodes bytes to base64 char codes.
3044          * @param {!function():number|null} src Bytes source as a function returning the next byte respectively `null` if
3045          *  there are no more bytes left.
3046          * @param {!function(number)} dst Characters destination as a function successively called with each encoded char
3047          *  code.
3048          */
3049         lxiv.encode = function(src, dst) {
3050             var b, t;
3051             while ((b = src()) !== null) {
3052                 dst(aout[(b>>2)&0x3f]);
3053                 t = (b&0x3)<<4;
3054                 if ((b = src()) !== null) {
3055                     t |= (b>>4)&0xf;
3056                     dst(aout[(t|((b>>4)&0xf))&0x3f]);
3057                     t = (b&0xf)<<2;
3058                     if ((b = src()) !== null)
3059                         dst(aout[(t|((b>>6)&0x3))&0x3f]),
3060                         dst(aout[b&0x3f]);
3061                     else
3062                         dst(aout[t&0x3f]),
3063                         dst(61);
3064                 } else
3065                     dst(aout[t&0x3f]),
3066                     dst(61),
3067                     dst(61);
3068             }
3069         };
3071         /**
3072          * Decodes base64 char codes to bytes.
3073          * @param {!function():number|null} src Characters source as a function returning the next char code respectively
3074          *  `null` if there are no more characters left.
3075          * @param {!function(number)} dst Bytes destination as a function successively called with the next byte.
3076          * @throws {Error} If a character code is invalid
3077          */
3078         lxiv.decode = function(src, dst) {
3079             var c, t1, t2;
3080             function fail(c) {
3081                 throw Error("Illegal character code: "+c);
3082             }
3083             while ((c = src()) !== null) {
3084                 t1 = ain[c];
3085                 if (typeof t1 === 'undefined') fail(c);
3086                 if ((c = src()) !== null) {
3087                     t2 = ain[c];
3088                     if (typeof t2 === 'undefined') fail(c);
3089                     dst((t1<<2)>>>0|(t2&0x30)>>4);
3090                     if ((c = src()) !== null) {
3091                         t1 = ain[c];
3092                         if (typeof t1 === 'undefined')
3093                             if (c === 61) break; else fail(c);
3094                         dst(((t2&0xf)<<4)>>>0|(t1&0x3c)>>2);
3095                         if ((c = src()) !== null) {
3096                             t2 = ain[c];
3097                             if (typeof t2 === 'undefined')
3098                                 if (c === 61) break; else fail(c);
3099                             dst(((t1&0x3)<<6)>>>0|t2);
3100                         }
3101                     }
3102                 }
3103             }
3104         };
3106         /**
3107          * Tests if a string is valid base64.
3108          * @param {string} str String to test
3109          * @returns {boolean} `true` if valid, otherwise `false`
3110          */
3111         lxiv.test = function(str) {
3112             return /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/.test(str);
3113         };
3115         return lxiv;
3116     }();
3118     // encodings/base64
3120     /**
3121      * Encodes this ByteBuffer's contents to a base64 encoded string.
3122      * @param {number=} begin Offset to begin at, defaults to {@link ByteBuffer#offset}.
3123      * @param {number=} end Offset to end at, defaults to {@link ByteBuffer#limit}.
3124      * @returns {string} Base64 encoded string
3125      * @throws {RangeError} If `begin` or `end` is out of bounds
3126      * @expose
3127      */
3128     ByteBufferPrototype.toBase64 = function(begin, end) {
3129         if (typeof begin === 'undefined')
3130             begin = this.offset;
3131         if (typeof end === 'undefined')
3132             end = this.limit;
3133         begin = begin | 0; end = end | 0;
3134         if (begin < 0 || end > this.capacity || begin > end)
3135             throw RangeError("begin, end");
3136         var sd; lxiv.encode(function() {
3137             return begin < end ? this.view[begin++] : null;
3138         }.bind(this), sd = stringDestination());
3139         return sd();
3140     };
3142     /**
3143      * Decodes a base64 encoded string to a ByteBuffer.
3144      * @param {string} str String to decode
3145      * @param {boolean=} littleEndian Whether to use little or big endian byte order. Defaults to
3146      *  {@link ByteBuffer.DEFAULT_ENDIAN}.
3147      * @returns {!ByteBuffer} ByteBuffer
3148      * @expose
3149      */
3150     ByteBuffer.fromBase64 = function(str, littleEndian) {
3151         if (typeof str !== 'string')
3152             throw TypeError("str");
3153         var bb = new ByteBuffer(str.length/4*3, littleEndian),
3154             i = 0;
3155         lxiv.decode(stringSource(str), function(b) {
3156             bb.view[i++] = b;
3157         });
3158         bb.limit = i;
3159         return bb;
3160     };
3162     /**
3163      * Encodes a binary string to base64 like `window.btoa` does.
3164      * @param {string} str Binary string
3165      * @returns {string} Base64 encoded string
3166      * @see https://developer.mozilla.org/en-US/docs/Web/API/Window.btoa
3167      * @expose
3168      */
3169     ByteBuffer.btoa = function(str) {
3170         return ByteBuffer.fromBinary(str).toBase64();
3171     };
3173     /**
3174      * Decodes a base64 encoded string to binary like `window.atob` does.
3175      * @param {string} b64 Base64 encoded string
3176      * @returns {string} Binary string
3177      * @see https://developer.mozilla.org/en-US/docs/Web/API/Window.atob
3178      * @expose
3179      */
3180     ByteBuffer.atob = function(b64) {
3181         return ByteBuffer.fromBase64(b64).toBinary();
3182     };
3184     // encodings/binary
3186     /**
3187      * Encodes this ByteBuffer to a binary encoded string, that is using only characters 0x00-0xFF as bytes.
3188      * @param {number=} begin Offset to begin at. Defaults to {@link ByteBuffer#offset}.
3189      * @param {number=} end Offset to end at. Defaults to {@link ByteBuffer#limit}.
3190      * @returns {string} Binary encoded string
3191      * @throws {RangeError} If `offset > limit`
3192      * @expose
3193      */
3194     ByteBufferPrototype.toBinary = function(begin, end) {
3195         if (typeof begin === 'undefined')
3196             begin = this.offset;
3197         if (typeof end === 'undefined')
3198             end = this.limit;
3199         begin |= 0; end |= 0;
3200         if (begin < 0 || end > this.capacity() || begin > end)
3201             throw RangeError("begin, end");
3202         if (begin === end)
3203             return "";
3204         var chars = [],
3205             parts = [];
3206         while (begin < end) {
3207             chars.push(this.view[begin++]);
3208             if (chars.length >= 1024)
3209                 parts.push(String.fromCharCode.apply(String, chars)),
3210                 chars = [];
3211         }
3212         return parts.join('') + String.fromCharCode.apply(String, chars);
3213     };
3215     /**
3216      * Decodes a binary encoded string, that is using only characters 0x00-0xFF as bytes, to a ByteBuffer.
3217      * @param {string} str String to decode
3218      * @param {boolean=} littleEndian Whether to use little or big endian byte order. Defaults to
3219      *  {@link ByteBuffer.DEFAULT_ENDIAN}.
3220      * @returns {!ByteBuffer} ByteBuffer
3221      * @expose
3222      */
3223     ByteBuffer.fromBinary = function(str, littleEndian) {
3224         if (typeof str !== 'string')
3225             throw TypeError("str");
3226         var i = 0,
3227             k = str.length,
3228             charCode,
3229             bb = new ByteBuffer(k, littleEndian);
3230         while (i<k) {
3231             charCode = str.charCodeAt(i);
3232             if (charCode > 0xff)
3233                 throw RangeError("illegal char code: "+charCode);
3234             bb.view[i++] = charCode;
3235         }
3236         bb.limit = k;
3237         return bb;
3238     };
3240     // encodings/debug
3242     /**
3243      * Encodes this ByteBuffer to a hex encoded string with marked offsets. Offset symbols are:
3244      * * `<` : offset,
3245      * * `'` : markedOffset,
3246      * * `>` : limit,
3247      * * `|` : offset and limit,
3248      * * `[` : offset and markedOffset,
3249      * * `]` : markedOffset and limit,
3250      * * `!` : offset, markedOffset and limit
3251      * @param {boolean=} columns If `true` returns two columns hex + ascii, defaults to `false`
3252      * @returns {string|!Array.<string>} Debug string or array of lines if `asArray = true`
3253      * @expose
3254      * @example `>00'01 02<03` contains four bytes with `limit=0, markedOffset=1, offset=3`
3255      * @example `00[01 02 03>` contains four bytes with `offset=markedOffset=1, limit=4`
3256      * @example `00|01 02 03` contains four bytes with `offset=limit=1, markedOffset=-1`
3257      * @example `|` contains zero bytes with `offset=limit=0, markedOffset=-1`
3258      */
3259     ByteBufferPrototype.toDebug = function(columns) {
3260         var i = -1,
3261             k = this.buffer.byteLength,
3262             b,
3263             hex = "",
3264             asc = "",
3265             out = "";
3266         while (i<k) {
3267             if (i !== -1) {
3268                 b = this.view[i];
3269                 if (b < 0x10) hex += "0"+b.toString(16).toUpperCase();
3270                 else hex += b.toString(16).toUpperCase();
3271                 if (columns)
3272                     asc += b > 32 && b < 127 ? String.fromCharCode(b) : '.';
3273             }
3274             ++i;
3275             if (columns) {
3276                 if (i > 0 && i % 16 === 0 && i !== k) {
3277                     while (hex.length < 3*16+3) hex += " ";
3278                     out += hex+asc+"\n";
3279                     hex = asc = "";
3280                 }
3281             }
3282             if (i === this.offset && i === this.limit)
3283                 hex += i === this.markedOffset ? "!" : "|";
3284             else if (i === this.offset)
3285                 hex += i === this.markedOffset ? "[" : "<";
3286             else if (i === this.limit)
3287                 hex += i === this.markedOffset ? "]" : ">";
3288             else
3289                 hex += i === this.markedOffset ? "'" : (columns || (i !== 0 && i !== k) ? " " : "");
3290         }
3291         if (columns && hex !== " ") {
3292             while (hex.length < 3*16+3)
3293                 hex += " ";
3294             out += hex + asc + "\n";
3295         }
3296         return columns ? out : hex;
3297     };
3299     /**
3300      * Decodes a hex encoded string with marked offsets to a ByteBuffer.
3301      * @param {string} str Debug string to decode (not be generated with `columns = true`)
3302      * @param {boolean=} littleEndian Whether to use little or big endian byte order. Defaults to
3303      *  {@link ByteBuffer.DEFAULT_ENDIAN}.
3304      * @param {boolean=} noAssert Whether to skip assertions of offsets and values. Defaults to
3305      *  {@link ByteBuffer.DEFAULT_NOASSERT}.
3306      * @returns {!ByteBuffer} ByteBuffer
3307      * @expose
3308      * @see ByteBuffer#toDebug
3309      */
3310     ByteBuffer.fromDebug = function(str, littleEndian, noAssert) {
3311         var k = str.length,
3312             bb = new ByteBuffer(((k+1)/3)|0, littleEndian, noAssert);
3313         var i = 0, j = 0, ch, b,
3314             rs = false, // Require symbol next
3315             ho = false, hm = false, hl = false, // Already has offset (ho), markedOffset (hm), limit (hl)?
3316             fail = false;
3317         while (i<k) {
3318             switch (ch = str.charAt(i++)) {
3319                 case '!':
3320                     if (!noAssert) {
3321                         if (ho || hm || hl) {
3322                             fail = true;
3323                             break;
3324                         }
3325                         ho = hm = hl = true;
3326                     }
3327                     bb.offset = bb.markedOffset = bb.limit = j;
3328                     rs = false;
3329                     break;
3330                 case '|':
3331                     if (!noAssert) {
3332                         if (ho || hl) {
3333                             fail = true;
3334                             break;
3335                         }
3336                         ho = hl = true;
3337                     }
3338                     bb.offset = bb.limit = j;
3339                     rs = false;
3340                     break;
3341                 case '[':
3342                     if (!noAssert) {
3343                         if (ho || hm) {
3344                             fail = true;
3345                             break;
3346                         }
3347                         ho = hm = true;
3348                     }
3349                     bb.offset = bb.markedOffset = j;
3350                     rs = false;
3351                     break;
3352                 case '<':
3353                     if (!noAssert) {
3354                         if (ho) {
3355                             fail = true;
3356                             break;
3357                         }
3358                         ho = true;
3359                     }
3360                     bb.offset = j;
3361                     rs = false;
3362                     break;
3363                 case ']':
3364                     if (!noAssert) {
3365                         if (hl || hm) {
3366                             fail = true;
3367                             break;
3368                         }
3369                         hl = hm = true;
3370                     }
3371                     bb.limit = bb.markedOffset = j;
3372                     rs = false;
3373                     break;
3374                 case '>':
3375                     if (!noAssert) {
3376                         if (hl) {
3377                             fail = true;
3378                             break;
3379                         }
3380                         hl = true;
3381                     }
3382                     bb.limit = j;
3383                     rs = false;
3384                     break;
3385                 case "'":
3386                     if (!noAssert) {
3387                         if (hm) {
3388                             fail = true;
3389                             break;
3390                         }
3391                         hm = true;
3392                     }
3393                     bb.markedOffset = j;
3394                     rs = false;
3395                     break;
3396                 case ' ':
3397                     rs = false;
3398                     break;
3399                 default:
3400                     if (!noAssert) {
3401                         if (rs) {
3402                             fail = true;
3403                             break;
3404                         }
3405                     }
3406                     b = parseInt(ch+str.charAt(i++), 16);
3407                     if (!noAssert) {
3408                         if (isNaN(b) || b < 0 || b > 255)
3409                             throw TypeError("Illegal str: Not a debug encoded string");
3410                     }
3411                     bb.view[j++] = b;
3412                     rs = true;
3413             }
3414             if (fail)
3415                 throw TypeError("Illegal str: Invalid symbol at "+i);
3416         }
3417         if (!noAssert) {
3418             if (!ho || !hl)
3419                 throw TypeError("Illegal str: Missing offset or limit");
3420             if (j<bb.buffer.byteLength)
3421                 throw TypeError("Illegal str: Not a debug encoded string (is it hex?) "+j+" < "+k);
3422         }
3423         return bb;
3424     };
3426     // encodings/hex
3428     /**
3429      * Encodes this ByteBuffer's contents to a hex encoded string.
3430      * @param {number=} begin Offset to begin at. Defaults to {@link ByteBuffer#offset}.
3431      * @param {number=} end Offset to end at. Defaults to {@link ByteBuffer#limit}.
3432      * @returns {string} Hex encoded string
3433      * @expose
3434      */
3435     ByteBufferPrototype.toHex = function(begin, end) {
3436         begin = typeof begin === 'undefined' ? this.offset : begin;
3437         end = typeof end === 'undefined' ? this.limit : end;
3438         if (!this.noAssert) {
3439             if (typeof begin !== 'number' || begin % 1 !== 0)
3440                 throw TypeError("Illegal begin: Not an integer");
3441             begin >>>= 0;
3442             if (typeof end !== 'number' || end % 1 !== 0)
3443                 throw TypeError("Illegal end: Not an integer");
3444             end >>>= 0;
3445             if (begin < 0 || begin > end || end > this.buffer.byteLength)
3446                 throw RangeError("Illegal range: 0 <= "+begin+" <= "+end+" <= "+this.buffer.byteLength);
3447         }
3448         var out = new Array(end - begin),
3449             b;
3450         while (begin < end) {
3451             b = this.view[begin++];
3452             if (b < 0x10)
3453                 out.push("0", b.toString(16));
3454             else out.push(b.toString(16));
3455         }
3456         return out.join('');
3457     };
3459     /**
3460      * Decodes a hex encoded string to a ByteBuffer.
3461      * @param {string} str String to decode
3462      * @param {boolean=} littleEndian Whether to use little or big endian byte order. Defaults to
3463      *  {@link ByteBuffer.DEFAULT_ENDIAN}.
3464      * @param {boolean=} noAssert Whether to skip assertions of offsets and values. Defaults to
3465      *  {@link ByteBuffer.DEFAULT_NOASSERT}.
3466      * @returns {!ByteBuffer} ByteBuffer
3467      * @expose
3468      */
3469     ByteBuffer.fromHex = function(str, littleEndian, noAssert) {
3470         if (!noAssert) {
3471             if (typeof str !== 'string')
3472                 throw TypeError("Illegal str: Not a string");
3473             if (str.length % 2 !== 0)
3474                 throw TypeError("Illegal str: Length not a multiple of 2");
3475         }
3476         var k = str.length,
3477             bb = new ByteBuffer((k / 2) | 0, littleEndian),
3478             b;
3479         for (var i=0, j=0; i<k; i+=2) {
3480             b = parseInt(str.substring(i, i+2), 16);
3481             if (!noAssert)
3482                 if (!isFinite(b) || b < 0 || b > 255)
3483                     throw TypeError("Illegal str: Contains non-hex characters");
3484             bb.view[j++] = b;
3485         }
3486         bb.limit = j;
3487         return bb;
3488     };
3490     // utfx-embeddable
3492     /**
3493      * utfx-embeddable (c) 2014 Daniel Wirtz <dcode@dcode.io>
3494      * Released under the Apache License, Version 2.0
3495      * see: https://github.com/dcodeIO/utfx for details
3496      */
3497     var utfx = function() {
3498         "use strict";
3500         /**
3501          * utfx namespace.
3502          * @inner
3503          * @type {!Object.<string,*>}
3504          */
3505         var utfx = {};
3507         /**
3508          * Maximum valid code point.
3509          * @type {number}
3510          * @const
3511          */
3512         utfx.MAX_CODEPOINT = 0x10FFFF;
3514         /**
3515          * Encodes UTF8 code points to UTF8 bytes.
3516          * @param {(!function():number|null) | number} src Code points source, either as a function returning the next code point
3517          *  respectively `null` if there are no more code points left or a single numeric code point.
3518          * @param {!function(number)} dst Bytes destination as a function successively called with the next byte
3519          */
3520         utfx.encodeUTF8 = function(src, dst) {
3521             var cp = null;
3522             if (typeof src === 'number')
3523                 cp = src,
3524                 src = function() { return null; };
3525             while (cp !== null || (cp = src()) !== null) {
3526                 if (cp < 0x80)
3527                     dst(cp&0x7F);
3528                 else if (cp < 0x800)
3529                     dst(((cp>>6)&0x1F)|0xC0),
3530                     dst((cp&0x3F)|0x80);
3531                 else if (cp < 0x10000)
3532                     dst(((cp>>12)&0x0F)|0xE0),
3533                     dst(((cp>>6)&0x3F)|0x80),
3534                     dst((cp&0x3F)|0x80);
3535                 else
3536                     dst(((cp>>18)&0x07)|0xF0),
3537                     dst(((cp>>12)&0x3F)|0x80),
3538                     dst(((cp>>6)&0x3F)|0x80),
3539                     dst((cp&0x3F)|0x80);
3540                 cp = null;
3541             }
3542         };
3544         /**
3545          * Decodes UTF8 bytes to UTF8 code points.
3546          * @param {!function():number|null} src Bytes source as a function returning the next byte respectively `null` if there
3547          *  are no more bytes left.
3548          * @param {!function(number)} dst Code points destination as a function successively called with each decoded code point.
3549          * @throws {RangeError} If a starting byte is invalid in UTF8
3550          * @throws {Error} If the last sequence is truncated. Has an array property `bytes` holding the
3551          *  remaining bytes.
3552          */
3553         utfx.decodeUTF8 = function(src, dst) {
3554             var a, b, c, d, fail = function(b) {
3555                 b = b.slice(0, b.indexOf(null));
3556                 var err = Error(b.toString());
3557                 err.name = "TruncatedError";
3558                 err['bytes'] = b;
3559                 throw err;
3560             };
3561             while ((a = src()) !== null) {
3562                 if ((a&0x80) === 0)
3563                     dst(a);
3564                 else if ((a&0xE0) === 0xC0)
3565                     ((b = src()) === null) && fail([a, b]),
3566                     dst(((a&0x1F)<<6) | (b&0x3F));
3567                 else if ((a&0xF0) === 0xE0)
3568                     ((b=src()) === null || (c=src()) === null) && fail([a, b, c]),
3569                     dst(((a&0x0F)<<12) | ((b&0x3F)<<6) | (c&0x3F));
3570                 else if ((a&0xF8) === 0xF0)
3571                     ((b=src()) === null || (c=src()) === null || (d=src()) === null) && fail([a, b, c ,d]),
3572                     dst(((a&0x07)<<18) | ((b&0x3F)<<12) | ((c&0x3F)<<6) | (d&0x3F));
3573                 else throw RangeError("Illegal starting byte: "+a);
3574             }
3575         };
3577         /**
3578          * Converts UTF16 characters to UTF8 code points.
3579          * @param {!function():number|null} src Characters source as a function returning the next char code respectively
3580          *  `null` if there are no more characters left.
3581          * @param {!function(number)} dst Code points destination as a function successively called with each converted code
3582          *  point.
3583          */
3584         utfx.UTF16toUTF8 = function(src, dst) {
3585             var c1, c2 = null;
3586             while (true) {
3587                 if ((c1 = c2 !== null ? c2 : src()) === null)
3588                     break;
3589                 if (c1 >= 0xD800 && c1 <= 0xDFFF) {
3590                     if ((c2 = src()) !== null) {
3591                         if (c2 >= 0xDC00 && c2 <= 0xDFFF) {
3592                             dst((c1-0xD800)*0x400+c2-0xDC00+0x10000);
3593                             c2 = null; continue;
3594                         }
3595                     }
3596                 }
3597                 dst(c1);
3598             }
3599             if (c2 !== null) dst(c2);
3600         };
3602         /**
3603          * Converts UTF8 code points to UTF16 characters.
3604          * @param {(!function():number|null) | number} src Code points source, either as a function returning the next code point
3605          *  respectively `null` if there are no more code points left or a single numeric code point.
3606          * @param {!function(number)} dst Characters destination as a function successively called with each converted char code.
3607          * @throws {RangeError} If a code point is out of range
3608          */
3609         utfx.UTF8toUTF16 = function(src, dst) {
3610             var cp = null;
3611             if (typeof src === 'number')
3612                 cp = src, src = function() { return null; };
3613             while (cp !== null || (cp = src()) !== null) {
3614                 if (cp <= 0xFFFF)
3615                     dst(cp);
3616                 else
3617                     cp -= 0x10000,
3618                     dst((cp>>10)+0xD800),
3619                     dst((cp%0x400)+0xDC00);
3620                 cp = null;
3621             }
3622         };
3624         /**
3625          * Converts and encodes UTF16 characters to UTF8 bytes.
3626          * @param {!function():number|null} src Characters source as a function returning the next char code respectively `null`
3627          *  if there are no more characters left.
3628          * @param {!function(number)} dst Bytes destination as a function successively called with the next byte.
3629          */
3630         utfx.encodeUTF16toUTF8 = function(src, dst) {
3631             utfx.UTF16toUTF8(src, function(cp) {
3632                 utfx.encodeUTF8(cp, dst);
3633             });
3634         };
3636         /**
3637          * Decodes and converts UTF8 bytes to UTF16 characters.
3638          * @param {!function():number|null} src Bytes source as a function returning the next byte respectively `null` if there
3639          *  are no more bytes left.
3640          * @param {!function(number)} dst Characters destination as a function successively called with each converted char code.
3641          * @throws {RangeError} If a starting byte is invalid in UTF8
3642          * @throws {Error} If the last sequence is truncated. Has an array property `bytes` holding the remaining bytes.
3643          */
3644         utfx.decodeUTF8toUTF16 = function(src, dst) {
3645             utfx.decodeUTF8(src, function(cp) {
3646                 utfx.UTF8toUTF16(cp, dst);
3647             });
3648         };
3650         /**
3651          * Calculates the byte length of an UTF8 code point.
3652          * @param {number} cp UTF8 code point
3653          * @returns {number} Byte length
3654          */
3655         utfx.calculateCodePoint = function(cp) {
3656             return (cp < 0x80) ? 1 : (cp < 0x800) ? 2 : (cp < 0x10000) ? 3 : 4;
3657         };
3659         /**
3660          * Calculates the number of UTF8 bytes required to store UTF8 code points.
3661          * @param {(!function():number|null)} src Code points source as a function returning the next code point respectively
3662          *  `null` if there are no more code points left.
3663          * @returns {number} The number of UTF8 bytes required
3664          */
3665         utfx.calculateUTF8 = function(src) {
3666             var cp, l=0;
3667             while ((cp = src()) !== null)
3668                 l += (cp < 0x80) ? 1 : (cp < 0x800) ? 2 : (cp < 0x10000) ? 3 : 4;
3669             return l;
3670         };
3672         /**
3673          * Calculates the number of UTF8 code points respectively UTF8 bytes required to store UTF16 char codes.
3674          * @param {(!function():number|null)} src Characters source as a function returning the next char code respectively
3675          *  `null` if there are no more characters left.
3676          * @returns {!Array.<number>} The number of UTF8 code points at index 0 and the number of UTF8 bytes required at index 1.
3677          */
3678         utfx.calculateUTF16asUTF8 = function(src) {
3679             var n=0, l=0;
3680             utfx.UTF16toUTF8(src, function(cp) {
3681                 ++n; l += (cp < 0x80) ? 1 : (cp < 0x800) ? 2 : (cp < 0x10000) ? 3 : 4;
3682             });
3683             return [n,l];
3684         };
3686         return utfx;
3687     }();
3689     // encodings/utf8
3691     /**
3692      * Encodes this ByteBuffer's contents between {@link ByteBuffer#offset} and {@link ByteBuffer#limit} to an UTF8 encoded
3693      *  string.
3694      * @returns {string} Hex encoded string
3695      * @throws {RangeError} If `offset > limit`
3696      * @expose
3697      */
3698     ByteBufferPrototype.toUTF8 = function(begin, end) {
3699         if (typeof begin === 'undefined') begin = this.offset;
3700         if (typeof end === 'undefined') end = this.limit;
3701         if (!this.noAssert) {
3702             if (typeof begin !== 'number' || begin % 1 !== 0)
3703                 throw TypeError("Illegal begin: Not an integer");
3704             begin >>>= 0;
3705             if (typeof end !== 'number' || end % 1 !== 0)
3706                 throw TypeError("Illegal end: Not an integer");
3707             end >>>= 0;
3708             if (begin < 0 || begin > end || end > this.buffer.byteLength)
3709                 throw RangeError("Illegal range: 0 <= "+begin+" <= "+end+" <= "+this.buffer.byteLength);
3710         }
3711         var sd; try {
3712             utfx.decodeUTF8toUTF16(function() {
3713                 return begin < end ? this.view[begin++] : null;
3714             }.bind(this), sd = stringDestination());
3715         } catch (e) {
3716             if (begin !== end)
3717                 throw RangeError("Illegal range: Truncated data, "+begin+" != "+end);
3718         }
3719         return sd();
3720     };
3722     /**
3723      * Decodes an UTF8 encoded string to a ByteBuffer.
3724      * @param {string} str String to decode
3725      * @param {boolean=} littleEndian Whether to use little or big endian byte order. Defaults to
3726      *  {@link ByteBuffer.DEFAULT_ENDIAN}.
3727      * @param {boolean=} noAssert Whether to skip assertions of offsets and values. Defaults to
3728      *  {@link ByteBuffer.DEFAULT_NOASSERT}.
3729      * @returns {!ByteBuffer} ByteBuffer
3730      * @expose
3731      */
3732     ByteBuffer.fromUTF8 = function(str, littleEndian, noAssert) {
3733         if (!noAssert)
3734             if (typeof str !== 'string')
3735                 throw TypeError("Illegal str: Not a string");
3736         var bb = new ByteBuffer(utfx.calculateUTF16asUTF8(stringSource(str), true)[1], littleEndian, noAssert),
3737             i = 0;
3738         utfx.encodeUTF16toUTF8(stringSource(str), function(b) {
3739             bb.view[i++] = b;
3740         });
3741         bb.limit = i;
3742         return bb;
3743     };
3745     return ByteBuffer;
3746 });