0) {
+ if(p < this.DB && (d = this[i]>>p) > 0) { m = true; r = int2char(d); }
+ while(i >= 0) {
+ if(p < k) {
+ d = (this[i]&((1<>(p+=this.DB-k);
+ }
+ else {
+ d = (this[i]>>(p-=k))&km;
+ if(p <= 0) { p += this.DB; --i; }
+ }
+ if(d > 0) m = true;
+ if(m) r += int2char(d);
+ }
+ }
+ return m?r:"0";
+ }
+
+ // (public) -this
+ function bnNegate() { var r = nbi(); BigInteger.ZERO.subTo(this,r); return r; }
+
+ // (public) |this|
+ function bnAbs() { return (this.s<0)?this.negate():this; }
+
+ // (public) return + if this > a, - if this < a, 0 if equal
+ function bnCompareTo(a) {
+ var r = this.s-a.s;
+ if(r != 0) return r;
+ var i = this.t;
+ r = i-a.t;
+ if(r != 0) return (this.s<0)?-r:r;
+ while(--i >= 0) if((r=this[i]-a[i]) != 0) return r;
+ return 0;
+ }
+
+ // returns bit length of the integer x
+ function nbits(x) {
+ var r = 1, t;
+ if((t=x>>>16) != 0) { x = t; r += 16; }
+ if((t=x>>8) != 0) { x = t; r += 8; }
+ if((t=x>>4) != 0) { x = t; r += 4; }
+ if((t=x>>2) != 0) { x = t; r += 2; }
+ if((t=x>>1) != 0) { x = t; r += 1; }
+ return r;
+ }
+
+ // (public) return the number of bits in "this"
+ function bnBitLength() {
+ if(this.t <= 0) return 0;
+ return this.DB*(this.t-1)+nbits(this[this.t-1]^(this.s&this.DM));
+ }
+
+ // (protected) r = this << n*DB
+ function bnpDLShiftTo(n,r) {
+ var i;
+ for(i = this.t-1; i >= 0; --i) r[i+n] = this[i];
+ for(i = n-1; i >= 0; --i) r[i] = 0;
+ r.t = this.t+n;
+ r.s = this.s;
+ }
+
+ // (protected) r = this >> n*DB
+ function bnpDRShiftTo(n,r) {
+ for(var i = n; i < this.t; ++i) r[i-n] = this[i];
+ r.t = Math.max(this.t-n,0);
+ r.s = this.s;
+ }
+
+ // (protected) r = this << n
+ function bnpLShiftTo(n,r) {
+ var bs = n%this.DB;
+ var cbs = this.DB-bs;
+ var bm = (1<= 0; --i) {
+ r[i+ds+1] = (this[i]>>cbs)|c;
+ c = (this[i]&bm)<= 0; --i) r[i] = 0;
+ r[ds] = c;
+ r.t = this.t+ds+1;
+ r.s = this.s;
+ r.clamp();
+ }
+
+ // (protected) r = this >> n
+ function bnpRShiftTo(n,r) {
+ r.s = this.s;
+ var ds = Math.floor(n/this.DB);
+ if(ds >= this.t) { r.t = 0; return; }
+ var bs = n%this.DB;
+ var cbs = this.DB-bs;
+ var bm = (1<>bs;
+ for(var i = ds+1; i < this.t; ++i) {
+ r[i-ds-1] |= (this[i]&bm)<>bs;
+ }
+ if(bs > 0) r[this.t-ds-1] |= (this.s&bm)<>= this.DB;
+ }
+ if(a.t < this.t) {
+ c -= a.s;
+ while(i < this.t) {
+ c += this[i];
+ r[i++] = c&this.DM;
+ c >>= this.DB;
+ }
+ c += this.s;
+ }
+ else {
+ c += this.s;
+ while(i < a.t) {
+ c -= a[i];
+ r[i++] = c&this.DM;
+ c >>= this.DB;
+ }
+ c -= a.s;
+ }
+ r.s = (c<0)?-1:0;
+ if(c < -1) r[i++] = this.DV+c;
+ else if(c > 0) r[i++] = c;
+ r.t = i;
+ r.clamp();
+ }
+
+ // (protected) r = this * a, r != this,a (HAC 14.12)
+ // "this" should be the larger one if appropriate.
+ function bnpMultiplyTo(a,r) {
+ var x = this.abs(), y = a.abs();
+ var i = x.t;
+ r.t = i+y.t;
+ while(--i >= 0) r[i] = 0;
+ for(i = 0; i < y.t; ++i) r[i+x.t] = x.am(0,y[i],r,i,0,x.t);
+ r.s = 0;
+ r.clamp();
+ if(this.s != a.s) BigInteger.ZERO.subTo(r,r);
+ }
+
+ // (protected) r = this^2, r != this (HAC 14.16)
+ function bnpSquareTo(r) {
+ var x = this.abs();
+ var i = r.t = 2*x.t;
+ while(--i >= 0) r[i] = 0;
+ for(i = 0; i < x.t-1; ++i) {
+ var c = x.am(i,x[i],r,2*i,0,1);
+ if((r[i+x.t]+=x.am(i+1,2*x[i],r,2*i+1,c,x.t-i-1)) >= x.DV) {
+ r[i+x.t] -= x.DV;
+ r[i+x.t+1] = 1;
+ }
+ }
+ if(r.t > 0) r[r.t-1] += x.am(i,x[i],r,2*i,0,1);
+ r.s = 0;
+ r.clamp();
+ }
+
+ // (protected) divide this by m, quotient and remainder to q, r (HAC 14.20)
+ // r != q, this != m. q or r may be null.
+ function bnpDivRemTo(m,q,r) {
+ var pm = m.abs();
+ if(pm.t <= 0) return;
+ var pt = this.abs();
+ if(pt.t < pm.t) {
+ if(q != null) q.fromInt(0);
+ if(r != null) this.copyTo(r);
+ return;
+ }
+ if(r == null) r = nbi();
+ var y = nbi(), ts = this.s, ms = m.s;
+ var nsh = this.DB-nbits(pm[pm.t-1]); // normalize modulus
+ if(nsh > 0) { pm.lShiftTo(nsh,y); pt.lShiftTo(nsh,r); }
+ else { pm.copyTo(y); pt.copyTo(r); }
+ var ys = y.t;
+ var y0 = y[ys-1];
+ if(y0 == 0) return;
+ var yt = y0*(1<1)?y[ys-2]>>this.F2:0);
+ var d1 = this.FV/yt, d2 = (1<= 0) {
+ r[r.t++] = 1;
+ r.subTo(t,r);
+ }
+ BigInteger.ONE.dlShiftTo(ys,t);
+ t.subTo(y,y); // "negative" y so we can replace sub with am later
+ while(y.t < ys) y[y.t++] = 0;
+ while(--j >= 0) {
+ // Estimate quotient digit
+ var qd = (r[--i]==y0)?this.DM:Math.floor(r[i]*d1+(r[i-1]+e)*d2);
+ if((r[i]+=y.am(0,qd,r,j,0,ys)) < qd) { // Try it out
+ y.dlShiftTo(j,t);
+ r.subTo(t,r);
+ while(r[i] < --qd) r.subTo(t,r);
+ }
+ }
+ if(q != null) {
+ r.drShiftTo(ys,q);
+ if(ts != ms) BigInteger.ZERO.subTo(q,q);
+ }
+ r.t = ys;
+ r.clamp();
+ if(nsh > 0) r.rShiftTo(nsh,r); // Denormalize remainder
+ if(ts < 0) BigInteger.ZERO.subTo(r,r);
+ }
+
+ // (public) this mod a
+ function bnMod(a) {
+ var r = nbi();
+ this.abs().divRemTo(a,null,r);
+ if(this.s < 0 && r.compareTo(BigInteger.ZERO) > 0) a.subTo(r,r);
+ return r;
+ }
+
+ // Modular reduction using "classic" algorithm
+ function Classic(m) { this.m = m; }
+ function cConvert(x) {
+ if(x.s < 0 || x.compareTo(this.m) >= 0) return x.mod(this.m);
+ else return x;
+ }
+ function cRevert(x) { return x; }
+ function cReduce(x) { x.divRemTo(this.m,null,x); }
+ function cMulTo(x,y,r) { x.multiplyTo(y,r); this.reduce(r); }
+ function cSqrTo(x,r) { x.squareTo(r); this.reduce(r); }
+
+ Classic.prototype.convert = cConvert;
+ Classic.prototype.revert = cRevert;
+ Classic.prototype.reduce = cReduce;
+ Classic.prototype.mulTo = cMulTo;
+ Classic.prototype.sqrTo = cSqrTo;
+
+ // (protected) return "-1/this % 2^DB"; useful for Mont. reduction
+ // justification:
+ // xy == 1 (mod m)
+ // xy = 1+km
+ // xy(2-xy) = (1+km)(1-km)
+ // x[y(2-xy)] = 1-k^2m^2
+ // x[y(2-xy)] == 1 (mod m^2)
+ // if y is 1/x mod m, then y(2-xy) is 1/x mod m^2
+ // should reduce x and y(2-xy) by m^2 at each step to keep size bounded.
+ // JS multiply "overflows" differently from C/C++, so care is needed here.
+ function bnpInvDigit() {
+ if(this.t < 1) return 0;
+ var x = this[0];
+ if((x&1) == 0) return 0;
+ var y = x&3; // y == 1/x mod 2^2
+ y = (y*(2-(x&0xf)*y))&0xf; // y == 1/x mod 2^4
+ y = (y*(2-(x&0xff)*y))&0xff; // y == 1/x mod 2^8
+ y = (y*(2-(((x&0xffff)*y)&0xffff)))&0xffff; // y == 1/x mod 2^16
+ // last step - calculate inverse mod DV directly;
+ // assumes 16 < DB <= 32 and assumes ability to handle 48-bit ints
+ y = (y*(2-x*y%this.DV))%this.DV; // y == 1/x mod 2^dbits
+ // we really want the negative inverse, and -DV < y < DV
+ return (y>0)?this.DV-y:-y;
+ }
+
+ // Montgomery reduction
+ function Montgomery(m) {
+ this.m = m;
+ this.mp = m.invDigit();
+ this.mpl = this.mp&0x7fff;
+ this.mph = this.mp>>15;
+ this.um = (1<<(m.DB-15))-1;
+ this.mt2 = 2*m.t;
+ }
+
+ // xR mod m
+ function montConvert(x) {
+ var r = nbi();
+ x.abs().dlShiftTo(this.m.t,r);
+ r.divRemTo(this.m,null,r);
+ if(x.s < 0 && r.compareTo(BigInteger.ZERO) > 0) this.m.subTo(r,r);
+ return r;
+ }
+
+ // x/R mod m
+ function montRevert(x) {
+ var r = nbi();
+ x.copyTo(r);
+ this.reduce(r);
+ return r;
+ }
+
+ // x = x/R mod m (HAC 14.32)
+ function montReduce(x) {
+ while(x.t <= this.mt2) // pad x so am has enough room later
+ x[x.t++] = 0;
+ for(var i = 0; i < this.m.t; ++i) {
+ // faster way of calculating u0 = x[i]*mp mod DV
+ var j = x[i]&0x7fff;
+ var u0 = (j*this.mpl+(((j*this.mph+(x[i]>>15)*this.mpl)&this.um)<<15))&x.DM;
+ // use am to combine the multiply-shift-add into one call
+ j = i+this.m.t;
+ x[j] += this.m.am(0,u0,x,i,0,this.m.t);
+ // propagate carry
+ while(x[j] >= x.DV) { x[j] -= x.DV; x[++j]++; }
+ }
+ x.clamp();
+ x.drShiftTo(this.m.t,x);
+ if(x.compareTo(this.m) >= 0) x.subTo(this.m,x);
+ }
+
+ // r = "x^2/R mod m"; x != r
+ function montSqrTo(x,r) { x.squareTo(r); this.reduce(r); }
+
+ // r = "xy/R mod m"; x,y != r
+ function montMulTo(x,y,r) { x.multiplyTo(y,r); this.reduce(r); }
+
+ Montgomery.prototype.convert = montConvert;
+ Montgomery.prototype.revert = montRevert;
+ Montgomery.prototype.reduce = montReduce;
+ Montgomery.prototype.mulTo = montMulTo;
+ Montgomery.prototype.sqrTo = montSqrTo;
+
+ // (protected) true iff this is even
+ function bnpIsEven() { return ((this.t>0)?(this[0]&1):this.s) == 0; }
+
+ // (protected) this^e, e < 2^32, doing sqr and mul with "r" (HAC 14.79)
+ function bnpExp(e,z) {
+ if(e > 0xffffffff || e < 1) return BigInteger.ONE;
+ var r = nbi(), r2 = nbi(), g = z.convert(this), i = nbits(e)-1;
+ g.copyTo(r);
+ while(--i >= 0) {
+ z.sqrTo(r,r2);
+ if((e&(1< 0) z.mulTo(r2,g,r);
+ else { var t = r; r = r2; r2 = t; }
+ }
+ return z.revert(r);
+ }
+
+ // (public) this^e % m, 0 <= e < 2^32
+ function bnModPowInt(e,m) {
+ var z;
+ if(e < 256 || m.isEven()) z = new Classic(m); else z = new Montgomery(m);
+ return this.exp(e,z);
+ }
+
+ // protected
+ BigInteger.prototype.copyTo = bnpCopyTo;
+ BigInteger.prototype.fromInt = bnpFromInt;
+ BigInteger.prototype.fromString = bnpFromString;
+ BigInteger.prototype.clamp = bnpClamp;
+ BigInteger.prototype.dlShiftTo = bnpDLShiftTo;
+ BigInteger.prototype.drShiftTo = bnpDRShiftTo;
+ BigInteger.prototype.lShiftTo = bnpLShiftTo;
+ BigInteger.prototype.rShiftTo = bnpRShiftTo;
+ BigInteger.prototype.subTo = bnpSubTo;
+ BigInteger.prototype.multiplyTo = bnpMultiplyTo;
+ BigInteger.prototype.squareTo = bnpSquareTo;
+ BigInteger.prototype.divRemTo = bnpDivRemTo;
+ BigInteger.prototype.invDigit = bnpInvDigit;
+ BigInteger.prototype.isEven = bnpIsEven;
+ BigInteger.prototype.exp = bnpExp;
+
+ // public
+ BigInteger.prototype.toString = bnToString;
+ BigInteger.prototype.negate = bnNegate;
+ BigInteger.prototype.abs = bnAbs;
+ BigInteger.prototype.compareTo = bnCompareTo;
+ BigInteger.prototype.bitLength = bnBitLength;
+ BigInteger.prototype.mod = bnMod;
+ BigInteger.prototype.modPowInt = bnModPowInt;
+
+ // "constants"
+ BigInteger.ZERO = nbv(0);
+ BigInteger.ONE = nbv(1);
+
+ // jsbn2 stuff
+
+ // (protected) convert from radix string
+ function bnpFromRadix(s,b) {
+ this.fromInt(0);
+ if(b == null) b = 10;
+ var cs = this.chunkSize(b);
+ var d = Math.pow(b,cs), mi = false, j = 0, w = 0;
+ for(var i = 0; i < s.length; ++i) {
+ var x = intAt(s,i);
+ if(x < 0) {
+ if(s.charAt(i) == "-" && this.signum() == 0) mi = true;
+ continue;
+ }
+ w = b*w+x;
+ if(++j >= cs) {
+ this.dMultiply(d);
+ this.dAddOffset(w,0);
+ j = 0;
+ w = 0;
+ }
+ }
+ if(j > 0) {
+ this.dMultiply(Math.pow(b,j));
+ this.dAddOffset(w,0);
+ }
+ if(mi) BigInteger.ZERO.subTo(this,this);
+ }
+
+ // (protected) return x s.t. r^x < DV
+ function bnpChunkSize(r) { return Math.floor(Math.LN2*this.DB/Math.log(r)); }
+
+ // (public) 0 if this == 0, 1 if this > 0
+ function bnSigNum() {
+ if(this.s < 0) return -1;
+ else if(this.t <= 0 || (this.t == 1 && this[0] <= 0)) return 0;
+ else return 1;
+ }
+
+ // (protected) this *= n, this >= 0, 1 < n < DV
+ function bnpDMultiply(n) {
+ this[this.t] = this.am(0,n-1,this,0,0,this.t);
+ ++this.t;
+ this.clamp();
+ }
+
+ // (protected) this += n << w words, this >= 0
+ function bnpDAddOffset(n,w) {
+ if(n == 0) return;
+ while(this.t <= w) this[this.t++] = 0;
+ this[w] += n;
+ while(this[w] >= this.DV) {
+ this[w] -= this.DV;
+ if(++w >= this.t) this[this.t++] = 0;
+ ++this[w];
+ }
+ }
+
+ // (protected) convert to radix string
+ function bnpToRadix(b) {
+ if(b == null) b = 10;
+ if(this.signum() == 0 || b < 2 || b > 36) return "0";
+ var cs = this.chunkSize(b);
+ var a = Math.pow(b,cs);
+ var d = nbv(a), y = nbi(), z = nbi(), r = "";
+ this.divRemTo(d,y,z);
+ while(y.signum() > 0) {
+ r = (a+z.intValue()).toString(b).substr(1) + r;
+ y.divRemTo(d,y,z);
+ }
+ return z.intValue().toString(b) + r;
+ }
+
+ // (public) return value as integer
+ function bnIntValue() {
+ if(this.s < 0) {
+ if(this.t == 1) return this[0]-this.DV;
+ else if(this.t == 0) return -1;
+ }
+ else if(this.t == 1) return this[0];
+ else if(this.t == 0) return 0;
+ // assumes 16 < DB < 32
+ return ((this[1]&((1<<(32-this.DB))-1))<>= this.DB;
+ }
+ if(a.t < this.t) {
+ c += a.s;
+ while(i < this.t) {
+ c += this[i];
+ r[i++] = c&this.DM;
+ c >>= this.DB;
+ }
+ c += this.s;
+ }
+ else {
+ c += this.s;
+ while(i < a.t) {
+ c += a[i];
+ r[i++] = c&this.DM;
+ c >>= this.DB;
+ }
+ c += a.s;
+ }
+ r.s = (c<0)?-1:0;
+ if(c > 0) r[i++] = c;
+ else if(c < -1) r[i++] = this.DV+c;
+ r.t = i;
+ r.clamp();
+ }
+
+ BigInteger.prototype.fromRadix = bnpFromRadix;
+ BigInteger.prototype.chunkSize = bnpChunkSize;
+ BigInteger.prototype.signum = bnSigNum;
+ BigInteger.prototype.dMultiply = bnpDMultiply;
+ BigInteger.prototype.dAddOffset = bnpDAddOffset;
+ BigInteger.prototype.toRadix = bnpToRadix;
+ BigInteger.prototype.intValue = bnIntValue;
+ BigInteger.prototype.addTo = bnpAddTo;
+
+ //======= end jsbn =======
+
+ // Emscripten wrapper
+ var Wrapper = {
+ abs: function(l, h) {
+ var x = new goog.math.Long(l, h);
+ var ret;
+ if (x.isNegative()) {
+ ret = x.negate();
+ } else {
+ ret = x;
+ }
+ HEAP32[tempDoublePtr>>2] = ret.low_;
+ HEAP32[tempDoublePtr+4>>2] = ret.high_;
+ },
+ ensureTemps: function() {
+ if (Wrapper.ensuredTemps) return;
+ Wrapper.ensuredTemps = true;
+ Wrapper.two32 = new BigInteger();
+ Wrapper.two32.fromString('4294967296', 10);
+ Wrapper.two64 = new BigInteger();
+ Wrapper.two64.fromString('18446744073709551616', 10);
+ Wrapper.temp1 = new BigInteger();
+ Wrapper.temp2 = new BigInteger();
+ },
+ lh2bignum: function(l, h) {
+ var a = new BigInteger();
+ a.fromString(h.toString(), 10);
+ var b = new BigInteger();
+ a.multiplyTo(Wrapper.two32, b);
+ var c = new BigInteger();
+ c.fromString(l.toString(), 10);
+ var d = new BigInteger();
+ c.addTo(b, d);
+ return d;
+ },
+ stringify: function(l, h, unsigned) {
+ var ret = new goog.math.Long(l, h).toString();
+ if (unsigned && ret[0] == '-') {
+ // unsign slowly using jsbn bignums
+ Wrapper.ensureTemps();
+ var bignum = new BigInteger();
+ bignum.fromString(ret, 10);
+ ret = new BigInteger();
+ Wrapper.two64.addTo(bignum, ret);
+ ret = ret.toString(10);
+ }
+ return ret;
+ },
+ fromString: function(str, base, min, max, unsigned) {
+ Wrapper.ensureTemps();
+ var bignum = new BigInteger();
+ bignum.fromString(str, base);
+ var bigmin = new BigInteger();
+ bigmin.fromString(min, 10);
+ var bigmax = new BigInteger();
+ bigmax.fromString(max, 10);
+ if (unsigned && bignum.compareTo(BigInteger.ZERO) < 0) {
+ var temp = new BigInteger();
+ bignum.addTo(Wrapper.two64, temp);
+ bignum = temp;
+ }
+ var error = false;
+ if (bignum.compareTo(bigmin) < 0) {
+ bignum = bigmin;
+ error = true;
+ } else if (bignum.compareTo(bigmax) > 0) {
+ bignum = bigmax;
+ error = true;
+ }
+ var ret = goog.math.Long.fromString(bignum.toString()); // min-max checks should have clamped this to a range goog.math.Long can handle well
+ HEAP32[tempDoublePtr>>2] = ret.low_;
+ HEAP32[tempDoublePtr+4>>2] = ret.high_;
+ if (error) throw 'range error';
+ }
+ };
+ return Wrapper;
+})();
+
+//======= end closure i64 code =======
+
+
+
+// === Auto-generated postamble setup entry stuff ===
+
+if (memoryInitializer) {
+ if (typeof Module['locateFile'] === 'function') {
+ memoryInitializer = Module['locateFile'](memoryInitializer);
+ } else if (Module['memoryInitializerPrefixURL']) {
+ memoryInitializer = Module['memoryInitializerPrefixURL'] + memoryInitializer;
+ }
+ if (ENVIRONMENT_IS_NODE || ENVIRONMENT_IS_SHELL) {
+ var data = Module['readBinary'](memoryInitializer);
+ HEAPU8.set(data, STATIC_BASE);
+ } else {
+ addRunDependency('memory initializer');
+ Browser.asyncLoad(memoryInitializer, function(data) {
+ HEAPU8.set(data, STATIC_BASE);
+ removeRunDependency('memory initializer');
+ }, function(data) {
+ throw 'could not load memory initializer ' + memoryInitializer;
+ });
+ }
+}
+
+function ExitStatus(status) {
+ this.name = "ExitStatus";
+ this.message = "Program terminated with exit(" + status + ")";
+ this.status = status;
+};
+ExitStatus.prototype = new Error();
+ExitStatus.prototype.constructor = ExitStatus;
+
+var initialStackTop;
+var preloadStartTime = null;
+var calledMain = false;
+
+dependenciesFulfilled = function runCaller() {
+ // If run has never been called, and we should call run (INVOKE_RUN is true, and Module.noInitialRun is not false)
+ if (!Module['calledRun'] && shouldRunNow) run();
+ if (!Module['calledRun']) dependenciesFulfilled = runCaller; // try this again later, after new deps are fulfilled
+}
+
+Module['callMain'] = Module.callMain = function callMain(args) {
+ assert(runDependencies == 0, 'cannot call main when async dependencies remain! (listen on __ATMAIN__)');
+ assert(__ATPRERUN__.length == 0, 'cannot call main when preRun functions remain to be called');
+
+ args = args || [];
+
+ ensureInitRuntime();
+
+ var argc = args.length+1;
+ function pad() {
+ for (var i = 0; i < 4-1; i++) {
+ argv.push(0);
+ }
+ }
+ var argv = [allocate(intArrayFromString(Module['thisProgram']), 'i8', ALLOC_NORMAL) ];
+ pad();
+ for (var i = 0; i < argc-1; i = i + 1) {
+ argv.push(allocate(intArrayFromString(args[i]), 'i8', ALLOC_NORMAL));
+ pad();
+ }
+ argv.push(0);
+ argv = allocate(argv, 'i32', ALLOC_NORMAL);
+
+ initialStackTop = STACKTOP;
+
+ try {
+
+ var ret = Module['_main'](argc, argv, 0);
+
+
+ // if we're not running an evented main loop, it's time to exit
+ exit(ret);
+ }
+ catch(e) {
+ if (e instanceof ExitStatus) {
+ // exit() throws this once it's done to make sure execution
+ // has been stopped completely
+ return;
+ } else if (e == 'SimulateInfiniteLoop') {
+ // running an evented main loop, don't immediately exit
+ Module['noExitRuntime'] = true;
+ return;
+ } else {
+ if (e && typeof e === 'object' && e.stack) Module.printErr('exception thrown: ' + [e, e.stack]);
+ throw e;
+ }
+ } finally {
+ calledMain = true;
+ }
+}
+
+
+
+
+function run(args) {
+ args = args || Module['arguments'];
+
+ if (preloadStartTime === null) preloadStartTime = Date.now();
+
+ if (runDependencies > 0) {
+ return;
+ }
+
+ preRun();
+
+ if (runDependencies > 0) return; // a preRun added a dependency, run will be called later
+ if (Module['calledRun']) return; // run may have just been called through dependencies being fulfilled just in this very frame
+
+ function doRun() {
+ if (Module['calledRun']) return; // run may have just been called while the async setStatus time below was happening
+ Module['calledRun'] = true;
+
+ if (ABORT) return;
+
+ ensureInitRuntime();
+
+ preMain();
+
+ if (ENVIRONMENT_IS_WEB && preloadStartTime !== null) {
+ Module.printErr('pre-main prep time: ' + (Date.now() - preloadStartTime) + ' ms');
+ }
+
+ if (Module['onRuntimeInitialized']) Module['onRuntimeInitialized']();
+
+ if (Module['_main'] && shouldRunNow) Module['callMain'](args);
+
+ postRun();
+ }
+
+ if (Module['setStatus']) {
+ Module['setStatus']('Running...');
+ setTimeout(function() {
+ setTimeout(function() {
+ Module['setStatus']('');
+ }, 1);
+ doRun();
+ }, 1);
+ } else {
+ doRun();
+ }
+}
+Module['run'] = Module.run = run;
+
+function exit(status) {
+ if (Module['noExitRuntime']) {
+ return;
+ }
+
+ ABORT = true;
+ EXITSTATUS = status;
+ STACKTOP = initialStackTop;
+
+ // exit the runtime
+ exitRuntime();
+
+ if (ENVIRONMENT_IS_NODE) {
+ // Work around a node.js bug where stdout buffer is not flushed at process exit:
+ // Instead of process.exit() directly, wait for stdout flush event.
+ // See https://github.com/joyent/node/issues/1669 and https://github.com/kripken/emscripten/issues/2582
+ // Workaround is based on https://github.com/RReverser/acorn/commit/50ab143cecc9ed71a2d66f78b4aec3bb2e9844f6
+ process['stdout']['once']('drain', function () {
+ process['exit'](status);
+ });
+ console.log(' '); // Make sure to print something to force the drain event to occur, in case the stdout buffer was empty.
+ // Work around another node bug where sometimes 'drain' is never fired - make another effort
+ // to emit the exit status, after a significant delay (if node hasn't fired drain by then, give up)
+ setTimeout(function() {
+ process['exit'](status);
+ }, 500);
+ } else
+ if (ENVIRONMENT_IS_SHELL && typeof quit === 'function') {
+ quit(status);
+ }
+ // if we reach here, we must throw an exception to halt the current execution
+ throw new ExitStatus(status);
+}
+Module['exit'] = Module.exit = exit;
+
+function abort(text) {
+ if (text) {
+ Module.print(text);
+ Module.printErr(text);
+ }
+
+ ABORT = true;
+ EXITSTATUS = 1;
+
+ var extra = '\nIf this abort() is unexpected, build with -s ASSERTIONS=1 which can give more information.';
+
+ throw 'abort() at ' + stackTrace() + extra;
+}
+Module['abort'] = Module.abort = abort;
+
+// {{PRE_RUN_ADDITIONS}}
+
+if (Module['preInit']) {
+ if (typeof Module['preInit'] == 'function') Module['preInit'] = [Module['preInit']];
+ while (Module['preInit'].length > 0) {
+ Module['preInit'].pop()();
+ }
+}
+
+// shouldRunNow refers to calling main(), not run().
+var shouldRunNow = true;
+if (Module['noInitialRun']) {
+ shouldRunNow = false;
+}
+
+
+run();
+
+// {{POST_RUN_ADDITIONS}}
+
+
+
+
+
+
+// {{MODULE_ADDITIONS}}
+
+
+
+
+/* vim: ts=4:sw=4:expandtab
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+var axolotlInternal = axolotlInternal || {};
+
+axolotlInternal.curve25519 = function() {
+ 'use strict';
+
+ // Insert some bytes into the emscripten memory and return a pointer
+ function _allocate(bytes) {
+ var address = Module._malloc(bytes.length);
+ Module.HEAPU8.set(bytes, address);
+
+ return address;
+ }
+
+ function _readBytes(address, length, array) {
+ array.set(Module.HEAPU8.subarray(address, address + length));
+ }
+
+ var basepoint = new Uint8Array(32);
+ basepoint[0] = 9;
+
+ return {
+ keyPair: function(privKey) {
+ var priv = new Uint8Array(privKey);
+ priv[0] &= 248;
+ priv[31] &= 127;
+ priv[31] |= 64
+
+ // Where to store the result
+ var publicKey_ptr = Module._malloc(32);
+
+ // Get a pointer to the private key
+ var privateKey_ptr = _allocate(priv);
+
+ // The basepoint for generating public keys
+ var basepoint_ptr = _allocate(basepoint);
+
+ // The return value is just 0, the operation is done in place
+ var err = Module._curve25519_donna(publicKey_ptr,
+ privateKey_ptr,
+ basepoint_ptr);
+
+ var res = new Uint8Array(32);
+ _readBytes(publicKey_ptr, 32, res);
+
+ Module._free(publicKey_ptr);
+ Module._free(privateKey_ptr);
+ Module._free(basepoint_ptr);
+
+ return Promise.resolve({ pubKey: res.buffer, privKey: privKey });
+ },
+ sharedSecret: function(pubKey, privKey) {
+ // Where to store the result
+ var sharedKey_ptr = Module._malloc(32);
+
+ // Get a pointer to our private key
+ var privateKey_ptr = _allocate(new Uint8Array(privKey));
+
+ // Get a pointer to their public key, the basepoint when you're
+ // generating a shared secret
+ var basepoint_ptr = _allocate(new Uint8Array(pubKey));
+
+ // Return value is 0 here too of course
+ var err = Module._curve25519_donna(sharedKey_ptr,
+ privateKey_ptr,
+ basepoint_ptr);
+
+ var res = new Uint8Array(32);
+ _readBytes(sharedKey_ptr, 32, res);
+
+ Module._free(sharedKey_ptr);
+ Module._free(privateKey_ptr);
+ Module._free(basepoint_ptr);
+
+ return Promise.resolve(res.buffer);
+ },
+ sign: function(privKey, message) {
+ // Where to store the result
+ var signature_ptr = Module._malloc(64);
+
+ // Get a pointer to our private key
+ var privateKey_ptr = _allocate(new Uint8Array(privKey));
+
+ // Get a pointer to the message
+ var message_ptr = _allocate(new Uint8Array(message));
+
+ var err = Module._curve25519_sign(signature_ptr,
+ privateKey_ptr,
+ message_ptr,
+ message.byteLength);
+
+ var res = new Uint8Array(64);
+ _readBytes(signature_ptr, 64, res);
+
+ Module._free(signature_ptr);
+ Module._free(privateKey_ptr);
+ Module._free(message_ptr);
+
+ return Promise.resolve(res.buffer);
+ },
+ verify: function(pubKey, message, sig) {
+ // Get a pointer to their public key
+ var publicKey_ptr = _allocate(new Uint8Array(pubKey));
+
+ // Get a pointer to the signature
+ var signature_ptr = _allocate(new Uint8Array(sig));
+
+ // Get a pointer to the message
+ var message_ptr = _allocate(new Uint8Array(message));
+
+ var res = Module._curve25519_verify(signature_ptr,
+ publicKey_ptr,
+ message_ptr,
+ message.byteLength);
+
+ Module._free(publicKey_ptr);
+ Module._free(signature_ptr);
+ Module._free(message_ptr);
+
+ return new Promise(function(resolve, reject) {
+ if (res !== 0) {
+ reject(new Error("Invalid signature"));
+ } else {
+ resolve();
+ }
+ });
+ }
+ };
+}();
+
+;(function(){
+/**
+ * CryptoJS core components.
+ */
+var CryptoJS = CryptoJS || (function (Math, undefined) {
+ /**
+ * CryptoJS namespace.
+ */
+ var C = {};
+
+ /**
+ * Library namespace.
+ */
+ var C_lib = C.lib = {};
+
+ /**
+ * Base object for prototypal inheritance.
+ */
+ var Base = C_lib.Base = (function () {
+ function F() {}
+
+ return {
+ /**
+ * Creates a new object that inherits from this object.
+ *
+ * @param {Object} overrides Properties to copy into the new object.
+ *
+ * @return {Object} The new object.
+ *
+ * @static
+ *
+ * @example
+ *
+ * var MyType = CryptoJS.lib.Base.extend({
+ * field: 'value',
+ *
+ * method: function () {
+ * }
+ * });
+ */
+ extend: function (overrides) {
+ // Spawn
+ F.prototype = this;
+ var subtype = new F();
+
+ // Augment
+ if (overrides) {
+ subtype.mixIn(overrides);
+ }
+
+ // Create default initializer
+ if (!subtype.hasOwnProperty('init')) {
+ subtype.init = function () {
+ subtype.$super.init.apply(this, arguments);
+ };
+ }
+
+ // Initializer's prototype is the subtype object
+ subtype.init.prototype = subtype;
+
+ // Reference supertype
+ subtype.$super = this;
+
+ return subtype;
+ },
+
+ /**
+ * Extends this object and runs the init method.
+ * Arguments to create() will be passed to init().
+ *
+ * @return {Object} The new object.
+ *
+ * @static
+ *
+ * @example
+ *
+ * var instance = MyType.create();
+ */
+ create: function () {
+ var instance = this.extend();
+ instance.init.apply(instance, arguments);
+
+ return instance;
+ },
+
+ /**
+ * Initializes a newly created object.
+ * Override this method to add some logic when your objects are created.
+ *
+ * @example
+ *
+ * var MyType = CryptoJS.lib.Base.extend({
+ * init: function () {
+ * // ...
+ * }
+ * });
+ */
+ init: function () {
+ },
+
+ /**
+ * Copies properties into this object.
+ *
+ * @param {Object} properties The properties to mix in.
+ *
+ * @example
+ *
+ * MyType.mixIn({
+ * field: 'value'
+ * });
+ */
+ mixIn: function (properties) {
+ for (var propertyName in properties) {
+ if (properties.hasOwnProperty(propertyName)) {
+ this[propertyName] = properties[propertyName];
+ }
+ }
+
+ // IE won't copy toString using the loop above
+ if (properties.hasOwnProperty('toString')) {
+ this.toString = properties.toString;
+ }
+ },
+
+ /**
+ * Creates a copy of this object.
+ *
+ * @return {Object} The clone.
+ *
+ * @example
+ *
+ * var clone = instance.clone();
+ */
+ clone: function () {
+ return this.init.prototype.extend(this);
+ }
+ };
+ }());
+
+ /**
+ * An array of 32-bit words.
+ *
+ * @property {Array} words The array of 32-bit words.
+ * @property {number} sigBytes The number of significant bytes in this word array.
+ */
+ var WordArray = C_lib.WordArray = Base.extend({
+ /**
+ * Initializes a newly created word array.
+ *
+ * @param {Array} words (Optional) An array of 32-bit words.
+ * @param {number} sigBytes (Optional) The number of significant bytes in the words.
+ *
+ * @example
+ *
+ * var wordArray = CryptoJS.lib.WordArray.create();
+ * var wordArray = CryptoJS.lib.WordArray.create([0x00010203, 0x04050607]);
+ * var wordArray = CryptoJS.lib.WordArray.create([0x00010203, 0x04050607], 6);
+ */
+ init: function (words, sigBytes) {
+ words = this.words = words || [];
+
+ if (sigBytes != undefined) {
+ this.sigBytes = sigBytes;
+ } else {
+ this.sigBytes = words.length * 4;
+ }
+ },
+
+ /**
+ * Converts this word array to a string.
+ *
+ * @param {Encoder} encoder (Optional) The encoding strategy to use. Default: CryptoJS.enc.Hex
+ *
+ * @return {string} The stringified word array.
+ *
+ * @example
+ *
+ * var string = wordArray + '';
+ * var string = wordArray.toString();
+ * var string = wordArray.toString(CryptoJS.enc.Utf8);
+ */
+ toString: function (encoder) {
+ return (encoder || Hex).stringify(this);
+ },
+
+ /**
+ * Concatenates a word array to this word array.
+ *
+ * @param {WordArray} wordArray The word array to append.
+ *
+ * @return {WordArray} This word array.
+ *
+ * @example
+ *
+ * wordArray1.concat(wordArray2);
+ */
+ concat: function (wordArray) {
+ // Shortcuts
+ var thisWords = this.words;
+ var thatWords = wordArray.words;
+ var thisSigBytes = this.sigBytes;
+ var thatSigBytes = wordArray.sigBytes;
+
+ // Clamp excess bits
+ this.clamp();
+
+ // Concat
+ if (thisSigBytes % 4) {
+ // Copy one byte at a time
+ for (var i = 0; i < thatSigBytes; i++) {
+ var thatByte = (thatWords[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff;
+ thisWords[(thisSigBytes + i) >>> 2] |= thatByte << (24 - ((thisSigBytes + i) % 4) * 8);
+ }
+ } else if (thatWords.length > 0xffff) {
+ // Copy one word at a time
+ for (var i = 0; i < thatSigBytes; i += 4) {
+ thisWords[(thisSigBytes + i) >>> 2] = thatWords[i >>> 2];
+ }
+ } else {
+ // Copy all words at once
+ thisWords.push.apply(thisWords, thatWords);
+ }
+ this.sigBytes += thatSigBytes;
+
+ // Chainable
+ return this;
+ },
+
+ /**
+ * Removes insignificant bits.
+ *
+ * @example
+ *
+ * wordArray.clamp();
+ */
+ clamp: function () {
+ // Shortcuts
+ var words = this.words;
+ var sigBytes = this.sigBytes;
+
+ // Clamp
+ words[sigBytes >>> 2] &= 0xffffffff << (32 - (sigBytes % 4) * 8);
+ words.length = Math.ceil(sigBytes / 4);
+ },
+
+ /**
+ * Creates a copy of this word array.
+ *
+ * @return {WordArray} The clone.
+ *
+ * @example
+ *
+ * var clone = wordArray.clone();
+ */
+ clone: function () {
+ var clone = Base.clone.call(this);
+ clone.words = this.words.slice(0);
+
+ return clone;
+ },
+
+ /**
+ * Creates a word array filled with random bytes.
+ *
+ * @param {number} nBytes The number of random bytes to generate.
+ *
+ * @return {WordArray} The random word array.
+ *
+ * @static
+ *
+ * @example
+ *
+ * var wordArray = CryptoJS.lib.WordArray.random(16);
+ */
+ random: function (nBytes) {
+ var words = [];
+ for (var i = 0; i < nBytes; i += 4) {
+ words.push((Math.random() * 0x100000000) | 0);
+ }
+
+ return new WordArray.init(words, nBytes);
+ }
+ });
+
+ /**
+ * Encoder namespace.
+ */
+ var C_enc = C.enc = {};
+
+ /**
+ * Hex encoding strategy.
+ */
+ var Hex = C_enc.Hex = {
+ /**
+ * Converts a word array to a hex string.
+ *
+ * @param {WordArray} wordArray The word array.
+ *
+ * @return {string} The hex string.
+ *
+ * @static
+ *
+ * @example
+ *
+ * var hexString = CryptoJS.enc.Hex.stringify(wordArray);
+ */
+ stringify: function (wordArray) {
+ // Shortcuts
+ var words = wordArray.words;
+ var sigBytes = wordArray.sigBytes;
+
+ // Convert
+ var hexChars = [];
+ for (var i = 0; i < sigBytes; i++) {
+ var bite = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff;
+ hexChars.push((bite >>> 4).toString(16));
+ hexChars.push((bite & 0x0f).toString(16));
+ }
+
+ return hexChars.join('');
+ },
+
+ /**
+ * Converts a hex string to a word array.
+ *
+ * @param {string} hexStr The hex string.
+ *
+ * @return {WordArray} The word array.
+ *
+ * @static
+ *
+ * @example
+ *
+ * var wordArray = CryptoJS.enc.Hex.parse(hexString);
+ */
+ parse: function (hexStr) {
+ // Shortcut
+ var hexStrLength = hexStr.length;
+
+ // Convert
+ var words = [];
+ for (var i = 0; i < hexStrLength; i += 2) {
+ words[i >>> 3] |= parseInt(hexStr.substr(i, 2), 16) << (24 - (i % 8) * 4);
+ }
+
+ return new WordArray.init(words, hexStrLength / 2);
+ }
+ };
+
+ /**
+ * Latin1 encoding strategy.
+ */
+ var Latin1 = C_enc.Latin1 = {
+ /**
+ * Converts a word array to a Latin1 string.
+ *
+ * @param {WordArray} wordArray The word array.
+ *
+ * @return {string} The Latin1 string.
+ *
+ * @static
+ *
+ * @example
+ *
+ * var latin1String = CryptoJS.enc.Latin1.stringify(wordArray);
+ */
+ stringify: function (wordArray) {
+ // Shortcuts
+ var words = wordArray.words;
+ var sigBytes = wordArray.sigBytes;
+
+ // Convert
+ var latin1Chars = [];
+ for (var i = 0; i < sigBytes; i++) {
+ var bite = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff;
+ latin1Chars.push(String.fromCharCode(bite));
+ }
+
+ return latin1Chars.join('');
+ },
+
+ /**
+ * Converts a Latin1 string to a word array.
+ *
+ * @param {string} latin1Str The Latin1 string.
+ *
+ * @return {WordArray} The word array.
+ *
+ * @static
+ *
+ * @example
+ *
+ * var wordArray = CryptoJS.enc.Latin1.parse(latin1String);
+ */
+ parse: function (latin1Str) {
+ // Shortcut
+ var latin1StrLength = latin1Str.length;
+
+ // Convert
+ var words = [];
+ for (var i = 0; i < latin1StrLength; i++) {
+ words[i >>> 2] |= (latin1Str.charCodeAt(i) & 0xff) << (24 - (i % 4) * 8);
+ }
+
+ return new WordArray.init(words, latin1StrLength);
+ }
+ };
+
+ /**
+ * UTF-8 encoding strategy.
+ */
+ var Utf8 = C_enc.Utf8 = {
+ /**
+ * Converts a word array to a UTF-8 string.
+ *
+ * @param {WordArray} wordArray The word array.
+ *
+ * @return {string} The UTF-8 string.
+ *
+ * @static
+ *
+ * @example
+ *
+ * var utf8String = CryptoJS.enc.Utf8.stringify(wordArray);
+ */
+ stringify: function (wordArray) {
+ try {
+ return decodeURIComponent(escape(Latin1.stringify(wordArray)));
+ } catch (e) {
+ throw new Error('Malformed UTF-8 data');
+ }
+ },
+
+ /**
+ * Converts a UTF-8 string to a word array.
+ *
+ * @param {string} utf8Str The UTF-8 string.
+ *
+ * @return {WordArray} The word array.
+ *
+ * @static
+ *
+ * @example
+ *
+ * var wordArray = CryptoJS.enc.Utf8.parse(utf8String);
+ */
+ parse: function (utf8Str) {
+ return Latin1.parse(unescape(encodeURIComponent(utf8Str)));
+ }
+ };
+
+ /**
+ * Abstract buffered block algorithm template.
+ *
+ * The property blockSize must be implemented in a concrete subtype.
+ *
+ * @property {number} _minBufferSize The number of blocks that should be kept unprocessed in the buffer. Default: 0
+ */
+ var BufferedBlockAlgorithm = C_lib.BufferedBlockAlgorithm = Base.extend({
+ /**
+ * Resets this block algorithm's data buffer to its initial state.
+ *
+ * @example
+ *
+ * bufferedBlockAlgorithm.reset();
+ */
+ reset: function () {
+ // Initial values
+ this._data = new WordArray.init();
+ this._nDataBytes = 0;
+ },
+
+ /**
+ * Adds new data to this block algorithm's buffer.
+ *
+ * @param {WordArray|string} data The data to append. Strings are converted to a WordArray using UTF-8.
+ *
+ * @example
+ *
+ * bufferedBlockAlgorithm._append('data');
+ * bufferedBlockAlgorithm._append(wordArray);
+ */
+ _append: function (data) {
+ // Convert string to WordArray, else assume WordArray already
+ if (typeof data == 'string') {
+ data = Utf8.parse(data);
+ }
+
+ // Append
+ this._data.concat(data);
+ this._nDataBytes += data.sigBytes;
+ },
+
+ /**
+ * Processes available data blocks.
+ *
+ * This method invokes _doProcessBlock(offset), which must be implemented by a concrete subtype.
+ *
+ * @param {boolean} doFlush Whether all blocks and partial blocks should be processed.
+ *
+ * @return {WordArray} The processed data.
+ *
+ * @example
+ *
+ * var processedData = bufferedBlockAlgorithm._process();
+ * var processedData = bufferedBlockAlgorithm._process(!!'flush');
+ */
+ _process: function (doFlush) {
+ // Shortcuts
+ var data = this._data;
+ var dataWords = data.words;
+ var dataSigBytes = data.sigBytes;
+ var blockSize = this.blockSize;
+ var blockSizeBytes = blockSize * 4;
+
+ // Count blocks ready
+ var nBlocksReady = dataSigBytes / blockSizeBytes;
+ if (doFlush) {
+ // Round up to include partial blocks
+ nBlocksReady = Math.ceil(nBlocksReady);
+ } else {
+ // Round down to include only full blocks,
+ // less the number of blocks that must remain in the buffer
+ nBlocksReady = Math.max((nBlocksReady | 0) - this._minBufferSize, 0);
+ }
+
+ // Count words ready
+ var nWordsReady = nBlocksReady * blockSize;
+
+ // Count bytes ready
+ var nBytesReady = Math.min(nWordsReady * 4, dataSigBytes);
+
+ // Process blocks
+ if (nWordsReady) {
+ for (var offset = 0; offset < nWordsReady; offset += blockSize) {
+ // Perform concrete-algorithm logic
+ this._doProcessBlock(dataWords, offset);
+ }
+
+ // Remove processed words
+ var processedWords = dataWords.splice(0, nWordsReady);
+ data.sigBytes -= nBytesReady;
+ }
+
+ // Return processed words
+ return new WordArray.init(processedWords, nBytesReady);
+ },
+
+ /**
+ * Creates a copy of this object.
+ *
+ * @return {Object} The clone.
+ *
+ * @example
+ *
+ * var clone = bufferedBlockAlgorithm.clone();
+ */
+ clone: function () {
+ var clone = Base.clone.call(this);
+ clone._data = this._data.clone();
+
+ return clone;
+ },
+
+ _minBufferSize: 0
+ });
+
+ /**
+ * Abstract hasher template.
+ *
+ * @property {number} blockSize The number of 32-bit words this hasher operates on. Default: 16 (512 bits)
+ */
+ var Hasher = C_lib.Hasher = BufferedBlockAlgorithm.extend({
+ /**
+ * Configuration options.
+ */
+ cfg: Base.extend(),
+
+ /**
+ * Initializes a newly created hasher.
+ *
+ * @param {Object} cfg (Optional) The configuration options to use for this hash computation.
+ *
+ * @example
+ *
+ * var hasher = CryptoJS.algo.SHA256.create();
+ */
+ init: function (cfg) {
+ // Apply config defaults
+ this.cfg = this.cfg.extend(cfg);
+
+ // Set initial values
+ this.reset();
+ },
+
+ /**
+ * Resets this hasher to its initial state.
+ *
+ * @example
+ *
+ * hasher.reset();
+ */
+ reset: function () {
+ // Reset data buffer
+ BufferedBlockAlgorithm.reset.call(this);
+
+ // Perform concrete-hasher logic
+ this._doReset();
+ },
+
+ /**
+ * Updates this hasher with a message.
+ *
+ * @param {WordArray|string} messageUpdate The message to append.
+ *
+ * @return {Hasher} This hasher.
+ *
+ * @example
+ *
+ * hasher.update('message');
+ * hasher.update(wordArray);
+ */
+ update: function (messageUpdate) {
+ // Append
+ this._append(messageUpdate);
+
+ // Update the hash
+ this._process();
+
+ // Chainable
+ return this;
+ },
+
+ /**
+ * Finalizes the hash computation.
+ * Note that the finalize operation is effectively a destructive, read-once operation.
+ *
+ * @param {WordArray|string} messageUpdate (Optional) A final message update.
+ *
+ * @return {WordArray} The hash.
+ *
+ * @example
+ *
+ * var hash = hasher.finalize();
+ * var hash = hasher.finalize('message');
+ * var hash = hasher.finalize(wordArray);
+ */
+ finalize: function (messageUpdate) {
+ // Final message update
+ if (messageUpdate) {
+ this._append(messageUpdate);
+ }
+
+ // Perform concrete-hasher logic
+ var hash = this._doFinalize();
+
+ return hash;
+ },
+
+ blockSize: 512/32,
+
+ /**
+ * Creates a shortcut function to a hasher's object interface.
+ *
+ * @param {Hasher} hasher The hasher to create a helper for.
+ *
+ * @return {Function} The shortcut function.
+ *
+ * @static
+ *
+ * @example
+ *
+ * var SHA256 = CryptoJS.lib.Hasher._createHelper(CryptoJS.algo.SHA256);
+ */
+ _createHelper: function (hasher) {
+ return function (message, cfg) {
+ return new hasher.init(cfg).finalize(message);
+ };
+ },
+
+ /**
+ * Creates a shortcut function to the HMAC's object interface.
+ *
+ * @param {Hasher} hasher The hasher to use in this HMAC helper.
+ *
+ * @return {Function} The shortcut function.
+ *
+ * @static
+ *
+ * @example
+ *
+ * var HmacSHA256 = CryptoJS.lib.Hasher._createHmacHelper(CryptoJS.algo.SHA256);
+ */
+ _createHmacHelper: function (hasher) {
+ return function (message, key) {
+ return new C_algo.HMAC.init(hasher, key).finalize(message);
+ };
+ }
+ });
+
+ /**
+ * Algorithm namespace.
+ */
+ var C_algo = C.algo = {};
+
+ return C;
+}(Math));
+
+(function (Math) {
+ // Shortcuts
+ var C = CryptoJS;
+ var C_lib = C.lib;
+ var WordArray = C_lib.WordArray;
+ var Hasher = C_lib.Hasher;
+ var C_algo = C.algo;
+
+ // Initialization and round constants tables
+ var H = [];
+ var K = [];
+
+ // Compute constants
+ (function () {
+ function isPrime(n) {
+ var sqrtN = Math.sqrt(n);
+ for (var factor = 2; factor <= sqrtN; factor++) {
+ if (!(n % factor)) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ function getFractionalBits(n) {
+ return ((n - (n | 0)) * 0x100000000) | 0;
+ }
+
+ var n = 2;
+ var nPrime = 0;
+ while (nPrime < 64) {
+ if (isPrime(n)) {
+ if (nPrime < 8) {
+ H[nPrime] = getFractionalBits(Math.pow(n, 1 / 2));
+ }
+ K[nPrime] = getFractionalBits(Math.pow(n, 1 / 3));
+
+ nPrime++;
+ }
+
+ n++;
+ }
+ }());
+
+ // Reusable object
+ var W = [];
+
+ /**
+ * SHA-256 hash algorithm.
+ */
+ var SHA256 = C_algo.SHA256 = Hasher.extend({
+ _doReset: function () {
+ this._hash = new WordArray.init(H.slice(0));
+ },
+
+ _doProcessBlock: function (M, offset) {
+ // Shortcut
+ var H = this._hash.words;
+
+ // Working variables
+ var a = H[0];
+ var b = H[1];
+ var c = H[2];
+ var d = H[3];
+ var e = H[4];
+ var f = H[5];
+ var g = H[6];
+ var h = H[7];
+
+ // Computation
+ for (var i = 0; i < 64; i++) {
+ if (i < 16) {
+ W[i] = M[offset + i] | 0;
+ } else {
+ var gamma0x = W[i - 15];
+ var gamma0 = ((gamma0x << 25) | (gamma0x >>> 7)) ^
+ ((gamma0x << 14) | (gamma0x >>> 18)) ^
+ (gamma0x >>> 3);
+
+ var gamma1x = W[i - 2];
+ var gamma1 = ((gamma1x << 15) | (gamma1x >>> 17)) ^
+ ((gamma1x << 13) | (gamma1x >>> 19)) ^
+ (gamma1x >>> 10);
+
+ W[i] = gamma0 + W[i - 7] + gamma1 + W[i - 16];
+ }
+
+ var ch = (e & f) ^ (~e & g);
+ var maj = (a & b) ^ (a & c) ^ (b & c);
+
+ var sigma0 = ((a << 30) | (a >>> 2)) ^ ((a << 19) | (a >>> 13)) ^ ((a << 10) | (a >>> 22));
+ var sigma1 = ((e << 26) | (e >>> 6)) ^ ((e << 21) | (e >>> 11)) ^ ((e << 7) | (e >>> 25));
+
+ var t1 = h + sigma1 + ch + K[i] + W[i];
+ var t2 = sigma0 + maj;
+
+ h = g;
+ g = f;
+ f = e;
+ e = (d + t1) | 0;
+ d = c;
+ c = b;
+ b = a;
+ a = (t1 + t2) | 0;
+ }
+
+ // Intermediate hash value
+ H[0] = (H[0] + a) | 0;
+ H[1] = (H[1] + b) | 0;
+ H[2] = (H[2] + c) | 0;
+ H[3] = (H[3] + d) | 0;
+ H[4] = (H[4] + e) | 0;
+ H[5] = (H[5] + f) | 0;
+ H[6] = (H[6] + g) | 0;
+ H[7] = (H[7] + h) | 0;
+ },
+
+ _doFinalize: function () {
+ // Shortcuts
+ var data = this._data;
+ var dataWords = data.words;
+
+ var nBitsTotal = this._nDataBytes * 8;
+ var nBitsLeft = data.sigBytes * 8;
+
+ // Add padding
+ dataWords[nBitsLeft >>> 5] |= 0x80 << (24 - nBitsLeft % 32);
+ dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 14] = Math.floor(nBitsTotal / 0x100000000);
+ dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 15] = nBitsTotal;
+ data.sigBytes = dataWords.length * 4;
+
+ // Hash final blocks
+ this._process();
+
+ // Return final computed hash
+ return this._hash;
+ },
+
+ clone: function () {
+ var clone = Hasher.clone.call(this);
+ clone._hash = this._hash.clone();
+
+ return clone;
+ }
+ });
+
+ /**
+ * Shortcut function to the hasher's object interface.
+ *
+ * @param {WordArray|string} message The message to hash.
+ *
+ * @return {WordArray} The hash.
+ *
+ * @static
+ *
+ * @example
+ *
+ * var hash = CryptoJS.SHA256('message');
+ * var hash = CryptoJS.SHA256(wordArray);
+ */
+ C.SHA256 = Hasher._createHelper(SHA256);
+
+ /**
+ * Shortcut function to the HMAC's object interface.
+ *
+ * @param {WordArray|string} message The message to hash.
+ * @param {WordArray|string} key The secret key.
+ *
+ * @return {WordArray} The HMAC.
+ *
+ * @static
+ *
+ * @example
+ *
+ * var hmac = CryptoJS.HmacSHA256(message, key);
+ */
+ C.HmacSHA256 = Hasher._createHmacHelper(SHA256);
+}(Math));
+
+(function () {
+ // Shortcuts
+ var C = CryptoJS;
+ var C_lib = C.lib;
+ var Base = C_lib.Base;
+ var C_enc = C.enc;
+ var Utf8 = C_enc.Utf8;
+ var C_algo = C.algo;
+
+ /**
+ * HMAC algorithm.
+ */
+ var HMAC = C_algo.HMAC = Base.extend({
+ /**
+ * Initializes a newly created HMAC.
+ *
+ * @param {Hasher} hasher The hash algorithm to use.
+ * @param {WordArray|string} key The secret key.
+ *
+ * @example
+ *
+ * var hmacHasher = CryptoJS.algo.HMAC.create(CryptoJS.algo.SHA256, key);
+ */
+ init: function (hasher, key) {
+ // Init hasher
+ hasher = this._hasher = new hasher.init();
+
+ // Convert string to WordArray, else assume WordArray already
+ if (typeof key == 'string') {
+ key = Utf8.parse(key);
+ }
+
+ // Shortcuts
+ var hasherBlockSize = hasher.blockSize;
+ var hasherBlockSizeBytes = hasherBlockSize * 4;
+
+ // Allow arbitrary length keys
+ if (key.sigBytes > hasherBlockSizeBytes) {
+ key = hasher.finalize(key);
+ }
+
+ // Clamp excess bits
+ key.clamp();
+
+ // Clone key for inner and outer pads
+ var oKey = this._oKey = key.clone();
+ var iKey = this._iKey = key.clone();
+
+ // Shortcuts
+ var oKeyWords = oKey.words;
+ var iKeyWords = iKey.words;
+
+ // XOR keys with pad constants
+ for (var i = 0; i < hasherBlockSize; i++) {
+ oKeyWords[i] ^= 0x5c5c5c5c;
+ iKeyWords[i] ^= 0x36363636;
+ }
+ oKey.sigBytes = iKey.sigBytes = hasherBlockSizeBytes;
+
+ // Set initial values
+ this.reset();
+ },
+
+ /**
+ * Resets this HMAC to its initial state.
+ *
+ * @example
+ *
+ * hmacHasher.reset();
+ */
+ reset: function () {
+ // Shortcut
+ var hasher = this._hasher;
+
+ // Reset
+ hasher.reset();
+ hasher.update(this._iKey);
+ },
+
+ /**
+ * Updates this HMAC with a message.
+ *
+ * @param {WordArray|string} messageUpdate The message to append.
+ *
+ * @return {HMAC} This HMAC instance.
+ *
+ * @example
+ *
+ * hmacHasher.update('message');
+ * hmacHasher.update(wordArray);
+ */
+ update: function (messageUpdate) {
+ this._hasher.update(messageUpdate);
+
+ // Chainable
+ return this;
+ },
+
+ /**
+ * Finalizes the HMAC computation.
+ * Note that the finalize operation is effectively a destructive, read-once operation.
+ *
+ * @param {WordArray|string} messageUpdate (Optional) A final message update.
+ *
+ * @return {WordArray} The HMAC.
+ *
+ * @example
+ *
+ * var hmac = hmacHasher.finalize();
+ * var hmac = hmacHasher.finalize('message');
+ * var hmac = hmacHasher.finalize(wordArray);
+ */
+ finalize: function (messageUpdate) {
+ // Shortcut
+ var hasher = this._hasher;
+
+ // Compute HMAC
+ var innerHash = hasher.finalize(messageUpdate);
+ hasher.reset();
+ var hmac = hasher.finalize(this._oKey.clone().concat(innerHash));
+
+ return hmac;
+ }
+ });
+}());
+
+(function () {
+ // Shortcuts
+ var C = CryptoJS;
+ var C_lib = C.lib;
+ var WordArray = C_lib.WordArray;
+ var C_enc = C.enc;
+
+ /**
+ * Base64 encoding strategy.
+ */
+ var Base64 = C_enc.Base64 = {
+ /**
+ * Converts a word array to a Base64 string.
+ *
+ * @param {WordArray} wordArray The word array.
+ *
+ * @return {string} The Base64 string.
+ *
+ * @static
+ *
+ * @example
+ *
+ * var base64String = CryptoJS.enc.Base64.stringify(wordArray);
+ */
+ stringify: function (wordArray) {
+ // Shortcuts
+ var words = wordArray.words;
+ var sigBytes = wordArray.sigBytes;
+ var map = this._map;
+
+ // Clamp excess bits
+ wordArray.clamp();
+
+ // Convert
+ var base64Chars = [];
+ for (var i = 0; i < sigBytes; i += 3) {
+ var byte1 = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff;
+ var byte2 = (words[(i + 1) >>> 2] >>> (24 - ((i + 1) % 4) * 8)) & 0xff;
+ var byte3 = (words[(i + 2) >>> 2] >>> (24 - ((i + 2) % 4) * 8)) & 0xff;
+
+ var triplet = (byte1 << 16) | (byte2 << 8) | byte3;
+
+ for (var j = 0; (j < 4) && (i + j * 0.75 < sigBytes); j++) {
+ base64Chars.push(map.charAt((triplet >>> (6 * (3 - j))) & 0x3f));
+ }
+ }
+
+ // Add padding
+ var paddingChar = map.charAt(64);
+ if (paddingChar) {
+ while (base64Chars.length % 4) {
+ base64Chars.push(paddingChar);
+ }
+ }
+
+ return base64Chars.join('');
+ },
+
+ /**
+ * Converts a Base64 string to a word array.
+ *
+ * @param {string} base64Str The Base64 string.
+ *
+ * @return {WordArray} The word array.
+ *
+ * @static
+ *
+ * @example
+ *
+ * var wordArray = CryptoJS.enc.Base64.parse(base64String);
+ */
+ parse: function (base64Str) {
+ // Shortcuts
+ var base64StrLength = base64Str.length;
+ var map = this._map;
+
+ // Ignore padding
+ var paddingChar = map.charAt(64);
+ if (paddingChar) {
+ var paddingIndex = base64Str.indexOf(paddingChar);
+ if (paddingIndex != -1) {
+ base64StrLength = paddingIndex;
+ }
+ }
+
+ // Convert
+ var words = [];
+ var nBytes = 0;
+ for (var i = 0; i < base64StrLength; i++) {
+ if (i % 4) {
+ var bits1 = map.indexOf(base64Str.charAt(i - 1)) << ((i % 4) * 2);
+ var bits2 = map.indexOf(base64Str.charAt(i)) >>> (6 - (i % 4) * 2);
+ words[nBytes >>> 2] |= (bits1 | bits2) << (24 - (nBytes % 4) * 8);
+ nBytes++;
+ }
+ }
+
+ return WordArray.create(words, nBytes);
+ },
+
+ _map: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='
+ };
+}());
+
+(function (Math) {
+ // Shortcuts
+ var C = CryptoJS;
+ var C_lib = C.lib;
+ var WordArray = C_lib.WordArray;
+ var Hasher = C_lib.Hasher;
+ var C_algo = C.algo;
+
+ // Constants table
+ var T = [];
+
+ // Compute constants
+ (function () {
+ for (var i = 0; i < 64; i++) {
+ T[i] = (Math.abs(Math.sin(i + 1)) * 0x100000000) | 0;
+ }
+ }());
+
+ /**
+ * MD5 hash algorithm.
+ */
+ var MD5 = C_algo.MD5 = Hasher.extend({
+ _doReset: function () {
+ this._hash = new WordArray.init([
+ 0x67452301, 0xefcdab89,
+ 0x98badcfe, 0x10325476
+ ]);
+ },
+
+ _doProcessBlock: function (M, offset) {
+ // Swap endian
+ for (var i = 0; i < 16; i++) {
+ // Shortcuts
+ var offset_i = offset + i;
+ var M_offset_i = M[offset_i];
+
+ M[offset_i] = (
+ (((M_offset_i << 8) | (M_offset_i >>> 24)) & 0x00ff00ff) |
+ (((M_offset_i << 24) | (M_offset_i >>> 8)) & 0xff00ff00)
+ );
+ }
+
+ // Shortcuts
+ var H = this._hash.words;
+
+ var M_offset_0 = M[offset + 0];
+ var M_offset_1 = M[offset + 1];
+ var M_offset_2 = M[offset + 2];
+ var M_offset_3 = M[offset + 3];
+ var M_offset_4 = M[offset + 4];
+ var M_offset_5 = M[offset + 5];
+ var M_offset_6 = M[offset + 6];
+ var M_offset_7 = M[offset + 7];
+ var M_offset_8 = M[offset + 8];
+ var M_offset_9 = M[offset + 9];
+ var M_offset_10 = M[offset + 10];
+ var M_offset_11 = M[offset + 11];
+ var M_offset_12 = M[offset + 12];
+ var M_offset_13 = M[offset + 13];
+ var M_offset_14 = M[offset + 14];
+ var M_offset_15 = M[offset + 15];
+
+ // Working varialbes
+ var a = H[0];
+ var b = H[1];
+ var c = H[2];
+ var d = H[3];
+
+ // Computation
+ a = FF(a, b, c, d, M_offset_0, 7, T[0]);
+ d = FF(d, a, b, c, M_offset_1, 12, T[1]);
+ c = FF(c, d, a, b, M_offset_2, 17, T[2]);
+ b = FF(b, c, d, a, M_offset_3, 22, T[3]);
+ a = FF(a, b, c, d, M_offset_4, 7, T[4]);
+ d = FF(d, a, b, c, M_offset_5, 12, T[5]);
+ c = FF(c, d, a, b, M_offset_6, 17, T[6]);
+ b = FF(b, c, d, a, M_offset_7, 22, T[7]);
+ a = FF(a, b, c, d, M_offset_8, 7, T[8]);
+ d = FF(d, a, b, c, M_offset_9, 12, T[9]);
+ c = FF(c, d, a, b, M_offset_10, 17, T[10]);
+ b = FF(b, c, d, a, M_offset_11, 22, T[11]);
+ a = FF(a, b, c, d, M_offset_12, 7, T[12]);
+ d = FF(d, a, b, c, M_offset_13, 12, T[13]);
+ c = FF(c, d, a, b, M_offset_14, 17, T[14]);
+ b = FF(b, c, d, a, M_offset_15, 22, T[15]);
+
+ a = GG(a, b, c, d, M_offset_1, 5, T[16]);
+ d = GG(d, a, b, c, M_offset_6, 9, T[17]);
+ c = GG(c, d, a, b, M_offset_11, 14, T[18]);
+ b = GG(b, c, d, a, M_offset_0, 20, T[19]);
+ a = GG(a, b, c, d, M_offset_5, 5, T[20]);
+ d = GG(d, a, b, c, M_offset_10, 9, T[21]);
+ c = GG(c, d, a, b, M_offset_15, 14, T[22]);
+ b = GG(b, c, d, a, M_offset_4, 20, T[23]);
+ a = GG(a, b, c, d, M_offset_9, 5, T[24]);
+ d = GG(d, a, b, c, M_offset_14, 9, T[25]);
+ c = GG(c, d, a, b, M_offset_3, 14, T[26]);
+ b = GG(b, c, d, a, M_offset_8, 20, T[27]);
+ a = GG(a, b, c, d, M_offset_13, 5, T[28]);
+ d = GG(d, a, b, c, M_offset_2, 9, T[29]);
+ c = GG(c, d, a, b, M_offset_7, 14, T[30]);
+ b = GG(b, c, d, a, M_offset_12, 20, T[31]);
+
+ a = HH(a, b, c, d, M_offset_5, 4, T[32]);
+ d = HH(d, a, b, c, M_offset_8, 11, T[33]);
+ c = HH(c, d, a, b, M_offset_11, 16, T[34]);
+ b = HH(b, c, d, a, M_offset_14, 23, T[35]);
+ a = HH(a, b, c, d, M_offset_1, 4, T[36]);
+ d = HH(d, a, b, c, M_offset_4, 11, T[37]);
+ c = HH(c, d, a, b, M_offset_7, 16, T[38]);
+ b = HH(b, c, d, a, M_offset_10, 23, T[39]);
+ a = HH(a, b, c, d, M_offset_13, 4, T[40]);
+ d = HH(d, a, b, c, M_offset_0, 11, T[41]);
+ c = HH(c, d, a, b, M_offset_3, 16, T[42]);
+ b = HH(b, c, d, a, M_offset_6, 23, T[43]);
+ a = HH(a, b, c, d, M_offset_9, 4, T[44]);
+ d = HH(d, a, b, c, M_offset_12, 11, T[45]);
+ c = HH(c, d, a, b, M_offset_15, 16, T[46]);
+ b = HH(b, c, d, a, M_offset_2, 23, T[47]);
+
+ a = II(a, b, c, d, M_offset_0, 6, T[48]);
+ d = II(d, a, b, c, M_offset_7, 10, T[49]);
+ c = II(c, d, a, b, M_offset_14, 15, T[50]);
+ b = II(b, c, d, a, M_offset_5, 21, T[51]);
+ a = II(a, b, c, d, M_offset_12, 6, T[52]);
+ d = II(d, a, b, c, M_offset_3, 10, T[53]);
+ c = II(c, d, a, b, M_offset_10, 15, T[54]);
+ b = II(b, c, d, a, M_offset_1, 21, T[55]);
+ a = II(a, b, c, d, M_offset_8, 6, T[56]);
+ d = II(d, a, b, c, M_offset_15, 10, T[57]);
+ c = II(c, d, a, b, M_offset_6, 15, T[58]);
+ b = II(b, c, d, a, M_offset_13, 21, T[59]);
+ a = II(a, b, c, d, M_offset_4, 6, T[60]);
+ d = II(d, a, b, c, M_offset_11, 10, T[61]);
+ c = II(c, d, a, b, M_offset_2, 15, T[62]);
+ b = II(b, c, d, a, M_offset_9, 21, T[63]);
+
+ // Intermediate hash value
+ H[0] = (H[0] + a) | 0;
+ H[1] = (H[1] + b) | 0;
+ H[2] = (H[2] + c) | 0;
+ H[3] = (H[3] + d) | 0;
+ },
+
+ _doFinalize: function () {
+ // Shortcuts
+ var data = this._data;
+ var dataWords = data.words;
+
+ var nBitsTotal = this._nDataBytes * 8;
+ var nBitsLeft = data.sigBytes * 8;
+
+ // Add padding
+ dataWords[nBitsLeft >>> 5] |= 0x80 << (24 - nBitsLeft % 32);
+
+ var nBitsTotalH = Math.floor(nBitsTotal / 0x100000000);
+ var nBitsTotalL = nBitsTotal;
+ dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 15] = (
+ (((nBitsTotalH << 8) | (nBitsTotalH >>> 24)) & 0x00ff00ff) |
+ (((nBitsTotalH << 24) | (nBitsTotalH >>> 8)) & 0xff00ff00)
+ );
+ dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 14] = (
+ (((nBitsTotalL << 8) | (nBitsTotalL >>> 24)) & 0x00ff00ff) |
+ (((nBitsTotalL << 24) | (nBitsTotalL >>> 8)) & 0xff00ff00)
+ );
+
+ data.sigBytes = (dataWords.length + 1) * 4;
+
+ // Hash final blocks
+ this._process();
+
+ // Shortcuts
+ var hash = this._hash;
+ var H = hash.words;
+
+ // Swap endian
+ for (var i = 0; i < 4; i++) {
+ // Shortcut
+ var H_i = H[i];
+
+ H[i] = (((H_i << 8) | (H_i >>> 24)) & 0x00ff00ff) |
+ (((H_i << 24) | (H_i >>> 8)) & 0xff00ff00);
+ }
+
+ // Return final computed hash
+ return hash;
+ },
+
+ clone: function () {
+ var clone = Hasher.clone.call(this);
+ clone._hash = this._hash.clone();
+
+ return clone;
+ }
+ });
+
+ function FF(a, b, c, d, x, s, t) {
+ var n = a + ((b & c) | (~b & d)) + x + t;
+ return ((n << s) | (n >>> (32 - s))) + b;
+ }
+
+ function GG(a, b, c, d, x, s, t) {
+ var n = a + ((b & d) | (c & ~d)) + x + t;
+ return ((n << s) | (n >>> (32 - s))) + b;
+ }
+
+ function HH(a, b, c, d, x, s, t) {
+ var n = a + (b ^ c ^ d) + x + t;
+ return ((n << s) | (n >>> (32 - s))) + b;
+ }
+
+ function II(a, b, c, d, x, s, t) {
+ var n = a + (c ^ (b | ~d)) + x + t;
+ return ((n << s) | (n >>> (32 - s))) + b;
+ }
+
+ /**
+ * Shortcut function to the hasher's object interface.
+ *
+ * @param {WordArray|string} message The message to hash.
+ *
+ * @return {WordArray} The hash.
+ *
+ * @static
+ *
+ * @example
+ *
+ * var hash = CryptoJS.MD5('message');
+ * var hash = CryptoJS.MD5(wordArray);
+ */
+ C.MD5 = Hasher._createHelper(MD5);
+
+ /**
+ * Shortcut function to the HMAC's object interface.
+ *
+ * @param {WordArray|string} message The message to hash.
+ * @param {WordArray|string} key The secret key.
+ *
+ * @return {WordArray} The HMAC.
+ *
+ * @static
+ *
+ * @example
+ *
+ * var hmac = CryptoJS.HmacMD5(message, key);
+ */
+ C.HmacMD5 = Hasher._createHmacHelper(MD5);
+}(Math));
+
+(function () {
+ // Shortcuts
+ var C = CryptoJS;
+ var C_lib = C.lib;
+ var Base = C_lib.Base;
+ var WordArray = C_lib.WordArray;
+ var C_algo = C.algo;
+ var MD5 = C_algo.MD5;
+
+ /**
+ * This key derivation function is meant to conform with EVP_BytesToKey.
+ * www.openssl.org/docs/crypto/EVP_BytesToKey.html
+ */
+ var EvpKDF = C_algo.EvpKDF = Base.extend({
+ /**
+ * Configuration options.
+ *
+ * @property {number} keySize The key size in words to generate. Default: 4 (128 bits)
+ * @property {Hasher} hasher The hash algorithm to use. Default: MD5
+ * @property {number} iterations The number of iterations to perform. Default: 1
+ */
+ cfg: Base.extend({
+ keySize: 128/32,
+ hasher: MD5,
+ iterations: 1
+ }),
+
+ /**
+ * Initializes a newly created key derivation function.
+ *
+ * @param {Object} cfg (Optional) The configuration options to use for the derivation.
+ *
+ * @example
+ *
+ * var kdf = CryptoJS.algo.EvpKDF.create();
+ * var kdf = CryptoJS.algo.EvpKDF.create({ keySize: 8 });
+ * var kdf = CryptoJS.algo.EvpKDF.create({ keySize: 8, iterations: 1000 });
+ */
+ init: function (cfg) {
+ this.cfg = this.cfg.extend(cfg);
+ },
+
+ /**
+ * Derives a key from a password.
+ *
+ * @param {WordArray|string} password The password.
+ * @param {WordArray|string} salt A salt.
+ *
+ * @return {WordArray} The derived key.
+ *
+ * @example
+ *
+ * var key = kdf.compute(password, salt);
+ */
+ compute: function (password, salt) {
+ // Shortcut
+ var cfg = this.cfg;
+
+ // Init hasher
+ var hasher = cfg.hasher.create();
+
+ // Initial values
+ var derivedKey = WordArray.create();
+
+ // Shortcuts
+ var derivedKeyWords = derivedKey.words;
+ var keySize = cfg.keySize;
+ var iterations = cfg.iterations;
+
+ // Generate key
+ while (derivedKeyWords.length < keySize) {
+ if (block) {
+ hasher.update(block);
+ }
+ var block = hasher.update(password).finalize(salt);
+ hasher.reset();
+
+ // Iterations
+ for (var i = 1; i < iterations; i++) {
+ block = hasher.finalize(block);
+ hasher.reset();
+ }
+
+ derivedKey.concat(block);
+ }
+ derivedKey.sigBytes = keySize * 4;
+
+ return derivedKey;
+ }
+ });
+
+ /**
+ * Derives a key from a password.
+ *
+ * @param {WordArray|string} password The password.
+ * @param {WordArray|string} salt A salt.
+ * @param {Object} cfg (Optional) The configuration options to use for this computation.
+ *
+ * @return {WordArray} The derived key.
+ *
+ * @static
+ *
+ * @example
+ *
+ * var key = CryptoJS.EvpKDF(password, salt);
+ * var key = CryptoJS.EvpKDF(password, salt, { keySize: 8 });
+ * var key = CryptoJS.EvpKDF(password, salt, { keySize: 8, iterations: 1000 });
+ */
+ C.EvpKDF = function (password, salt, cfg) {
+ return EvpKDF.create(cfg).compute(password, salt);
+ };
+}());
+
+/**
+ * Cipher core components.
+ */
+CryptoJS.lib.Cipher || (function (undefined) {
+ // Shortcuts
+ var C = CryptoJS;
+ var C_lib = C.lib;
+ var Base = C_lib.Base;
+ var WordArray = C_lib.WordArray;
+ var BufferedBlockAlgorithm = C_lib.BufferedBlockAlgorithm;
+ var C_enc = C.enc;
+ var Utf8 = C_enc.Utf8;
+ var Base64 = C_enc.Base64;
+ var C_algo = C.algo;
+ var EvpKDF = C_algo.EvpKDF;
+
+ /**
+ * Abstract base cipher template.
+ *
+ * @property {number} keySize This cipher's key size. Default: 4 (128 bits)
+ * @property {number} ivSize This cipher's IV size. Default: 4 (128 bits)
+ * @property {number} _ENC_XFORM_MODE A constant representing encryption mode.
+ * @property {number} _DEC_XFORM_MODE A constant representing decryption mode.
+ */
+ var Cipher = C_lib.Cipher = BufferedBlockAlgorithm.extend({
+ /**
+ * Configuration options.
+ *
+ * @property {WordArray} iv The IV to use for this operation.
+ */
+ cfg: Base.extend(),
+
+ /**
+ * Creates this cipher in encryption mode.
+ *
+ * @param {WordArray} key The key.
+ * @param {Object} cfg (Optional) The configuration options to use for this operation.
+ *
+ * @return {Cipher} A cipher instance.
+ *
+ * @static
+ *
+ * @example
+ *
+ * var cipher = CryptoJS.algo.AES.createEncryptor(keyWordArray, { iv: ivWordArray });
+ */
+ createEncryptor: function (key, cfg) {
+ return this.create(this._ENC_XFORM_MODE, key, cfg);
+ },
+
+ /**
+ * Creates this cipher in decryption mode.
+ *
+ * @param {WordArray} key The key.
+ * @param {Object} cfg (Optional) The configuration options to use for this operation.
+ *
+ * @return {Cipher} A cipher instance.
+ *
+ * @static
+ *
+ * @example
+ *
+ * var cipher = CryptoJS.algo.AES.createDecryptor(keyWordArray, { iv: ivWordArray });
+ */
+ createDecryptor: function (key, cfg) {
+ return this.create(this._DEC_XFORM_MODE, key, cfg);
+ },
+
+ /**
+ * Initializes a newly created cipher.
+ *
+ * @param {number} xformMode Either the encryption or decryption transormation mode constant.
+ * @param {WordArray} key The key.
+ * @param {Object} cfg (Optional) The configuration options to use for this operation.
+ *
+ * @example
+ *
+ * var cipher = CryptoJS.algo.AES.create(CryptoJS.algo.AES._ENC_XFORM_MODE, keyWordArray, { iv: ivWordArray });
+ */
+ init: function (xformMode, key, cfg) {
+ // Apply config defaults
+ this.cfg = this.cfg.extend(cfg);
+
+ // Store transform mode and key
+ this._xformMode = xformMode;
+ this._key = key;
+
+ // Set initial values
+ this.reset();
+ },
+
+ /**
+ * Resets this cipher to its initial state.
+ *
+ * @example
+ *
+ * cipher.reset();
+ */
+ reset: function () {
+ // Reset data buffer
+ BufferedBlockAlgorithm.reset.call(this);
+
+ // Perform concrete-cipher logic
+ this._doReset();
+ },
+
+ /**
+ * Adds data to be encrypted or decrypted.
+ *
+ * @param {WordArray|string} dataUpdate The data to encrypt or decrypt.
+ *
+ * @return {WordArray} The data after processing.
+ *
+ * @example
+ *
+ * var encrypted = cipher.process('data');
+ * var encrypted = cipher.process(wordArray);
+ */
+ process: function (dataUpdate) {
+ // Append
+ this._append(dataUpdate);
+
+ // Process available blocks
+ return this._process();
+ },
+
+ /**
+ * Finalizes the encryption or decryption process.
+ * Note that the finalize operation is effectively a destructive, read-once operation.
+ *
+ * @param {WordArray|string} dataUpdate The final data to encrypt or decrypt.
+ *
+ * @return {WordArray} The data after final processing.
+ *
+ * @example
+ *
+ * var encrypted = cipher.finalize();
+ * var encrypted = cipher.finalize('data');
+ * var encrypted = cipher.finalize(wordArray);
+ */
+ finalize: function (dataUpdate) {
+ // Final data update
+ if (dataUpdate) {
+ this._append(dataUpdate);
+ }
+
+ // Perform concrete-cipher logic
+ var finalProcessedData = this._doFinalize();
+
+ return finalProcessedData;
+ },
+
+ keySize: 128/32,
+
+ ivSize: 128/32,
+
+ _ENC_XFORM_MODE: 1,
+
+ _DEC_XFORM_MODE: 2,
+
+ /**
+ * Creates shortcut functions to a cipher's object interface.
+ *
+ * @param {Cipher} cipher The cipher to create a helper for.
+ *
+ * @return {Object} An object with encrypt and decrypt shortcut functions.
+ *
+ * @static
+ *
+ * @example
+ *
+ * var AES = CryptoJS.lib.Cipher._createHelper(CryptoJS.algo.AES);
+ */
+ _createHelper: (function () {
+ function selectCipherStrategy(key) {
+ if (typeof key == 'string') {
+ return PasswordBasedCipher;
+ } else {
+ return SerializableCipher;
+ }
+ }
+
+ return function (cipher) {
+ return {
+ encrypt: function (message, key, cfg) {
+ return selectCipherStrategy(key).encrypt(cipher, message, key, cfg);
+ },
+
+ decrypt: function (ciphertext, key, cfg) {
+ return selectCipherStrategy(key).decrypt(cipher, ciphertext, key, cfg);
+ }
+ };
+ };
+ }())
+ });
+
+ /**
+ * Abstract base stream cipher template.
+ *
+ * @property {number} blockSize The number of 32-bit words this cipher operates on. Default: 1 (32 bits)
+ */
+ var StreamCipher = C_lib.StreamCipher = Cipher.extend({
+ _doFinalize: function () {
+ // Process partial blocks
+ var finalProcessedBlocks = this._process(!!'flush');
+
+ return finalProcessedBlocks;
+ },
+
+ blockSize: 1
+ });
+
+ /**
+ * Mode namespace.
+ */
+ var C_mode = C.mode = {};
+
+ /**
+ * Abstract base block cipher mode template.
+ */
+ var BlockCipherMode = C_lib.BlockCipherMode = Base.extend({
+ /**
+ * Creates this mode for encryption.
+ *
+ * @param {Cipher} cipher A block cipher instance.
+ * @param {Array} iv The IV words.
+ *
+ * @static
+ *
+ * @example
+ *
+ * var mode = CryptoJS.mode.CBC.createEncryptor(cipher, iv.words);
+ */
+ createEncryptor: function (cipher, iv) {
+ return this.Encryptor.create(cipher, iv);
+ },
+
+ /**
+ * Creates this mode for decryption.
+ *
+ * @param {Cipher} cipher A block cipher instance.
+ * @param {Array} iv The IV words.
+ *
+ * @static
+ *
+ * @example
+ *
+ * var mode = CryptoJS.mode.CBC.createDecryptor(cipher, iv.words);
+ */
+ createDecryptor: function (cipher, iv) {
+ return this.Decryptor.create(cipher, iv);
+ },
+
+ /**
+ * Initializes a newly created mode.
+ *
+ * @param {Cipher} cipher A block cipher instance.
+ * @param {Array} iv The IV words.
+ *
+ * @example
+ *
+ * var mode = CryptoJS.mode.CBC.Encryptor.create(cipher, iv.words);
+ */
+ init: function (cipher, iv) {
+ this._cipher = cipher;
+ this._iv = iv;
+ }
+ });
+
+ /**
+ * Cipher Block Chaining mode.
+ */
+ var CBC = C_mode.CBC = (function () {
+ /**
+ * Abstract base CBC mode.
+ */
+ var CBC = BlockCipherMode.extend();
+
+ /**
+ * CBC encryptor.
+ */
+ CBC.Encryptor = CBC.extend({
+ /**
+ * Processes the data block at offset.
+ *
+ * @param {Array} words The data words to operate on.
+ * @param {number} offset The offset where the block starts.
+ *
+ * @example
+ *
+ * mode.processBlock(data.words, offset);
+ */
+ processBlock: function (words, offset) {
+ // Shortcuts
+ var cipher = this._cipher;
+ var blockSize = cipher.blockSize;
+
+ // XOR and encrypt
+ xorBlock.call(this, words, offset, blockSize);
+ cipher.encryptBlock(words, offset);
+
+ // Remember this block to use with next block
+ this._prevBlock = words.slice(offset, offset + blockSize);
+ }
+ });
+
+ /**
+ * CBC decryptor.
+ */
+ CBC.Decryptor = CBC.extend({
+ /**
+ * Processes the data block at offset.
+ *
+ * @param {Array} words The data words to operate on.
+ * @param {number} offset The offset where the block starts.
+ *
+ * @example
+ *
+ * mode.processBlock(data.words, offset);
+ */
+ processBlock: function (words, offset) {
+ // Shortcuts
+ var cipher = this._cipher;
+ var blockSize = cipher.blockSize;
+
+ // Remember this block to use with next block
+ var thisBlock = words.slice(offset, offset + blockSize);
+
+ // Decrypt and XOR
+ cipher.decryptBlock(words, offset);
+ xorBlock.call(this, words, offset, blockSize);
+
+ // This block becomes the previous block
+ this._prevBlock = thisBlock;
+ }
+ });
+
+ function xorBlock(words, offset, blockSize) {
+ // Shortcut
+ var iv = this._iv;
+
+ // Choose mixing block
+ if (iv) {
+ var block = iv;
+
+ // Remove IV for subsequent blocks
+ this._iv = undefined;
+ } else {
+ var block = this._prevBlock;
+ }
+
+ // XOR blocks
+ for (var i = 0; i < blockSize; i++) {
+ words[offset + i] ^= block[i];
+ }
+ }
+
+ return CBC;
+ }());
+
+ /**
+ * Padding namespace.
+ */
+ var C_pad = C.pad = {};
+
+ /**
+ * PKCS #5/7 padding strategy.
+ */
+ var Pkcs7 = C_pad.Pkcs7 = {
+ /**
+ * Pads data using the algorithm defined in PKCS #5/7.
+ *
+ * @param {WordArray} data The data to pad.
+ * @param {number} blockSize The multiple that the data should be padded to.
+ *
+ * @static
+ *
+ * @example
+ *
+ * CryptoJS.pad.Pkcs7.pad(wordArray, 4);
+ */
+ pad: function (data, blockSize) {
+ // Shortcut
+ var blockSizeBytes = blockSize * 4;
+
+ // Count padding bytes
+ var nPaddingBytes = blockSizeBytes - data.sigBytes % blockSizeBytes;
+
+ // Create padding word
+ var paddingWord = (nPaddingBytes << 24) | (nPaddingBytes << 16) | (nPaddingBytes << 8) | nPaddingBytes;
+
+ // Create padding
+ var paddingWords = [];
+ for (var i = 0; i < nPaddingBytes; i += 4) {
+ paddingWords.push(paddingWord);
+ }
+ var padding = WordArray.create(paddingWords, nPaddingBytes);
+
+ // Add padding
+ data.concat(padding);
+ },
+
+ /**
+ * Unpads data that had been padded using the algorithm defined in PKCS #5/7.
+ *
+ * @param {WordArray} data The data to unpad.
+ *
+ * @static
+ *
+ * @example
+ *
+ * CryptoJS.pad.Pkcs7.unpad(wordArray);
+ */
+ unpad: function (data) {
+ // Get number of padding bytes from last byte
+ var nPaddingBytes = data.words[(data.sigBytes - 1) >>> 2] & 0xff;
+
+ // Remove padding
+ data.sigBytes -= nPaddingBytes;
+ }
+ };
+
+ /**
+ * Abstract base block cipher template.
+ *
+ * @property {number} blockSize The number of 32-bit words this cipher operates on. Default: 4 (128 bits)
+ */
+ var BlockCipher = C_lib.BlockCipher = Cipher.extend({
+ /**
+ * Configuration options.
+ *
+ * @property {Mode} mode The block mode to use. Default: CBC
+ * @property {Padding} padding The padding strategy to use. Default: Pkcs7
+ */
+ cfg: Cipher.cfg.extend({
+ mode: CBC,
+ padding: Pkcs7
+ }),
+
+ reset: function () {
+ // Reset cipher
+ Cipher.reset.call(this);
+
+ // Shortcuts
+ var cfg = this.cfg;
+ var iv = cfg.iv;
+ var mode = cfg.mode;
+
+ // Reset block mode
+ if (this._xformMode == this._ENC_XFORM_MODE) {
+ var modeCreator = mode.createEncryptor;
+ } else /* if (this._xformMode == this._DEC_XFORM_MODE) */ {
+ var modeCreator = mode.createDecryptor;
+
+ // Keep at least one block in the buffer for unpadding
+ this._minBufferSize = 1;
+ }
+ this._mode = modeCreator.call(mode, this, iv && iv.words);
+ },
+
+ _doProcessBlock: function (words, offset) {
+ this._mode.processBlock(words, offset);
+ },
+
+ _doFinalize: function () {
+ // Shortcut
+ var padding = this.cfg.padding;
+
+ // Finalize
+ if (this._xformMode == this._ENC_XFORM_MODE) {
+ // Pad data
+ padding.pad(this._data, this.blockSize);
+
+ // Process final blocks
+ var finalProcessedBlocks = this._process(!!'flush');
+ } else /* if (this._xformMode == this._DEC_XFORM_MODE) */ {
+ // Process final blocks
+ var finalProcessedBlocks = this._process(!!'flush');
+
+ // Unpad data
+ padding.unpad(finalProcessedBlocks);
+ }
+
+ return finalProcessedBlocks;
+ },
+
+ blockSize: 128/32
+ });
+
+ /**
+ * A collection of cipher parameters.
+ *
+ * @property {WordArray} ciphertext The raw ciphertext.
+ * @property {WordArray} key The key to this ciphertext.
+ * @property {WordArray} iv The IV used in the ciphering operation.
+ * @property {WordArray} salt The salt used with a key derivation function.
+ * @property {Cipher} algorithm The cipher algorithm.
+ * @property {Mode} mode The block mode used in the ciphering operation.
+ * @property {Padding} padding The padding scheme used in the ciphering operation.
+ * @property {number} blockSize The block size of the cipher.
+ * @property {Format} formatter The default formatting strategy to convert this cipher params object to a string.
+ */
+ var CipherParams = C_lib.CipherParams = Base.extend({
+ /**
+ * Initializes a newly created cipher params object.
+ *
+ * @param {Object} cipherParams An object with any of the possible cipher parameters.
+ *
+ * @example
+ *
+ * var cipherParams = CryptoJS.lib.CipherParams.create({
+ * ciphertext: ciphertextWordArray,
+ * key: keyWordArray,
+ * iv: ivWordArray,
+ * salt: saltWordArray,
+ * algorithm: CryptoJS.algo.AES,
+ * mode: CryptoJS.mode.CBC,
+ * padding: CryptoJS.pad.PKCS7,
+ * blockSize: 4,
+ * formatter: CryptoJS.format.OpenSSL
+ * });
+ */
+ init: function (cipherParams) {
+ this.mixIn(cipherParams);
+ },
+
+ /**
+ * Converts this cipher params object to a string.
+ *
+ * @param {Format} formatter (Optional) The formatting strategy to use.
+ *
+ * @return {string} The stringified cipher params.
+ *
+ * @throws Error If neither the formatter nor the default formatter is set.
+ *
+ * @example
+ *
+ * var string = cipherParams + '';
+ * var string = cipherParams.toString();
+ * var string = cipherParams.toString(CryptoJS.format.OpenSSL);
+ */
+ toString: function (formatter) {
+ return (formatter || this.formatter).stringify(this);
+ }
+ });
+
+ /**
+ * Format namespace.
+ */
+ var C_format = C.format = {};
+
+ /**
+ * OpenSSL formatting strategy.
+ */
+ var OpenSSLFormatter = C_format.OpenSSL = {
+ /**
+ * Converts a cipher params object to an OpenSSL-compatible string.
+ *
+ * @param {CipherParams} cipherParams The cipher params object.
+ *
+ * @return {string} The OpenSSL-compatible string.
+ *
+ * @static
+ *
+ * @example
+ *
+ * var openSSLString = CryptoJS.format.OpenSSL.stringify(cipherParams);
+ */
+ stringify: function (cipherParams) {
+ // Shortcuts
+ var ciphertext = cipherParams.ciphertext;
+ var salt = cipherParams.salt;
+
+ // Format
+ if (salt) {
+ var wordArray = WordArray.create([0x53616c74, 0x65645f5f]).concat(salt).concat(ciphertext);
+ } else {
+ var wordArray = ciphertext;
+ }
+
+ return wordArray.toString(Base64);
+ },
+
+ /**
+ * Converts an OpenSSL-compatible string to a cipher params object.
+ *
+ * @param {string} openSSLStr The OpenSSL-compatible string.
+ *
+ * @return {CipherParams} The cipher params object.
+ *
+ * @static
+ *
+ * @example
+ *
+ * var cipherParams = CryptoJS.format.OpenSSL.parse(openSSLString);
+ */
+ parse: function (openSSLStr) {
+ // Parse base64
+ var ciphertext = Base64.parse(openSSLStr);
+
+ // Shortcut
+ var ciphertextWords = ciphertext.words;
+
+ // Test for salt
+ if (ciphertextWords[0] == 0x53616c74 && ciphertextWords[1] == 0x65645f5f) {
+ // Extract salt
+ var salt = WordArray.create(ciphertextWords.slice(2, 4));
+
+ // Remove salt from ciphertext
+ ciphertextWords.splice(0, 4);
+ ciphertext.sigBytes -= 16;
+ }
+
+ return CipherParams.create({ ciphertext: ciphertext, salt: salt });
+ }
+ };
+
+ /**
+ * A cipher wrapper that returns ciphertext as a serializable cipher params object.
+ */
+ var SerializableCipher = C_lib.SerializableCipher = Base.extend({
+ /**
+ * Configuration options.
+ *
+ * @property {Formatter} format The formatting strategy to convert cipher param objects to and from a string. Default: OpenSSL
+ */
+ cfg: Base.extend({
+ format: OpenSSLFormatter
+ }),
+
+ /**
+ * Encrypts a message.
+ *
+ * @param {Cipher} cipher The cipher algorithm to use.
+ * @param {WordArray|string} message The message to encrypt.
+ * @param {WordArray} key The key.
+ * @param {Object} cfg (Optional) The configuration options to use for this operation.
+ *
+ * @return {CipherParams} A cipher params object.
+ *
+ * @static
+ *
+ * @example
+ *
+ * var ciphertextParams = CryptoJS.lib.SerializableCipher.encrypt(CryptoJS.algo.AES, message, key);
+ * var ciphertextParams = CryptoJS.lib.SerializableCipher.encrypt(CryptoJS.algo.AES, message, key, { iv: iv });
+ * var ciphertextParams = CryptoJS.lib.SerializableCipher.encrypt(CryptoJS.algo.AES, message, key, { iv: iv, format: CryptoJS.format.OpenSSL });
+ */
+ encrypt: function (cipher, message, key, cfg) {
+ // Apply config defaults
+ cfg = this.cfg.extend(cfg);
+
+ // Encrypt
+ var encryptor = cipher.createEncryptor(key, cfg);
+ var ciphertext = encryptor.finalize(message);
+
+ // Shortcut
+ var cipherCfg = encryptor.cfg;
+
+ // Create and return serializable cipher params
+ return CipherParams.create({
+ ciphertext: ciphertext,
+ key: key,
+ iv: cipherCfg.iv,
+ algorithm: cipher,
+ mode: cipherCfg.mode,
+ padding: cipherCfg.padding,
+ blockSize: cipher.blockSize,
+ formatter: cfg.format
+ });
+ },
+
+ /**
+ * Decrypts serialized ciphertext.
+ *
+ * @param {Cipher} cipher The cipher algorithm to use.
+ * @param {CipherParams|string} ciphertext The ciphertext to decrypt.
+ * @param {WordArray} key The key.
+ * @param {Object} cfg (Optional) The configuration options to use for this operation.
+ *
+ * @return {WordArray} The plaintext.
+ *
+ * @static
+ *
+ * @example
+ *
+ * var plaintext = CryptoJS.lib.SerializableCipher.decrypt(CryptoJS.algo.AES, formattedCiphertext, key, { iv: iv, format: CryptoJS.format.OpenSSL });
+ * var plaintext = CryptoJS.lib.SerializableCipher.decrypt(CryptoJS.algo.AES, ciphertextParams, key, { iv: iv, format: CryptoJS.format.OpenSSL });
+ */
+ decrypt: function (cipher, ciphertext, key, cfg) {
+ // Apply config defaults
+ cfg = this.cfg.extend(cfg);
+
+ // Convert string to CipherParams
+ ciphertext = this._parse(ciphertext, cfg.format);
+
+ // Decrypt
+ var plaintext = cipher.createDecryptor(key, cfg).finalize(ciphertext.ciphertext);
+
+ return plaintext;
+ },
+
+ /**
+ * Converts serialized ciphertext to CipherParams,
+ * else assumed CipherParams already and returns ciphertext unchanged.
+ *
+ * @param {CipherParams|string} ciphertext The ciphertext.
+ * @param {Formatter} format The formatting strategy to use to parse serialized ciphertext.
+ *
+ * @return {CipherParams} The unserialized ciphertext.
+ *
+ * @static
+ *
+ * @example
+ *
+ * var ciphertextParams = CryptoJS.lib.SerializableCipher._parse(ciphertextStringOrParams, format);
+ */
+ _parse: function (ciphertext, format) {
+ if (typeof ciphertext == 'string') {
+ return format.parse(ciphertext, this);
+ } else {
+ return ciphertext;
+ }
+ }
+ });
+
+ /**
+ * Key derivation function namespace.
+ */
+ var C_kdf = C.kdf = {};
+
+ /**
+ * OpenSSL key derivation function.
+ */
+ var OpenSSLKdf = C_kdf.OpenSSL = {
+ /**
+ * Derives a key and IV from a password.
+ *
+ * @param {string} password The password to derive from.
+ * @param {number} keySize The size in words of the key to generate.
+ * @param {number} ivSize The size in words of the IV to generate.
+ * @param {WordArray|string} salt (Optional) A 64-bit salt to use. If omitted, a salt will be generated randomly.
+ *
+ * @return {CipherParams} A cipher params object with the key, IV, and salt.
+ *
+ * @static
+ *
+ * @example
+ *
+ * var derivedParams = CryptoJS.kdf.OpenSSL.execute('Password', 256/32, 128/32);
+ * var derivedParams = CryptoJS.kdf.OpenSSL.execute('Password', 256/32, 128/32, 'saltsalt');
+ */
+ execute: function (password, keySize, ivSize, salt) {
+ // Generate random salt
+ if (!salt) {
+ salt = WordArray.random(64/8);
+ }
+
+ // Derive key and IV
+ var key = EvpKDF.create({ keySize: keySize + ivSize }).compute(password, salt);
+
+ // Separate key and IV
+ var iv = WordArray.create(key.words.slice(keySize), ivSize * 4);
+ key.sigBytes = keySize * 4;
+
+ // Return params
+ return CipherParams.create({ key: key, iv: iv, salt: salt });
+ }
+ };
+
+ /**
+ * A serializable cipher wrapper that derives the key from a password,
+ * and returns ciphertext as a serializable cipher params object.
+ */
+ var PasswordBasedCipher = C_lib.PasswordBasedCipher = SerializableCipher.extend({
+ /**
+ * Configuration options.
+ *
+ * @property {KDF} kdf The key derivation function to use to generate a key and IV from a password. Default: OpenSSL
+ */
+ cfg: SerializableCipher.cfg.extend({
+ kdf: OpenSSLKdf
+ }),
+
+ /**
+ * Encrypts a message using a password.
+ *
+ * @param {Cipher} cipher The cipher algorithm to use.
+ * @param {WordArray|string} message The message to encrypt.
+ * @param {string} password The password.
+ * @param {Object} cfg (Optional) The configuration options to use for this operation.
+ *
+ * @return {CipherParams} A cipher params object.
+ *
+ * @static
+ *
+ * @example
+ *
+ * var ciphertextParams = CryptoJS.lib.PasswordBasedCipher.encrypt(CryptoJS.algo.AES, message, 'password');
+ * var ciphertextParams = CryptoJS.lib.PasswordBasedCipher.encrypt(CryptoJS.algo.AES, message, 'password', { format: CryptoJS.format.OpenSSL });
+ */
+ encrypt: function (cipher, message, password, cfg) {
+ // Apply config defaults
+ cfg = this.cfg.extend(cfg);
+
+ // Derive key and other params
+ var derivedParams = cfg.kdf.execute(password, cipher.keySize, cipher.ivSize);
+
+ // Add IV to config
+ cfg.iv = derivedParams.iv;
+
+ // Encrypt
+ var ciphertext = SerializableCipher.encrypt.call(this, cipher, message, derivedParams.key, cfg);
+
+ // Mix in derived params
+ ciphertext.mixIn(derivedParams);
+
+ return ciphertext;
+ },
+
+ /**
+ * Decrypts serialized ciphertext using a password.
+ *
+ * @param {Cipher} cipher The cipher algorithm to use.
+ * @param {CipherParams|string} ciphertext The ciphertext to decrypt.
+ * @param {string} password The password.
+ * @param {Object} cfg (Optional) The configuration options to use for this operation.
+ *
+ * @return {WordArray} The plaintext.
+ *
+ * @static
+ *
+ * @example
+ *
+ * var plaintext = CryptoJS.lib.PasswordBasedCipher.decrypt(CryptoJS.algo.AES, formattedCiphertext, 'password', { format: CryptoJS.format.OpenSSL });
+ * var plaintext = CryptoJS.lib.PasswordBasedCipher.decrypt(CryptoJS.algo.AES, ciphertextParams, 'password', { format: CryptoJS.format.OpenSSL });
+ */
+ decrypt: function (cipher, ciphertext, password, cfg) {
+ // Apply config defaults
+ cfg = this.cfg.extend(cfg);
+
+ // Convert string to CipherParams
+ ciphertext = this._parse(ciphertext, cfg.format);
+
+ // Derive key and other params
+ var derivedParams = cfg.kdf.execute(password, cipher.keySize, cipher.ivSize, ciphertext.salt);
+
+ // Add IV to config
+ cfg.iv = derivedParams.iv;
+
+ // Decrypt
+ var plaintext = SerializableCipher.decrypt.call(this, cipher, ciphertext, derivedParams.key, cfg);
+
+ return plaintext;
+ }
+ });
+}());
+
+(function () {
+ // Shortcuts
+ var C = CryptoJS;
+ var C_lib = C.lib;
+ var BlockCipher = C_lib.BlockCipher;
+ var C_algo = C.algo;
+
+ // Lookup tables
+ var SBOX = [];
+ var INV_SBOX = [];
+ var SUB_MIX_0 = [];
+ var SUB_MIX_1 = [];
+ var SUB_MIX_2 = [];
+ var SUB_MIX_3 = [];
+ var INV_SUB_MIX_0 = [];
+ var INV_SUB_MIX_1 = [];
+ var INV_SUB_MIX_2 = [];
+ var INV_SUB_MIX_3 = [];
+
+ // Compute lookup tables
+ (function () {
+ // Compute double table
+ var d = [];
+ for (var i = 0; i < 256; i++) {
+ if (i < 128) {
+ d[i] = i << 1;
+ } else {
+ d[i] = (i << 1) ^ 0x11b;
+ }
+ }
+
+ // Walk GF(2^8)
+ var x = 0;
+ var xi = 0;
+ for (var i = 0; i < 256; i++) {
+ // Compute sbox
+ var sx = xi ^ (xi << 1) ^ (xi << 2) ^ (xi << 3) ^ (xi << 4);
+ sx = (sx >>> 8) ^ (sx & 0xff) ^ 0x63;
+ SBOX[x] = sx;
+ INV_SBOX[sx] = x;
+
+ // Compute multiplication
+ var x2 = d[x];
+ var x4 = d[x2];
+ var x8 = d[x4];
+
+ // Compute sub bytes, mix columns tables
+ var t = (d[sx] * 0x101) ^ (sx * 0x1010100);
+ SUB_MIX_0[x] = (t << 24) | (t >>> 8);
+ SUB_MIX_1[x] = (t << 16) | (t >>> 16);
+ SUB_MIX_2[x] = (t << 8) | (t >>> 24);
+ SUB_MIX_3[x] = t;
+
+ // Compute inv sub bytes, inv mix columns tables
+ var t = (x8 * 0x1010101) ^ (x4 * 0x10001) ^ (x2 * 0x101) ^ (x * 0x1010100);
+ INV_SUB_MIX_0[sx] = (t << 24) | (t >>> 8);
+ INV_SUB_MIX_1[sx] = (t << 16) | (t >>> 16);
+ INV_SUB_MIX_2[sx] = (t << 8) | (t >>> 24);
+ INV_SUB_MIX_3[sx] = t;
+
+ // Compute next counter
+ if (!x) {
+ x = xi = 1;
+ } else {
+ x = x2 ^ d[d[d[x8 ^ x2]]];
+ xi ^= d[d[xi]];
+ }
+ }
+ }());
+
+ // Precomputed Rcon lookup
+ var RCON = [0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36];
+
+ /**
+ * AES block cipher algorithm.
+ */
+ var AES = C_algo.AES = BlockCipher.extend({
+ _doReset: function () {
+ // Shortcuts
+ var key = this._key;
+ var keyWords = key.words;
+ var keySize = key.sigBytes / 4;
+
+ // Compute number of rounds
+ var nRounds = this._nRounds = keySize + 6
+
+ // Compute number of key schedule rows
+ var ksRows = (nRounds + 1) * 4;
+
+ // Compute key schedule
+ var keySchedule = this._keySchedule = [];
+ for (var ksRow = 0; ksRow < ksRows; ksRow++) {
+ if (ksRow < keySize) {
+ keySchedule[ksRow] = keyWords[ksRow];
+ } else {
+ var t = keySchedule[ksRow - 1];
+
+ if (!(ksRow % keySize)) {
+ // Rot word
+ t = (t << 8) | (t >>> 24);
+
+ // Sub word
+ t = (SBOX[t >>> 24] << 24) | (SBOX[(t >>> 16) & 0xff] << 16) | (SBOX[(t >>> 8) & 0xff] << 8) | SBOX[t & 0xff];
+
+ // Mix Rcon
+ t ^= RCON[(ksRow / keySize) | 0] << 24;
+ } else if (keySize > 6 && ksRow % keySize == 4) {
+ // Sub word
+ t = (SBOX[t >>> 24] << 24) | (SBOX[(t >>> 16) & 0xff] << 16) | (SBOX[(t >>> 8) & 0xff] << 8) | SBOX[t & 0xff];
+ }
+
+ keySchedule[ksRow] = keySchedule[ksRow - keySize] ^ t;
+ }
+ }
+
+ // Compute inv key schedule
+ var invKeySchedule = this._invKeySchedule = [];
+ for (var invKsRow = 0; invKsRow < ksRows; invKsRow++) {
+ var ksRow = ksRows - invKsRow;
+
+ if (invKsRow % 4) {
+ var t = keySchedule[ksRow];
+ } else {
+ var t = keySchedule[ksRow - 4];
+ }
+
+ if (invKsRow < 4 || ksRow <= 4) {
+ invKeySchedule[invKsRow] = t;
+ } else {
+ invKeySchedule[invKsRow] = INV_SUB_MIX_0[SBOX[t >>> 24]] ^ INV_SUB_MIX_1[SBOX[(t >>> 16) & 0xff]] ^
+ INV_SUB_MIX_2[SBOX[(t >>> 8) & 0xff]] ^ INV_SUB_MIX_3[SBOX[t & 0xff]];
+ }
+ }
+ },
+
+ encryptBlock: function (M, offset) {
+ this._doCryptBlock(M, offset, this._keySchedule, SUB_MIX_0, SUB_MIX_1, SUB_MIX_2, SUB_MIX_3, SBOX);
+ },
+
+ decryptBlock: function (M, offset) {
+ // Swap 2nd and 4th rows
+ var t = M[offset + 1];
+ M[offset + 1] = M[offset + 3];
+ M[offset + 3] = t;
+
+ this._doCryptBlock(M, offset, this._invKeySchedule, INV_SUB_MIX_0, INV_SUB_MIX_1, INV_SUB_MIX_2, INV_SUB_MIX_3, INV_SBOX);
+
+ // Inv swap 2nd and 4th rows
+ var t = M[offset + 1];
+ M[offset + 1] = M[offset + 3];
+ M[offset + 3] = t;
+ },
+
+ _doCryptBlock: function (M, offset, keySchedule, SUB_MIX_0, SUB_MIX_1, SUB_MIX_2, SUB_MIX_3, SBOX) {
+ // Shortcut
+ var nRounds = this._nRounds;
+
+ // Get input, add round key
+ var s0 = M[offset] ^ keySchedule[0];
+ var s1 = M[offset + 1] ^ keySchedule[1];
+ var s2 = M[offset + 2] ^ keySchedule[2];
+ var s3 = M[offset + 3] ^ keySchedule[3];
+
+ // Key schedule row counter
+ var ksRow = 4;
+
+ // Rounds
+ for (var round = 1; round < nRounds; round++) {
+ // Shift rows, sub bytes, mix columns, add round key
+ var t0 = SUB_MIX_0[s0 >>> 24] ^ SUB_MIX_1[(s1 >>> 16) & 0xff] ^ SUB_MIX_2[(s2 >>> 8) & 0xff] ^ SUB_MIX_3[s3 & 0xff] ^ keySchedule[ksRow++];
+ var t1 = SUB_MIX_0[s1 >>> 24] ^ SUB_MIX_1[(s2 >>> 16) & 0xff] ^ SUB_MIX_2[(s3 >>> 8) & 0xff] ^ SUB_MIX_3[s0 & 0xff] ^ keySchedule[ksRow++];
+ var t2 = SUB_MIX_0[s2 >>> 24] ^ SUB_MIX_1[(s3 >>> 16) & 0xff] ^ SUB_MIX_2[(s0 >>> 8) & 0xff] ^ SUB_MIX_3[s1 & 0xff] ^ keySchedule[ksRow++];
+ var t3 = SUB_MIX_0[s3 >>> 24] ^ SUB_MIX_1[(s0 >>> 16) & 0xff] ^ SUB_MIX_2[(s1 >>> 8) & 0xff] ^ SUB_MIX_3[s2 & 0xff] ^ keySchedule[ksRow++];
+
+ // Update state
+ s0 = t0;
+ s1 = t1;
+ s2 = t2;
+ s3 = t3;
+ }
+
+ // Shift rows, sub bytes, add round key
+ var t0 = ((SBOX[s0 >>> 24] << 24) | (SBOX[(s1 >>> 16) & 0xff] << 16) | (SBOX[(s2 >>> 8) & 0xff] << 8) | SBOX[s3 & 0xff]) ^ keySchedule[ksRow++];
+ var t1 = ((SBOX[s1 >>> 24] << 24) | (SBOX[(s2 >>> 16) & 0xff] << 16) | (SBOX[(s3 >>> 8) & 0xff] << 8) | SBOX[s0 & 0xff]) ^ keySchedule[ksRow++];
+ var t2 = ((SBOX[s2 >>> 24] << 24) | (SBOX[(s3 >>> 16) & 0xff] << 16) | (SBOX[(s0 >>> 8) & 0xff] << 8) | SBOX[s1 & 0xff]) ^ keySchedule[ksRow++];
+ var t3 = ((SBOX[s3 >>> 24] << 24) | (SBOX[(s0 >>> 16) & 0xff] << 16) | (SBOX[(s1 >>> 8) & 0xff] << 8) | SBOX[s2 & 0xff]) ^ keySchedule[ksRow++];
+
+ // Set output
+ M[offset] = t0;
+ M[offset + 1] = t1;
+ M[offset + 2] = t2;
+ M[offset + 3] = t3;
+ },
+
+ keySize: 256/32
+ });
+
+ /**
+ * Shortcut functions to the cipher's object interface.
+ *
+ * @example
+ *
+ * var ciphertext = CryptoJS.AES.encrypt(message, key, cfg);
+ * var plaintext = CryptoJS.AES.decrypt(ciphertext, key, cfg);
+ */
+ C.AES = BlockCipher._createHelper(AES);
+}());
+
+/*
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+;(function() {
+ 'use strict';
+ // Test for webcrypto support, polyfill if needed.
+ if (window.crypto.subtle === undefined || window.crypto.subtle === null) {
+ window.crypto.subtle = (function () {
+ var StaticArrayBufferProto = new ArrayBuffer().__proto__;
+ function assertIsArrayBuffer(thing) {
+ if (thing !== Object(thing) || thing.__proto__ != StaticArrayBufferProto)
+ throw new Error("Needed a ArrayBuffer");
+ }
+
+ // Synchronous implementation functions for polyfilling webcrypto
+ // All inputs/outputs are arraybuffers!
+ function HmacSHA256(key, input) {
+ assertIsArrayBuffer(key);
+ assertIsArrayBuffer(input);
+ return CryptoJS.HmacSHA256(
+ CryptoJS.enc.Latin1.parse(axolotlInternal.utils.convertToString(input)),
+ CryptoJS.enc.Latin1.parse(axolotlInternal.utils.convertToString(key))
+ );
+ };
+
+ function encryptAESCBC(plaintext, key, iv) {
+ assertIsArrayBuffer(plaintext);
+ assertIsArrayBuffer(key);
+ assertIsArrayBuffer(iv);
+ return CryptoJS.AES.encrypt(
+ CryptoJS.enc.Latin1.parse(axolotlInternal.utils.convertToString(plaintext)),
+ CryptoJS.enc.Latin1.parse(axolotlInternal.utils.convertToString(key)),
+ { iv: CryptoJS.enc.Latin1.parse(axolotlInternal.utils.convertToString(iv)) }
+ ).ciphertext;
+ };
+
+ function decryptAESCBC(ciphertext, key, iv) {
+ assertIsArrayBuffer(ciphertext);
+ assertIsArrayBuffer(key);
+ assertIsArrayBuffer(iv);
+ return CryptoJS.AES.decrypt(
+ btoa(axolotlInternal.utils.convertToString(ciphertext)),
+ CryptoJS.enc.Latin1.parse(axolotlInternal.utils.convertToString(key)),
+ { iv: CryptoJS.enc.Latin1.parse(axolotlInternal.utils.convertToString(iv)) }
+ );
+ };
+
+ // utility function for connecting front and back ends via promises
+ // Takes an implementation function and 0 or more arguments
+ function promise(implementation) {
+ var args = Array.prototype.slice.call(arguments);
+ args.shift();
+ return new Promise(function(resolve) {
+ var wordArray = implementation.apply(this, args);
+ // convert 32bit WordArray to array buffer
+ var buffer = new ArrayBuffer(wordArray.sigBytes);
+ var view = new DataView(buffer);
+ for(var i = 0; i*4 < buffer.byteLength; i++) {
+ view.setInt32(i*4, wordArray.words[i]);
+ }
+ resolve(buffer);
+ });
+ };
+
+ return {
+ encrypt: function(algorithm, key, data) {
+ if (algorithm.name === "AES-CBC")
+ return promise(encryptAESCBC, data, key, algorithm.iv.buffer || algorithm.iv);
+ },
+
+ decrypt: function(algorithm, key, data) {
+ if (algorithm.name === "AES-CBC")
+ return promise(decryptAESCBC, data, key, algorithm.iv.buffer || algorithm.iv);
+ },
+
+ sign: function(algorithm, key, data) {
+ if (algorithm.name === "HMAC" && algorithm.hash === "SHA-256")
+ return promise(HmacSHA256, key, data);
+ },
+
+ importKey: function(format, key, algorithm, extractable, usages) {
+ return new Promise(function(resolve,reject){ resolve(key); });
+ }
+ };
+ })();
+ } // if !window.crypto.subtle
+})();
+
+})();
+/*
+ Copyright 2013 Daniel Wirtz
+ Copyright 2009 The Closure Library Authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS-IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+/**
+ * @license Long.js (c) 2013 Daniel Wirtz
+ * Released under the Apache License, Version 2.0
+ * see: https://github.com/dcodeIO/Long.js for details
+ */
+(function(global) {
+ "use strict";
+
+ /**
+ * Constructs a 64 bit two's-complement integer, given its low and high 32 bit values as *signed* integers.
+ * See the from* functions below for more convenient ways of constructing Longs.
+ * @exports Long
+ * @class A Long class for representing a 64 bit two's-complement integer value.
+ * @param {number} low The low (signed) 32 bits of the long
+ * @param {number} high The high (signed) 32 bits of the long
+ * @param {boolean=} unsigned Whether unsigned or not, defaults to `false` for signed
+ * @constructor
+ */
+ var Long = function(low, high, unsigned) {
+
+ /**
+ * The low 32 bits as a signed value.
+ * @type {number}
+ * @expose
+ */
+ this.low = low|0;
+
+ /**
+ * The high 32 bits as a signed value.
+ * @type {number}
+ * @expose
+ */
+ this.high = high|0;
+
+ /**
+ * Whether unsigned or not.
+ * @type {boolean}
+ * @expose
+ */
+ this.unsigned = !!unsigned;
+ };
+
+ // The internal representation of a long is the two given signed, 32-bit values.
+ // We use 32-bit pieces because these are the size of integers on which
+ // Javascript performs bit-operations. For operations like addition and
+ // multiplication, we split each number into 16 bit pieces, which can easily be
+ // multiplied within Javascript's floating-point representation without overflow
+ // or change in sign.
+ //
+ // In the algorithms below, we frequently reduce the negative case to the
+ // positive case by negating the input(s) and then post-processing the result.
+ // Note that we must ALWAYS check specially whether those values are MIN_VALUE
+ // (-2^63) because -MIN_VALUE == MIN_VALUE (since 2^63 cannot be represented as
+ // a positive number, it overflows back into a negative). Not handling this
+ // case would often result in infinite recursion.
+ //
+ // Common constant values ZERO, ONE, NEG_ONE, etc. are defined below the from*
+ // methods on which they depend.
+
+ /**
+ * Tests if the specified object is a Long.
+ * @param {*} obj Object
+ * @returns {boolean}
+ * @expose
+ */
+ Long.isLong = function(obj) {
+ return (obj && obj instanceof Long) === true;
+ };
+
+ /**
+ * A cache of the Long representations of small integer values.
+ * @type {!Object}
+ * @inner
+ */
+ var INT_CACHE = {};
+
+ /**
+ * A cache of the Long representations of small unsigned integer values.
+ * @type {!Object}
+ * @inner
+ */
+ var UINT_CACHE = {};
+
+ /**
+ * Returns a Long representing the given 32 bit integer value.
+ * @param {number} value The 32 bit integer in question
+ * @param {boolean=} unsigned Whether unsigned or not, defaults to `false` for signed
+ * @returns {!Long} The corresponding Long value
+ * @expose
+ */
+ Long.fromInt = function(value, unsigned) {
+ var obj, cachedObj;
+ if (!unsigned) {
+ value = value | 0;
+ if (-128 <= value && value < 128) {
+ cachedObj = INT_CACHE[value];
+ if (cachedObj)
+ return cachedObj;
+ }
+ obj = new Long(value, value < 0 ? -1 : 0, false);
+ if (-128 <= value && value < 128)
+ INT_CACHE[value] = obj;
+ return obj;
+ } else {
+ value = value >>> 0;
+ if (0 <= value && value < 256) {
+ cachedObj = UINT_CACHE[value];
+ if (cachedObj)
+ return cachedObj;
+ }
+ obj = new Long(value, (value | 0) < 0 ? -1 : 0, true);
+ if (0 <= value && value < 256)
+ UINT_CACHE[value] = obj;
+ return obj;
+ }
+ };
+
+ /**
+ * Returns a Long representing the given value, provided that it is a finite number. Otherwise, zero is returned.
+ * @param {number} value The number in question
+ * @param {boolean=} unsigned Whether unsigned or not, defaults to `false` for signed
+ * @returns {!Long} The corresponding Long value
+ * @expose
+ */
+ Long.fromNumber = function(value, unsigned) {
+ unsigned = !!unsigned;
+ if (isNaN(value) || !isFinite(value))
+ return Long.ZERO;
+ if (!unsigned && value <= -TWO_PWR_63_DBL)
+ return Long.MIN_VALUE;
+ if (!unsigned && value + 1 >= TWO_PWR_63_DBL)
+ return Long.MAX_VALUE;
+ if (unsigned && value >= TWO_PWR_64_DBL)
+ return Long.MAX_UNSIGNED_VALUE;
+ if (value < 0)
+ return Long.fromNumber(-value, unsigned).negate();
+ return new Long((value % TWO_PWR_32_DBL) | 0, (value / TWO_PWR_32_DBL) | 0, unsigned);
+ };
+
+ /**
+ * Returns a Long representing the 64 bit integer that comes by concatenating the given low and high bits. Each is
+ * assumed to use 32 bits.
+ * @param {number} lowBits The low 32 bits
+ * @param {number} highBits The high 32 bits
+ * @param {boolean=} unsigned Whether unsigned or not, defaults to `false` for signed
+ * @returns {!Long} The corresponding Long value
+ * @expose
+ */
+ Long.fromBits = function(lowBits, highBits, unsigned) {
+ return new Long(lowBits, highBits, unsigned);
+ };
+
+ /**
+ * Returns a Long representation of the given string, written using the specified radix.
+ * @param {string} str The textual representation of the Long
+ * @param {(boolean|number)=} unsigned Whether unsigned or not, defaults to `false` for signed
+ * @param {number=} radix The radix in which the text is written (2-36), defaults to 10
+ * @returns {!Long} The corresponding Long value
+ * @expose
+ */
+ Long.fromString = function(str, unsigned, radix) {
+ if (str.length === 0)
+ throw Error('number format error: empty string');
+ if (str === "NaN" || str === "Infinity" || str === "+Infinity" || str === "-Infinity")
+ return Long.ZERO;
+ if (typeof unsigned === 'number') // For goog.math.long compatibility
+ radix = unsigned,
+ unsigned = false;
+ radix = radix || 10;
+ if (radix < 2 || 36 < radix)
+ throw Error('radix out of range: ' + radix);
+
+ var p;
+ if ((p = str.indexOf('-')) > 0)
+ throw Error('number format error: interior "-" character: ' + str);
+ else if (p === 0)
+ return Long.fromString(str.substring(1), unsigned, radix).negate();
+
+ // Do several (8) digits each time through the loop, so as to
+ // minimize the calls to the very expensive emulated div.
+ var radixToPower = Long.fromNumber(Math.pow(radix, 8));
+
+ var result = Long.ZERO;
+ for (var i = 0; i < str.length; i += 8) {
+ var size = Math.min(8, str.length - i);
+ var value = parseInt(str.substring(i, i + size), radix);
+ if (size < 8) {
+ var power = Long.fromNumber(Math.pow(radix, size));
+ result = result.multiply(power).add(Long.fromNumber(value));
+ } else {
+ result = result.multiply(radixToPower);
+ result = result.add(Long.fromNumber(value));
+ }
+ }
+ result.unsigned = unsigned;
+ return result;
+ };
+
+ /**
+ * Converts the specified value to a Long.
+ * @param {!Long|number|string|!{low: number, high: number, unsigned: boolean}} val Value
+ * @returns {!Long}
+ * @expose
+ */
+ Long.fromValue = function(val) {
+ if (typeof val === 'number')
+ return Long.fromNumber(val);
+ if (typeof val === 'string')
+ return Long.fromString(val);
+ if (Long.isLong(val))
+ return val;
+ // Throws for not an object (undefined, null):
+ return new Long(val.low, val.high, val.unsigned);
+ };
+
+ // NOTE: the compiler should inline these constant values below and then remove these variables, so there should be
+ // no runtime penalty for these.
+
+ /**
+ * @type {number}
+ * @const
+ * @inner
+ */
+ var TWO_PWR_16_DBL = 1 << 16;
+
+ /**
+ * @type {number}
+ * @const
+ * @inner
+ */
+ var TWO_PWR_24_DBL = 1 << 24;
+
+ /**
+ * @type {number}
+ * @const
+ * @inner
+ */
+ var TWO_PWR_32_DBL = TWO_PWR_16_DBL * TWO_PWR_16_DBL;
+
+ /**
+ * @type {number}
+ * @const
+ * @inner
+ */
+ var TWO_PWR_64_DBL = TWO_PWR_32_DBL * TWO_PWR_32_DBL;
+
+ /**
+ * @type {number}
+ * @const
+ * @inner
+ */
+ var TWO_PWR_63_DBL = TWO_PWR_64_DBL / 2;
+
+ /**
+ * @type {!Long}
+ * @const
+ * @inner
+ */
+ var TWO_PWR_24 = Long.fromInt(TWO_PWR_24_DBL);
+
+ /**
+ * Signed zero.
+ * @type {!Long}
+ * @expose
+ */
+ Long.ZERO = Long.fromInt(0);
+
+ /**
+ * Unsigned zero.
+ * @type {!Long}
+ * @expose
+ */
+ Long.UZERO = Long.fromInt(0, true);
+
+ /**
+ * Signed one.
+ * @type {!Long}
+ * @expose
+ */
+ Long.ONE = Long.fromInt(1);
+
+ /**
+ * Unsigned one.
+ * @type {!Long}
+ * @expose
+ */
+ Long.UONE = Long.fromInt(1, true);
+
+ /**
+ * Signed negative one.
+ * @type {!Long}
+ * @expose
+ */
+ Long.NEG_ONE = Long.fromInt(-1);
+
+ /**
+ * Maximum signed value.
+ * @type {!Long}
+ * @expose
+ */
+ Long.MAX_VALUE = Long.fromBits(0xFFFFFFFF|0, 0x7FFFFFFF|0, false);
+
+ /**
+ * Maximum unsigned value.
+ * @type {!Long}
+ * @expose
+ */
+ Long.MAX_UNSIGNED_VALUE = Long.fromBits(0xFFFFFFFF|0, 0xFFFFFFFF|0, true);
+
+ /**
+ * Minimum signed value.
+ * @type {!Long}
+ * @expose
+ */
+ Long.MIN_VALUE = Long.fromBits(0, 0x80000000|0, false);
+
+ /**
+ * Converts the Long to a 32 bit integer, assuming it is a 32 bit integer.
+ * @returns {number}
+ * @expose
+ */
+ Long.prototype.toInt = function() {
+ return this.unsigned ? this.low >>> 0 : this.low;
+ };
+
+ /**
+ * Converts the Long to a the nearest floating-point representation of this value (double, 53 bit mantissa).
+ * @returns {number}
+ * @expose
+ */
+ Long.prototype.toNumber = function() {
+ if (this.unsigned) {
+ return ((this.high >>> 0) * TWO_PWR_32_DBL) + (this.low >>> 0);
+ }
+ return this.high * TWO_PWR_32_DBL + (this.low >>> 0);
+ };
+
+ /**
+ * Converts the Long to a string written in the specified radix.
+ * @param {number=} radix Radix (2-36), defaults to 10
+ * @returns {string}
+ * @override
+ * @throws {RangeError} If `radix` is out of range
+ * @expose
+ */
+ Long.prototype.toString = function(radix) {
+ radix = radix || 10;
+ if (radix < 2 || 36 < radix)
+ throw RangeError('radix out of range: ' + radix);
+ if (this.isZero())
+ return '0';
+ var rem;
+ if (this.isNegative()) { // Unsigned Longs are never negative
+ if (this.equals(Long.MIN_VALUE)) {
+ // We need to change the Long value before it can be negated, so we remove
+ // the bottom-most digit in this base and then recurse to do the rest.
+ var radixLong = Long.fromNumber(radix);
+ var div = this.div(radixLong);
+ rem = div.multiply(radixLong).subtract(this);
+ return div.toString(radix) + rem.toInt().toString(radix);
+ } else
+ return '-' + this.negate().toString(radix);
+ }
+
+ // Do several (6) digits each time through the loop, so as to
+ // minimize the calls to the very expensive emulated div.
+ var radixToPower = Long.fromNumber(Math.pow(radix, 6), this.unsigned);
+ rem = this;
+ var result = '';
+ while (true) {
+ var remDiv = rem.div(radixToPower),
+ intval = rem.subtract(remDiv.multiply(radixToPower)).toInt() >>> 0,
+ digits = intval.toString(radix);
+ rem = remDiv;
+ if (rem.isZero())
+ return digits + result;
+ else {
+ while (digits.length < 6)
+ digits = '0' + digits;
+ result = '' + digits + result;
+ }
+ }
+ };
+
+ /**
+ * Gets the high 32 bits as a signed integer.
+ * @returns {number} Signed high bits
+ * @expose
+ */
+ Long.prototype.getHighBits = function() {
+ return this.high;
+ };
+
+ /**
+ * Gets the high 32 bits as an unsigned integer.
+ * @returns {number} Unsigned high bits
+ * @expose
+ */
+ Long.prototype.getHighBitsUnsigned = function() {
+ return this.high >>> 0;
+ };
+
+ /**
+ * Gets the low 32 bits as a signed integer.
+ * @returns {number} Signed low bits
+ * @expose
+ */
+ Long.prototype.getLowBits = function() {
+ return this.low;
+ };
+
+ /**
+ * Gets the low 32 bits as an unsigned integer.
+ * @returns {number} Unsigned low bits
+ * @expose
+ */
+ Long.prototype.getLowBitsUnsigned = function() {
+ return this.low >>> 0;
+ };
+
+ /**
+ * Gets the number of bits needed to represent the absolute value of this Long.
+ * @returns {number}
+ * @expose
+ */
+ Long.prototype.getNumBitsAbs = function() {
+ if (this.isNegative()) // Unsigned Longs are never negative
+ return this.equals(Long.MIN_VALUE) ? 64 : this.negate().getNumBitsAbs();
+ var val = this.high != 0 ? this.high : this.low;
+ for (var bit = 31; bit > 0; bit--)
+ if ((val & (1 << bit)) != 0)
+ break;
+ return this.high != 0 ? bit + 33 : bit + 1;
+ };
+
+ /**
+ * Tests if this Long's value equals zero.
+ * @returns {boolean}
+ * @expose
+ */
+ Long.prototype.isZero = function() {
+ return this.high === 0 && this.low === 0;
+ };
+
+ /**
+ * Tests if this Long's value is negative.
+ * @returns {boolean}
+ * @expose
+ */
+ Long.prototype.isNegative = function() {
+ return !this.unsigned && this.high < 0;
+ };
+
+ /**
+ * Tests if this Long's value is positive.
+ * @returns {boolean}
+ * @expose
+ */
+ Long.prototype.isPositive = function() {
+ return this.unsigned || this.high >= 0;
+ };
+
+ /**
+ * Tests if this Long's value is odd.
+ * @returns {boolean}
+ * @expose
+ */
+ Long.prototype.isOdd = function() {
+ return (this.low & 1) === 1;
+ };
+
+ /**
+ * Tests if this Long's value is even.
+ * @returns {boolean}
+ * @expose
+ */
+ Long.prototype.isEven = function() {
+ return (this.low & 1) === 0;
+ };
+
+ /**
+ * Tests if this Long's value equals the specified's.
+ * @param {!Long|number|string} other Other value
+ * @returns {boolean}
+ * @expose
+ */
+ Long.prototype.equals = function(other) {
+ if (!Long.isLong(other))
+ other = Long.fromValue(other);
+ if (this.unsigned !== other.unsigned && (this.high >>> 31) === 1 && (other.high >>> 31) === 1)
+ return false;
+ return this.high === other.high && this.low === other.low;
+ };
+
+ /**
+ * Tests if this Long's value differs from the specified's.
+ * @param {!Long|number|string} other Other value
+ * @returns {boolean}
+ * @expose
+ */
+ Long.prototype.notEquals = function(other) {
+ if (!Long.isLong(other))
+ other = Long.fromValue(other);
+ return !this.equals(other);
+ };
+
+ /**
+ * Tests if this Long's value is less than the specified's.
+ * @param {!Long|number|string} other Other value
+ * @returns {boolean}
+ * @expose
+ */
+ Long.prototype.lessThan = function(other) {
+ if (!Long.isLong(other))
+ other = Long.fromValue(other);
+ return this.compare(other) < 0;
+ };
+
+ /**
+ * Tests if this Long's value is less than or equal the specified's.
+ * @param {!Long|number|string} other Other value
+ * @returns {boolean}
+ * @expose
+ */
+ Long.prototype.lessThanOrEqual = function(other) {
+ if (!Long.isLong(other))
+ other = Long.fromValue(other);
+ return this.compare(other) <= 0;
+ };
+
+ /**
+ * Tests if this Long's value is greater than the specified's.
+ * @param {!Long|number|string} other Other value
+ * @returns {boolean}
+ * @expose
+ */
+ Long.prototype.greaterThan = function(other) {
+ if (!Long.isLong(other))
+ other = Long.fromValue(other);
+ return this.compare(other) > 0;
+ };
+
+ /**
+ * Tests if this Long's value is greater than or equal the specified's.
+ * @param {!Long|number|string} other Other value
+ * @returns {boolean}
+ * @expose
+ */
+ Long.prototype.greaterThanOrEqual = function(other) {
+ return this.compare(other) >= 0;
+ };
+
+ /**
+ * Compares this Long's value with the specified's.
+ * @param {!Long|number|string} other Other value
+ * @returns {number} 0 if they are the same, 1 if the this is greater and -1
+ * if the given one is greater
+ * @expose
+ */
+ Long.prototype.compare = function(other) {
+ if (this.equals(other))
+ return 0;
+ var thisNeg = this.isNegative(),
+ otherNeg = other.isNegative();
+ if (thisNeg && !otherNeg)
+ return -1;
+ if (!thisNeg && otherNeg)
+ return 1;
+ // At this point the sign bits are the same
+ if (!this.unsigned)
+ return this.subtract(other).isNegative() ? -1 : 1;
+ // Both are positive if at least one is unsigned
+ return (other.high >>> 0) > (this.high >>> 0) || (other.high === this.high && (other.low >>> 0) > (this.low >>> 0)) ? -1 : 1;
+ };
+
+ /**
+ * Negates this Long's value.
+ * @returns {!Long} Negated Long
+ * @expose
+ */
+ Long.prototype.negate = function() {
+ if (!this.unsigned && this.equals(Long.MIN_VALUE))
+ return Long.MIN_VALUE;
+ return this.not().add(Long.ONE);
+ };
+
+ /**
+ * Returns the sum of this and the specified Long.
+ * @param {!Long|number|string} addend Addend
+ * @returns {!Long} Sum
+ * @expose
+ */
+ Long.prototype.add = function(addend) {
+ if (!Long.isLong(addend))
+ addend = Long.fromValue(addend);
+
+ // Divide each number into 4 chunks of 16 bits, and then sum the chunks.
+
+ var a48 = this.high >>> 16;
+ var a32 = this.high & 0xFFFF;
+ var a16 = this.low >>> 16;
+ var a00 = this.low & 0xFFFF;
+
+ var b48 = addend.high >>> 16;
+ var b32 = addend.high & 0xFFFF;
+ var b16 = addend.low >>> 16;
+ var b00 = addend.low & 0xFFFF;
+
+ var c48 = 0, c32 = 0, c16 = 0, c00 = 0;
+ c00 += a00 + b00;
+ c16 += c00 >>> 16;
+ c00 &= 0xFFFF;
+ c16 += a16 + b16;
+ c32 += c16 >>> 16;
+ c16 &= 0xFFFF;
+ c32 += a32 + b32;
+ c48 += c32 >>> 16;
+ c32 &= 0xFFFF;
+ c48 += a48 + b48;
+ c48 &= 0xFFFF;
+ return Long.fromBits((c16 << 16) | c00, (c48 << 16) | c32, this.unsigned);
+ };
+
+ /**
+ * Returns the difference of this and the specified Long.
+ * @param {!Long|number|string} subtrahend Subtrahend
+ * @returns {!Long} Difference
+ * @expose
+ */
+ Long.prototype.subtract = function(subtrahend) {
+ if (!Long.isLong(subtrahend))
+ subtrahend = Long.fromValue(subtrahend);
+ return this.add(subtrahend.negate());
+ };
+
+ /**
+ * Returns the product of this and the specified Long.
+ * @param {!Long|number|string} multiplier Multiplier
+ * @returns {!Long} Product
+ * @expose
+ */
+ Long.prototype.multiply = function(multiplier) {
+ if (this.isZero())
+ return Long.ZERO;
+ if (!Long.isLong(multiplier))
+ multiplier = Long.fromValue(multiplier);
+ if (multiplier.isZero())
+ return Long.ZERO;
+ if (this.equals(Long.MIN_VALUE))
+ return multiplier.isOdd() ? Long.MIN_VALUE : Long.ZERO;
+ if (multiplier.equals(Long.MIN_VALUE))
+ return this.isOdd() ? Long.MIN_VALUE : Long.ZERO;
+
+ if (this.isNegative()) {
+ if (multiplier.isNegative())
+ return this.negate().multiply(multiplier.negate());
+ else
+ return this.negate().multiply(multiplier).negate();
+ } else if (multiplier.isNegative())
+ return this.multiply(multiplier.negate()).negate();
+
+ // If both longs are small, use float multiplication
+ if (this.lessThan(TWO_PWR_24) && multiplier.lessThan(TWO_PWR_24))
+ return Long.fromNumber(this.toNumber() * multiplier.toNumber(), this.unsigned);
+
+ // Divide each long into 4 chunks of 16 bits, and then add up 4x4 products.
+ // We can skip products that would overflow.
+
+ var a48 = this.high >>> 16;
+ var a32 = this.high & 0xFFFF;
+ var a16 = this.low >>> 16;
+ var a00 = this.low & 0xFFFF;
+
+ var b48 = multiplier.high >>> 16;
+ var b32 = multiplier.high & 0xFFFF;
+ var b16 = multiplier.low >>> 16;
+ var b00 = multiplier.low & 0xFFFF;
+
+ var c48 = 0, c32 = 0, c16 = 0, c00 = 0;
+ c00 += a00 * b00;
+ c16 += c00 >>> 16;
+ c00 &= 0xFFFF;
+ c16 += a16 * b00;
+ c32 += c16 >>> 16;
+ c16 &= 0xFFFF;
+ c16 += a00 * b16;
+ c32 += c16 >>> 16;
+ c16 &= 0xFFFF;
+ c32 += a32 * b00;
+ c48 += c32 >>> 16;
+ c32 &= 0xFFFF;
+ c32 += a16 * b16;
+ c48 += c32 >>> 16;
+ c32 &= 0xFFFF;
+ c32 += a00 * b32;
+ c48 += c32 >>> 16;
+ c32 &= 0xFFFF;
+ c48 += a48 * b00 + a32 * b16 + a16 * b32 + a00 * b48;
+ c48 &= 0xFFFF;
+ return Long.fromBits((c16 << 16) | c00, (c48 << 16) | c32, this.unsigned);
+ };
+
+ /**
+ * Returns this Long divided by the specified.
+ * @param {!Long|number|string} divisor Divisor
+ * @returns {!Long} Quotient
+ * @expose
+ */
+ Long.prototype.div = function(divisor) {
+ if (!Long.isLong(divisor))
+ divisor = Long.fromValue(divisor);
+ if (divisor.isZero())
+ throw(new Error('division by zero'));
+ if (this.isZero())
+ return this.unsigned ? Long.UZERO : Long.ZERO;
+ var approx, rem, res;
+ if (this.equals(Long.MIN_VALUE)) {
+ if (divisor.equals(Long.ONE) || divisor.equals(Long.NEG_ONE))
+ return Long.MIN_VALUE; // recall that -MIN_VALUE == MIN_VALUE
+ else if (divisor.equals(Long.MIN_VALUE))
+ return Long.ONE;
+ else {
+ // At this point, we have |other| >= 2, so |this/other| < |MIN_VALUE|.
+ var halfThis = this.shiftRight(1);
+ approx = halfThis.div(divisor).shiftLeft(1);
+ if (approx.equals(Long.ZERO)) {
+ return divisor.isNegative() ? Long.ONE : Long.NEG_ONE;
+ } else {
+ rem = this.subtract(divisor.multiply(approx));
+ res = approx.add(rem.div(divisor));
+ return res;
+ }
+ }
+ } else if (divisor.equals(Long.MIN_VALUE))
+ return this.unsigned ? Long.UZERO : Long.ZERO;
+ if (this.isNegative()) {
+ if (divisor.isNegative())
+ return this.negate().div(divisor.negate());
+ return this.negate().div(divisor).negate();
+ } else if (divisor.isNegative())
+ return this.div(divisor.negate()).negate();
+
+ // Repeat the following until the remainder is less than other: find a
+ // floating-point that approximates remainder / other *from below*, add this
+ // into the result, and subtract it from the remainder. It is critical that
+ // the approximate value is less than or equal to the real value so that the
+ // remainder never becomes negative.
+ res = Long.ZERO;
+ rem = this;
+ while (rem.greaterThanOrEqual(divisor)) {
+ // Approximate the result of division. This may be a little greater or
+ // smaller than the actual value.
+ approx = Math.max(1, Math.floor(rem.toNumber() / divisor.toNumber()));
+
+ // We will tweak the approximate result by changing it in the 48-th digit or
+ // the smallest non-fractional digit, whichever is larger.
+ var log2 = Math.ceil(Math.log(approx) / Math.LN2),
+ delta = (log2 <= 48) ? 1 : Math.pow(2, log2 - 48),
+
+ // Decrease the approximation until it is smaller than the remainder. Note
+ // that if it is too large, the product overflows and is negative.
+ approxRes = Long.fromNumber(approx),
+ approxRem = approxRes.multiply(divisor);
+ while (approxRem.isNegative() || approxRem.greaterThan(rem)) {
+ approx -= delta;
+ approxRes = Long.fromNumber(approx, this.unsigned);
+ approxRem = approxRes.multiply(divisor);
+ }
+
+ // We know the answer can't be zero... and actually, zero would cause
+ // infinite recursion since we would make no progress.
+ if (approxRes.isZero())
+ approxRes = Long.ONE;
+
+ res = res.add(approxRes);
+ rem = rem.subtract(approxRem);
+ }
+ return res;
+ };
+
+ /**
+ * Returns this Long modulo the specified.
+ * @param {!Long|number|string} divisor Divisor
+ * @returns {!Long} Remainder
+ * @expose
+ */
+ Long.prototype.modulo = function(divisor) {
+ if (!Long.isLong(divisor))
+ divisor = Long.fromValue(divisor);
+ return this.subtract(this.div(divisor).multiply(divisor));
+ };
+
+ /**
+ * Returns the bitwise NOT of this Long.
+ * @returns {!Long}
+ * @expose
+ */
+ Long.prototype.not = function() {
+ return Long.fromBits(~this.low, ~this.high, this.unsigned);
+ };
+
+ /**
+ * Returns the bitwise AND of this Long and the specified.
+ * @param {!Long|number|string} other Other Long
+ * @returns {!Long}
+ * @expose
+ */
+ Long.prototype.and = function(other) {
+ if (!Long.isLong(other))
+ other = Long.fromValue(other);
+ return Long.fromBits(this.low & other.low, this.high & other.high, this.unsigned);
+ };
+
+ /**
+ * Returns the bitwise OR of this Long and the specified.
+ * @param {!Long|number|string} other Other Long
+ * @returns {!Long}
+ * @expose
+ */
+ Long.prototype.or = function(other) {
+ if (!Long.isLong(other))
+ other = Long.fromValue(other);
+ return Long.fromBits(this.low | other.low, this.high | other.high, this.unsigned);
+ };
+
+ /**
+ * Returns the bitwise XOR of this Long and the given one.
+ * @param {!Long|number|string} other Other Long
+ * @returns {!Long}
+ * @expose
+ */
+ Long.prototype.xor = function(other) {
+ if (!Long.isLong(other))
+ other = Long.fromValue(other);
+ return Long.fromBits(this.low ^ other.low, this.high ^ other.high, this.unsigned);
+ };
+
+ /**
+ * Returns this Long with bits shifted to the left by the given amount.
+ * @param {number|!Long} numBits Number of bits
+ * @returns {!Long} Shifted Long
+ * @expose
+ */
+ Long.prototype.shiftLeft = function(numBits) {
+ if (Long.isLong(numBits))
+ numBits = numBits.toInt();
+ if ((numBits &= 63) === 0)
+ return this;
+ else if (numBits < 32)
+ return Long.fromBits(this.low << numBits, (this.high << numBits) | (this.low >>> (32 - numBits)), this.unsigned);
+ else
+ return Long.fromBits(0, this.low << (numBits - 32), this.unsigned);
+ };
+
+ /**
+ * Returns this Long with bits arithmetically shifted to the right by the given amount.
+ * @param {number|!Long} numBits Number of bits
+ * @returns {!Long} Shifted Long
+ * @expose
+ */
+ Long.prototype.shiftRight = function(numBits) {
+ if (Long.isLong(numBits))
+ numBits = numBits.toInt();
+ if ((numBits &= 63) === 0)
+ return this;
+ else if (numBits < 32)
+ return Long.fromBits((this.low >>> numBits) | (this.high << (32 - numBits)), this.high >> numBits, this.unsigned);
+ else
+ return Long.fromBits(this.high >> (numBits - 32), this.high >= 0 ? 0 : -1, this.unsigned);
+ };
+
+ /**
+ * Returns this Long with bits logically shifted to the right by the given amount.
+ * @param {number|!Long} numBits Number of bits
+ * @returns {!Long} Shifted Long
+ * @expose
+ */
+ Long.prototype.shiftRightUnsigned = function(numBits) {
+ if (Long.isLong(numBits))
+ numBits = numBits.toInt();
+ numBits &= 63;
+ if (numBits === 0)
+ return this;
+ else {
+ var high = this.high;
+ if (numBits < 32) {
+ var low = this.low;
+ return Long.fromBits((low >>> numBits) | (high << (32 - numBits)), high >>> numBits, this.unsigned);
+ } else if (numBits === 32)
+ return Long.fromBits(high, 0, this.unsigned);
+ else
+ return Long.fromBits(high >>> (numBits - 32), 0, this.unsigned);
+ }
+ };
+
+ /**
+ * Converts this Long to signed.
+ * @returns {!Long} Signed long
+ * @expose
+ */
+ Long.prototype.toSigned = function() {
+ if (!this.unsigned)
+ return this;
+ return new Long(this.low, this.high, false);
+ };
+
+ /**
+ * Converts this Long to unsigned.
+ * @returns {!Long} Unsigned long
+ * @expose
+ */
+ Long.prototype.toUnsigned = function() {
+ if (this.unsigned)
+ return this;
+ return new Long(this.low, this.high, true);
+ };
+
+ /* CommonJS */ if (typeof require === 'function' && typeof module === 'object' && module && typeof exports === 'object' && exports)
+ module["exports"] = Long;
+ /* AMD */ else if (typeof define === 'function' && define["amd"])
+ define(function() { return Long; });
+ /* Global */ else
+ (global["dcodeIO"] = global["dcodeIO"] || {})["Long"] = Long;
+
+})(this);
+
+/*
+ Copyright 2013-2014 Daniel Wirtz
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+/**
+ * @license ByteBuffer.js (c) 2013-2014 Daniel Wirtz
+ * This version of ByteBuffer.js uses an ArrayBuffer (AB) as its backing buffer and is compatible with modern browsers.
+ * Released under the Apache License, Version 2.0
+ * see: https://github.com/dcodeIO/ByteBuffer.js for details
+ */ //
+(function(global) {
+ "use strict";
+
+ /**
+ * @param {function(new: Long, number, number, boolean=)=} Long
+ * @returns {function(new: ByteBuffer, number=, boolean=, boolean=)}}
+ * @inner
+ */
+ function loadByteBuffer(Long) {
+
+ /**
+ * Constructs a new ByteBuffer.
+ * @class The swiss army knife for binary data in JavaScript.
+ * @exports ByteBuffer
+ * @constructor
+ * @param {number=} capacity Initial capacity. Defaults to {@link ByteBuffer.DEFAULT_CAPACITY}.
+ * @param {boolean=} littleEndian Whether to use little or big endian byte order. Defaults to
+ * {@link ByteBuffer.DEFAULT_ENDIAN}.
+ * @param {boolean=} noAssert Whether to skip assertions of offsets and values. Defaults to
+ * {@link ByteBuffer.DEFAULT_NOASSERT}.
+ * @expose
+ */
+ var ByteBuffer = function(capacity, littleEndian, noAssert) {
+ if (typeof capacity === 'undefined') capacity = ByteBuffer.DEFAULT_CAPACITY;
+ if (typeof littleEndian === 'undefined') littleEndian = ByteBuffer.DEFAULT_ENDIAN;
+ if (typeof noAssert === 'undefined') noAssert = ByteBuffer.DEFAULT_NOASSERT;
+ if (!noAssert) {
+ capacity = capacity | 0;
+ if (capacity < 0)
+ throw RangeError("Illegal capacity");
+ littleEndian = !!littleEndian;
+ noAssert = !!noAssert;
+ }
+
+ /**
+ * Backing buffer.
+ * @type {!ArrayBuffer}
+ * @expose
+ */
+ this.buffer = capacity === 0 ? EMPTY_BUFFER : new ArrayBuffer(capacity);
+
+ /**
+ * Data view to manipulate the backing buffer. Becomes `null` if the backing buffer has a capacity of `0`.
+ * @type {?DataView}
+ * @expose
+ */
+ this.view = capacity === 0 ? null : new DataView(this.buffer);
+
+ /**
+ * Absolute read/write offset.
+ * @type {number}
+ * @expose
+ * @see ByteBuffer#flip
+ * @see ByteBuffer#clear
+ */
+ this.offset = 0;
+
+ /**
+ * Marked offset.
+ * @type {number}
+ * @expose
+ * @see ByteBuffer#mark
+ * @see ByteBuffer#reset
+ */
+ this.markedOffset = -1;
+
+ /**
+ * Absolute limit of the contained data. Set to the backing buffer's capacity upon allocation.
+ * @type {number}
+ * @expose
+ * @see ByteBuffer#flip
+ * @see ByteBuffer#clear
+ */
+ this.limit = capacity;
+
+ /**
+ * Whether to use little endian byte order, defaults to `false` for big endian.
+ * @type {boolean}
+ * @expose
+ */
+ this.littleEndian = typeof littleEndian !== 'undefined' ? !!littleEndian : false;
+
+ /**
+ * Whether to skip assertions of offsets and values, defaults to `false`.
+ * @type {boolean}
+ * @expose
+ */
+ this.noAssert = !!noAssert;
+ };
+
+ /**
+ * ByteBuffer version.
+ * @type {string}
+ * @const
+ * @expose
+ */
+ ByteBuffer.VERSION = "3.5.4";
+
+ /**
+ * Little endian constant that can be used instead of its boolean value. Evaluates to `true`.
+ * @type {boolean}
+ * @const
+ * @expose
+ */
+ ByteBuffer.LITTLE_ENDIAN = true;
+
+ /**
+ * Big endian constant that can be used instead of its boolean value. Evaluates to `false`.
+ * @type {boolean}
+ * @const
+ * @expose
+ */
+ ByteBuffer.BIG_ENDIAN = false;
+
+ /**
+ * Default initial capacity of `16`.
+ * @type {number}
+ * @expose
+ */
+ ByteBuffer.DEFAULT_CAPACITY = 16;
+
+ /**
+ * Default endianess of `false` for big endian.
+ * @type {boolean}
+ * @expose
+ */
+ ByteBuffer.DEFAULT_ENDIAN = ByteBuffer.BIG_ENDIAN;
+
+ /**
+ * Default no assertions flag of `false`.
+ * @type {boolean}
+ * @expose
+ */
+ ByteBuffer.DEFAULT_NOASSERT = false;
+
+ /**
+ * A `Long` class for representing a 64-bit two's-complement integer value. May be `null` if Long.js has not been loaded
+ * and int64 support is not available.
+ * @type {?Long}
+ * @const
+ * @see https://github.com/dcodeIO/Long.js
+ * @expose
+ */
+ ByteBuffer.Long = Long || null;
+
+ /**
+ * @alias ByteBuffer.prototype
+ * @inner
+ */
+ var ByteBufferPrototype = ByteBuffer.prototype;
+
+ // helpers
+
+ /**
+ * @type {!ArrayBuffer}
+ * @inner
+ */
+ var EMPTY_BUFFER = new ArrayBuffer(0);
+
+ /**
+ * String.fromCharCode reference for compile-time renaming.
+ * @type {function(...number):string}
+ * @inner
+ */
+ var stringFromCharCode = String.fromCharCode;
+
+ /**
+ * Creates a source function for a string.
+ * @param {string} s String to read from
+ * @returns {function():number|null} Source function returning the next char code respectively `null` if there are
+ * no more characters left.
+ * @throws {TypeError} If the argument is invalid
+ * @inner
+ */
+ function stringSource(s) {
+ var i=0; return function() {
+ return i < s.length ? s.charCodeAt(i++) : null;
+ };
+ }
+
+ /**
+ * Creates a destination function for a string.
+ * @returns {function(number=):undefined|string} Destination function successively called with the next char code.
+ * Returns the final string when called without arguments.
+ * @inner
+ */
+ function stringDestination() {
+ var cs = [], ps = []; return function() {
+ if (arguments.length === 0)
+ return ps.join('')+stringFromCharCode.apply(String, cs);
+ if (cs.length + arguments.length > 1024)
+ ps.push(stringFromCharCode.apply(String, cs)),
+ cs.length = 0;
+ Array.prototype.push.apply(cs, arguments);
+ };
+ }
+
+ /**
+ * Allocates a new ByteBuffer backed by a buffer of the specified capacity.
+ * @param {number=} capacity Initial capacity. Defaults to {@link ByteBuffer.DEFAULT_CAPACITY}.
+ * @param {boolean=} littleEndian Whether to use little or big endian byte order. Defaults to
+ * {@link ByteBuffer.DEFAULT_ENDIAN}.
+ * @param {boolean=} noAssert Whether to skip assertions of offsets and values. Defaults to
+ * {@link ByteBuffer.DEFAULT_NOASSERT}.
+ * @returns {!ByteBuffer}
+ * @expose
+ */
+ ByteBuffer.allocate = function(capacity, littleEndian, noAssert) {
+ return new ByteBuffer(capacity, littleEndian, noAssert);
+ };
+
+ /**
+ * Concatenates multiple ByteBuffers into one.
+ * @param {!Array.} buffers Buffers to concatenate
+ * @param {(string|boolean)=} encoding String encoding if `buffers` contains a string ("base64", "hex", "binary",
+ * defaults to "utf8")
+ * @param {boolean=} littleEndian Whether to use little or big endian byte order for the resulting ByteBuffer. Defaults
+ * to {@link ByteBuffer.DEFAULT_ENDIAN}.
+ * @param {boolean=} noAssert Whether to skip assertions of offsets and values for the resulting ByteBuffer. Defaults to
+ * {@link ByteBuffer.DEFAULT_NOASSERT}.
+ * @returns {!ByteBuffer} Concatenated ByteBuffer
+ * @expose
+ */
+ ByteBuffer.concat = function(buffers, encoding, littleEndian, noAssert) {
+ if (typeof encoding === 'boolean' || typeof encoding !== 'string') {
+ noAssert = littleEndian;
+ littleEndian = encoding;
+ encoding = undefined;
+ }
+ var capacity = 0;
+ for (var i=0, k=buffers.length, length; i 0) capacity += length;
+ }
+ if (capacity === 0)
+ return new ByteBuffer(0, littleEndian, noAssert);
+ var bb = new ByteBuffer(capacity, littleEndian, noAssert),
+ bi;
+ var view = new Uint8Array(bb.buffer);
+ i=0; while (i} buffer Anything that can be wrapped
+ * @param {(string|boolean)=} encoding String encoding if `buffer` is a string ("base64", "hex", "binary", defaults to
+ * "utf8")
+ * @param {boolean=} littleEndian Whether to use little or big endian byte order. Defaults to
+ * {@link ByteBuffer.DEFAULT_ENDIAN}.
+ * @param {boolean=} noAssert Whether to skip assertions of offsets and values. Defaults to
+ * {@link ByteBuffer.DEFAULT_NOASSERT}.
+ * @returns {!ByteBuffer} A ByteBuffer wrapping `buffer`
+ * @expose
+ */
+ ByteBuffer.wrap = function(buffer, encoding, littleEndian, noAssert) {
+ if (typeof encoding !== 'string') {
+ noAssert = littleEndian;
+ littleEndian = encoding;
+ encoding = undefined;
+ }
+ if (typeof buffer === 'string') {
+ if (typeof encoding === 'undefined')
+ encoding = "utf8";
+ switch (encoding) {
+ case "base64":
+ return ByteBuffer.fromBase64(buffer, littleEndian);
+ case "hex":
+ return ByteBuffer.fromHex(buffer, littleEndian);
+ case "binary":
+ return ByteBuffer.fromBinary(buffer, littleEndian);
+ case "utf8":
+ return ByteBuffer.fromUTF8(buffer, littleEndian);
+ case "debug":
+ return ByteBuffer.fromDebug(buffer, littleEndian);
+ default:
+ throw Error("Unsupported encoding: "+encoding);
+ }
+ }
+ if (buffer === null || typeof buffer !== 'object')
+ throw TypeError("Illegal buffer");
+ var bb;
+ if (ByteBuffer.isByteBuffer(buffer)) {
+ bb = ByteBufferPrototype.clone.call(buffer);
+ bb.markedOffset = -1;
+ return bb;
+ }
+ if (buffer instanceof Uint8Array) { // Extract ArrayBuffer from Uint8Array
+ bb = new ByteBuffer(0, littleEndian, noAssert);
+ if (buffer.length > 0) { // Avoid references to more than one EMPTY_BUFFER
+ bb.buffer = buffer.buffer;
+ bb.offset = buffer.byteOffset;
+ bb.limit = buffer.byteOffset + buffer.length;
+ bb.view = buffer.length > 0 ? new DataView(buffer.buffer) : null;
+ }
+ } else if (buffer instanceof ArrayBuffer) { // Reuse ArrayBuffer
+ bb = new ByteBuffer(0, littleEndian, noAssert);
+ if (buffer.byteLength > 0) {
+ bb.buffer = buffer;
+ bb.offset = 0;
+ bb.limit = buffer.byteLength;
+ bb.view = buffer.byteLength > 0 ? new DataView(buffer) : null;
+ }
+ } else if (Object.prototype.toString.call(buffer) === "[object Array]") { // Create from octets
+ bb = new ByteBuffer(buffer.length, littleEndian, noAssert);
+ bb.limit = buffer.length;
+ for (i=0; i>>= 0;
+ if (offset < 0 || offset + 0 > this.buffer.byteLength)
+ throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength);
+ }
+ offset += 1;
+ var capacity0 = this.buffer.byteLength;
+ if (offset > capacity0)
+ this.resize((capacity0 *= 2) > offset ? capacity0 : offset);
+ offset -= 1;
+ this.view.setInt8(offset, value);
+ if (relative) this.offset += 1;
+ return this;
+ };
+
+ /**
+ * Writes an 8bit signed integer. This is an alias of {@link ByteBuffer#writeInt8}.
+ * @function
+ * @param {number} value Value to write
+ * @param {number=} offset Offset to write to. Will use and advance {@link ByteBuffer#offset} by `1` if omitted.
+ * @returns {!ByteBuffer} this
+ * @expose
+ */
+ ByteBufferPrototype.writeByte = ByteBufferPrototype.writeInt8;
+
+ /**
+ * Reads an 8bit signed integer.
+ * @param {number=} offset Offset to read from. Will use and advance {@link ByteBuffer#offset} by `1` if omitted.
+ * @returns {number} Value read
+ * @expose
+ */
+ ByteBufferPrototype.readInt8 = function(offset) {
+ var relative = typeof offset === 'undefined';
+ if (relative) offset = this.offset;
+ if (!this.noAssert) {
+ if (typeof offset !== 'number' || offset % 1 !== 0)
+ throw TypeError("Illegal offset: "+offset+" (not an integer)");
+ offset >>>= 0;
+ if (offset < 0 || offset + 1 > this.buffer.byteLength)
+ throw RangeError("Illegal offset: 0 <= "+offset+" (+"+1+") <= "+this.buffer.byteLength);
+ }
+ var value = this.view.getInt8(offset);
+ if (relative) this.offset += 1;
+ return value;
+ };
+
+ /**
+ * Reads an 8bit signed integer. This is an alias of {@link ByteBuffer#readInt8}.
+ * @function
+ * @param {number=} offset Offset to read from. Will use and advance {@link ByteBuffer#offset} by `1` if omitted.
+ * @returns {number} Value read
+ * @expose
+ */
+ ByteBufferPrototype.readByte = ByteBufferPrototype.readInt8;
+
+ /**
+ * Writes an 8bit unsigned integer.
+ * @param {number} value Value to write
+ * @param {number=} offset Offset to write to. Will use and advance {@link ByteBuffer#offset} by `1` if omitted.
+ * @returns {!ByteBuffer} this
+ * @expose
+ */
+ ByteBufferPrototype.writeUint8 = function(value, offset) {
+ var relative = typeof offset === 'undefined';
+ if (relative) offset = this.offset;
+ if (!this.noAssert) {
+ if (typeof value !== 'number' || value % 1 !== 0)
+ throw TypeError("Illegal value: "+value+" (not an integer)");
+ value >>>= 0;
+ if (typeof offset !== 'number' || offset % 1 !== 0)
+ throw TypeError("Illegal offset: "+offset+" (not an integer)");
+ offset >>>= 0;
+ if (offset < 0 || offset + 0 > this.buffer.byteLength)
+ throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength);
+ }
+ offset += 1;
+ var capacity1 = this.buffer.byteLength;
+ if (offset > capacity1)
+ this.resize((capacity1 *= 2) > offset ? capacity1 : offset);
+ offset -= 1;
+ this.view.setUint8(offset, value);
+ if (relative) this.offset += 1;
+ return this;
+ };
+
+ /**
+ * Reads an 8bit unsigned integer.
+ * @param {number=} offset Offset to read from. Will use and advance {@link ByteBuffer#offset} by `1` if omitted.
+ * @returns {number} Value read
+ * @expose
+ */
+ ByteBufferPrototype.readUint8 = function(offset) {
+ var relative = typeof offset === 'undefined';
+ if (relative) offset = this.offset;
+ if (!this.noAssert) {
+ if (typeof offset !== 'number' || offset % 1 !== 0)
+ throw TypeError("Illegal offset: "+offset+" (not an integer)");
+ offset >>>= 0;
+ if (offset < 0 || offset + 1 > this.buffer.byteLength)
+ throw RangeError("Illegal offset: 0 <= "+offset+" (+"+1+") <= "+this.buffer.byteLength);
+ }
+ var value = this.view.getUint8(offset);
+ if (relative) this.offset += 1;
+ return value;
+ };
+
+ // types/ints/int16
+
+ /**
+ * Writes a 16bit signed integer.
+ * @param {number} value Value to write
+ * @param {number=} offset Offset to write to. Will use and advance {@link ByteBuffer#offset} by `2` if omitted.
+ * @throws {TypeError} If `offset` or `value` is not a valid number
+ * @throws {RangeError} If `offset` is out of bounds
+ * @expose
+ */
+ ByteBufferPrototype.writeInt16 = function(value, offset) {
+ var relative = typeof offset === 'undefined';
+ if (relative) offset = this.offset;
+ if (!this.noAssert) {
+ if (typeof value !== 'number' || value % 1 !== 0)
+ throw TypeError("Illegal value: "+value+" (not an integer)");
+ value |= 0;
+ if (typeof offset !== 'number' || offset % 1 !== 0)
+ throw TypeError("Illegal offset: "+offset+" (not an integer)");
+ offset >>>= 0;
+ if (offset < 0 || offset + 0 > this.buffer.byteLength)
+ throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength);
+ }
+ offset += 2;
+ var capacity2 = this.buffer.byteLength;
+ if (offset > capacity2)
+ this.resize((capacity2 *= 2) > offset ? capacity2 : offset);
+ offset -= 2;
+ this.view.setInt16(offset, value, this.littleEndian);
+ if (relative) this.offset += 2;
+ return this;
+ };
+
+ /**
+ * Writes a 16bit signed integer. This is an alias of {@link ByteBuffer#writeInt16}.
+ * @function
+ * @param {number} value Value to write
+ * @param {number=} offset Offset to write to. Will use and advance {@link ByteBuffer#offset} by `2` if omitted.
+ * @throws {TypeError} If `offset` or `value` is not a valid number
+ * @throws {RangeError} If `offset` is out of bounds
+ * @expose
+ */
+ ByteBufferPrototype.writeShort = ByteBufferPrototype.writeInt16;
+
+ /**
+ * Reads a 16bit signed integer.
+ * @param {number=} offset Offset to read from. Will use and advance {@link ByteBuffer#offset} by `2` if omitted.
+ * @returns {number} Value read
+ * @throws {TypeError} If `offset` is not a valid number
+ * @throws {RangeError} If `offset` is out of bounds
+ * @expose
+ */
+ ByteBufferPrototype.readInt16 = function(offset) {
+ var relative = typeof offset === 'undefined';
+ if (relative) offset = this.offset;
+ if (!this.noAssert) {
+ if (typeof offset !== 'number' || offset % 1 !== 0)
+ throw TypeError("Illegal offset: "+offset+" (not an integer)");
+ offset >>>= 0;
+ if (offset < 0 || offset + 2 > this.buffer.byteLength)
+ throw RangeError("Illegal offset: 0 <= "+offset+" (+"+2+") <= "+this.buffer.byteLength);
+ }
+ var value = this.view.getInt16(offset, this.littleEndian);
+ if (relative) this.offset += 2;
+ return value;
+ };
+
+ /**
+ * Reads a 16bit signed integer. This is an alias of {@link ByteBuffer#readInt16}.
+ * @function
+ * @param {number=} offset Offset to read from. Will use and advance {@link ByteBuffer#offset} by `2` if omitted.
+ * @returns {number} Value read
+ * @throws {TypeError} If `offset` is not a valid number
+ * @throws {RangeError} If `offset` is out of bounds
+ * @expose
+ */
+ ByteBufferPrototype.readShort = ByteBufferPrototype.readInt16;
+
+ /**
+ * Writes a 16bit unsigned integer.
+ * @param {number} value Value to write
+ * @param {number=} offset Offset to write to. Will use and advance {@link ByteBuffer#offset} by `2` if omitted.
+ * @throws {TypeError} If `offset` or `value` is not a valid number
+ * @throws {RangeError} If `offset` is out of bounds
+ * @expose
+ */
+ ByteBufferPrototype.writeUint16 = function(value, offset) {
+ var relative = typeof offset === 'undefined';
+ if (relative) offset = this.offset;
+ if (!this.noAssert) {
+ if (typeof value !== 'number' || value % 1 !== 0)
+ throw TypeError("Illegal value: "+value+" (not an integer)");
+ value >>>= 0;
+ if (typeof offset !== 'number' || offset % 1 !== 0)
+ throw TypeError("Illegal offset: "+offset+" (not an integer)");
+ offset >>>= 0;
+ if (offset < 0 || offset + 0 > this.buffer.byteLength)
+ throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength);
+ }
+ offset += 2;
+ var capacity3 = this.buffer.byteLength;
+ if (offset > capacity3)
+ this.resize((capacity3 *= 2) > offset ? capacity3 : offset);
+ offset -= 2;
+ this.view.setUint16(offset, value, this.littleEndian);
+ if (relative) this.offset += 2;
+ return this;
+ };
+
+ /**
+ * Reads a 16bit unsigned integer.
+ * @param {number=} offset Offset to read from. Will use and advance {@link ByteBuffer#offset} by `2` if omitted.
+ * @returns {number} Value read
+ * @throws {TypeError} If `offset` is not a valid number
+ * @throws {RangeError} If `offset` is out of bounds
+ * @expose
+ */
+ ByteBufferPrototype.readUint16 = function(offset) {
+ var relative = typeof offset === 'undefined';
+ if (relative) offset = this.offset;
+ if (!this.noAssert) {
+ if (typeof offset !== 'number' || offset % 1 !== 0)
+ throw TypeError("Illegal offset: "+offset+" (not an integer)");
+ offset >>>= 0;
+ if (offset < 0 || offset + 2 > this.buffer.byteLength)
+ throw RangeError("Illegal offset: 0 <= "+offset+" (+"+2+") <= "+this.buffer.byteLength);
+ }
+ var value = this.view.getUint16(offset, this.littleEndian);
+ if (relative) this.offset += 2;
+ return value;
+ };
+
+ // types/ints/int32
+
+ /**
+ * Writes a 32bit signed integer.
+ * @param {number} value Value to write
+ * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by `4` if omitted.
+ * @expose
+ */
+ ByteBufferPrototype.writeInt32 = function(value, offset) {
+ var relative = typeof offset === 'undefined';
+ if (relative) offset = this.offset;
+ if (!this.noAssert) {
+ if (typeof value !== 'number' || value % 1 !== 0)
+ throw TypeError("Illegal value: "+value+" (not an integer)");
+ value |= 0;
+ if (typeof offset !== 'number' || offset % 1 !== 0)
+ throw TypeError("Illegal offset: "+offset+" (not an integer)");
+ offset >>>= 0;
+ if (offset < 0 || offset + 0 > this.buffer.byteLength)
+ throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength);
+ }
+ offset += 4;
+ var capacity4 = this.buffer.byteLength;
+ if (offset > capacity4)
+ this.resize((capacity4 *= 2) > offset ? capacity4 : offset);
+ offset -= 4;
+ this.view.setInt32(offset, value, this.littleEndian);
+ if (relative) this.offset += 4;
+ return this;
+ };
+
+ /**
+ * Writes a 32bit signed integer. This is an alias of {@link ByteBuffer#writeInt32}.
+ * @param {number} value Value to write
+ * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by `4` if omitted.
+ * @expose
+ */
+ ByteBufferPrototype.writeInt = ByteBufferPrototype.writeInt32;
+
+ /**
+ * Reads a 32bit signed integer.
+ * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by `4` if omitted.
+ * @returns {number} Value read
+ * @expose
+ */
+ ByteBufferPrototype.readInt32 = function(offset) {
+ var relative = typeof offset === 'undefined';
+ if (relative) offset = this.offset;
+ if (!this.noAssert) {
+ if (typeof offset !== 'number' || offset % 1 !== 0)
+ throw TypeError("Illegal offset: "+offset+" (not an integer)");
+ offset >>>= 0;
+ if (offset < 0 || offset + 4 > this.buffer.byteLength)
+ throw RangeError("Illegal offset: 0 <= "+offset+" (+"+4+") <= "+this.buffer.byteLength);
+ }
+ var value = this.view.getInt32(offset, this.littleEndian);
+ if (relative) this.offset += 4;
+ return value;
+ };
+
+ /**
+ * Reads a 32bit signed integer. This is an alias of {@link ByteBuffer#readInt32}.
+ * @param {number=} offset Offset to read from. Will use and advance {@link ByteBuffer#offset} by `4` if omitted.
+ * @returns {number} Value read
+ * @expose
+ */
+ ByteBufferPrototype.readInt = ByteBufferPrototype.readInt32;
+
+ /**
+ * Writes a 32bit unsigned integer.
+ * @param {number} value Value to write
+ * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by `4` if omitted.
+ * @expose
+ */
+ ByteBufferPrototype.writeUint32 = function(value, offset) {
+ var relative = typeof offset === 'undefined';
+ if (relative) offset = this.offset;
+ if (!this.noAssert) {
+ if (typeof value !== 'number' || value % 1 !== 0)
+ throw TypeError("Illegal value: "+value+" (not an integer)");
+ value >>>= 0;
+ if (typeof offset !== 'number' || offset % 1 !== 0)
+ throw TypeError("Illegal offset: "+offset+" (not an integer)");
+ offset >>>= 0;
+ if (offset < 0 || offset + 0 > this.buffer.byteLength)
+ throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength);
+ }
+ offset += 4;
+ var capacity5 = this.buffer.byteLength;
+ if (offset > capacity5)
+ this.resize((capacity5 *= 2) > offset ? capacity5 : offset);
+ offset -= 4;
+ this.view.setUint32(offset, value, this.littleEndian);
+ if (relative) this.offset += 4;
+ return this;
+ };
+
+ /**
+ * Reads a 32bit unsigned integer.
+ * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by `4` if omitted.
+ * @returns {number} Value read
+ * @expose
+ */
+ ByteBufferPrototype.readUint32 = function(offset) {
+ var relative = typeof offset === 'undefined';
+ if (relative) offset = this.offset;
+ if (!this.noAssert) {
+ if (typeof offset !== 'number' || offset % 1 !== 0)
+ throw TypeError("Illegal offset: "+offset+" (not an integer)");
+ offset >>>= 0;
+ if (offset < 0 || offset + 4 > this.buffer.byteLength)
+ throw RangeError("Illegal offset: 0 <= "+offset+" (+"+4+") <= "+this.buffer.byteLength);
+ }
+ var value = this.view.getUint32(offset, this.littleEndian);
+ if (relative) this.offset += 4;
+ return value;
+ };
+
+ // types/ints/int64
+
+ if (Long) {
+
+ /**
+ * Writes a 64bit signed integer.
+ * @param {number|!Long} value Value to write
+ * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by `8` if omitted.
+ * @returns {!ByteBuffer} this
+ * @expose
+ */
+ ByteBufferPrototype.writeInt64 = function(value, offset) {
+ var relative = typeof offset === 'undefined';
+ if (relative) offset = this.offset;
+ if (!this.noAssert) {
+ if (typeof value === 'number')
+ value = Long.fromNumber(value);
+ else if (!(value && value instanceof Long))
+ throw TypeError("Illegal value: "+value+" (not an integer or Long)");
+ if (typeof offset !== 'number' || offset % 1 !== 0)
+ throw TypeError("Illegal offset: "+offset+" (not an integer)");
+ offset >>>= 0;
+ if (offset < 0 || offset + 0 > this.buffer.byteLength)
+ throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength);
+ }
+ if (typeof value === 'number')
+ value = Long.fromNumber(value);
+ offset += 8;
+ var capacity6 = this.buffer.byteLength;
+ if (offset > capacity6)
+ this.resize((capacity6 *= 2) > offset ? capacity6 : offset);
+ offset -= 8;
+ if (this.littleEndian) {
+ this.view.setInt32(offset , value.low , true);
+ this.view.setInt32(offset+4, value.high, true);
+ } else {
+ this.view.setInt32(offset , value.high, false);
+ this.view.setInt32(offset+4, value.low , false);
+ }
+ if (relative) this.offset += 8;
+ return this;
+ };
+
+ /**
+ * Writes a 64bit signed integer. This is an alias of {@link ByteBuffer#writeInt64}.
+ * @param {number|!Long} value Value to write
+ * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by `8` if omitted.
+ * @returns {!ByteBuffer} this
+ * @expose
+ */
+ ByteBufferPrototype.writeLong = ByteBufferPrototype.writeInt64;
+
+ /**
+ * Reads a 64bit signed integer.
+ * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by `8` if omitted.
+ * @returns {!Long}
+ * @expose
+ */
+ ByteBufferPrototype.readInt64 = function(offset) {
+ var relative = typeof offset === 'undefined';
+ if (relative) offset = this.offset;
+ if (!this.noAssert) {
+ if (typeof offset !== 'number' || offset % 1 !== 0)
+ throw TypeError("Illegal offset: "+offset+" (not an integer)");
+ offset >>>= 0;
+ if (offset < 0 || offset + 8 > this.buffer.byteLength)
+ throw RangeError("Illegal offset: 0 <= "+offset+" (+"+8+") <= "+this.buffer.byteLength);
+ }
+ var value = this.littleEndian
+ ? new Long(this.view.getInt32(offset , true ), this.view.getInt32(offset+4, true ), false)
+ : new Long(this.view.getInt32(offset+4, false), this.view.getInt32(offset , false), false);
+ if (relative) this.offset += 8;
+ return value;
+ };
+
+ /**
+ * Reads a 64bit signed integer. This is an alias of {@link ByteBuffer#readInt64}.
+ * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by `8` if omitted.
+ * @returns {!Long}
+ * @expose
+ */
+ ByteBufferPrototype.readLong = ByteBufferPrototype.readInt64;
+
+ /**
+ * Writes a 64bit unsigned integer.
+ * @param {number|!Long} value Value to write
+ * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by `8` if omitted.
+ * @returns {!ByteBuffer} this
+ * @expose
+ */
+ ByteBufferPrototype.writeUint64 = function(value, offset) {
+ var relative = typeof offset === 'undefined';
+ if (relative) offset = this.offset;
+ if (!this.noAssert) {
+ if (typeof value === 'number')
+ value = Long.fromNumber(value);
+ else if (!(value && value instanceof Long))
+ throw TypeError("Illegal value: "+value+" (not an integer or Long)");
+ if (typeof offset !== 'number' || offset % 1 !== 0)
+ throw TypeError("Illegal offset: "+offset+" (not an integer)");
+ offset >>>= 0;
+ if (offset < 0 || offset + 0 > this.buffer.byteLength)
+ throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength);
+ }
+ if (typeof value === 'number')
+ value = Long.fromNumber(value);
+ offset += 8;
+ var capacity7 = this.buffer.byteLength;
+ if (offset > capacity7)
+ this.resize((capacity7 *= 2) > offset ? capacity7 : offset);
+ offset -= 8;
+ if (this.littleEndian) {
+ this.view.setInt32(offset , value.low , true);
+ this.view.setInt32(offset+4, value.high, true);
+ } else {
+ this.view.setInt32(offset , value.high, false);
+ this.view.setInt32(offset+4, value.low , false);
+ }
+ if (relative) this.offset += 8;
+ return this;
+ };
+
+ /**
+ * Reads a 64bit unsigned integer.
+ * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by `8` if omitted.
+ * @returns {!Long}
+ * @expose
+ */
+ ByteBufferPrototype.readUint64 = function(offset) {
+ var relative = typeof offset === 'undefined';
+ if (relative) offset = this.offset;
+ if (!this.noAssert) {
+ if (typeof offset !== 'number' || offset % 1 !== 0)
+ throw TypeError("Illegal offset: "+offset+" (not an integer)");
+ offset >>>= 0;
+ if (offset < 0 || offset + 8 > this.buffer.byteLength)
+ throw RangeError("Illegal offset: 0 <= "+offset+" (+"+8+") <= "+this.buffer.byteLength);
+ }
+ var value = this.littleEndian
+ ? new Long(this.view.getInt32(offset , true ), this.view.getInt32(offset+4, true ), true)
+ : new Long(this.view.getInt32(offset+4, false), this.view.getInt32(offset , false), true);
+ if (relative) this.offset += 8;
+ return value;
+ };
+
+ } // Long
+
+
+ // types/floats/float32
+
+ /**
+ * Writes a 32bit float.
+ * @param {number} value Value to write
+ * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by `4` if omitted.
+ * @returns {!ByteBuffer} this
+ * @expose
+ */
+ ByteBufferPrototype.writeFloat32 = function(value, offset) {
+ var relative = typeof offset === 'undefined';
+ if (relative) offset = this.offset;
+ if (!this.noAssert) {
+ if (typeof value !== 'number')
+ throw TypeError("Illegal value: "+value+" (not a number)");
+ if (typeof offset !== 'number' || offset % 1 !== 0)
+ throw TypeError("Illegal offset: "+offset+" (not an integer)");
+ offset >>>= 0;
+ if (offset < 0 || offset + 0 > this.buffer.byteLength)
+ throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength);
+ }
+ offset += 4;
+ var capacity8 = this.buffer.byteLength;
+ if (offset > capacity8)
+ this.resize((capacity8 *= 2) > offset ? capacity8 : offset);
+ offset -= 4;
+ this.view.setFloat32(offset, value, this.littleEndian);
+ if (relative) this.offset += 4;
+ return this;
+ };
+
+ /**
+ * Writes a 32bit float. This is an alias of {@link ByteBuffer#writeFloat32}.
+ * @function
+ * @param {number} value Value to write
+ * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by `4` if omitted.
+ * @returns {!ByteBuffer} this
+ * @expose
+ */
+ ByteBufferPrototype.writeFloat = ByteBufferPrototype.writeFloat32;
+
+ /**
+ * Reads a 32bit float.
+ * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by `4` if omitted.
+ * @returns {number}
+ * @expose
+ */
+ ByteBufferPrototype.readFloat32 = function(offset) {
+ var relative = typeof offset === 'undefined';
+ if (relative) offset = this.offset;
+ if (!this.noAssert) {
+ if (typeof offset !== 'number' || offset % 1 !== 0)
+ throw TypeError("Illegal offset: "+offset+" (not an integer)");
+ offset >>>= 0;
+ if (offset < 0 || offset + 4 > this.buffer.byteLength)
+ throw RangeError("Illegal offset: 0 <= "+offset+" (+"+4+") <= "+this.buffer.byteLength);
+ }
+ var value = this.view.getFloat32(offset, this.littleEndian);
+ if (relative) this.offset += 4;
+ return value;
+ };
+
+ /**
+ * Reads a 32bit float. This is an alias of {@link ByteBuffer#readFloat32}.
+ * @function
+ * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by `4` if omitted.
+ * @returns {number}
+ * @expose
+ */
+ ByteBufferPrototype.readFloat = ByteBufferPrototype.readFloat32;
+
+ // types/floats/float64
+
+ /**
+ * Writes a 64bit float.
+ * @param {number} value Value to write
+ * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by `8` if omitted.
+ * @returns {!ByteBuffer} this
+ * @expose
+ */
+ ByteBufferPrototype.writeFloat64 = function(value, offset) {
+ var relative = typeof offset === 'undefined';
+ if (relative) offset = this.offset;
+ if (!this.noAssert) {
+ if (typeof value !== 'number')
+ throw TypeError("Illegal value: "+value+" (not a number)");
+ if (typeof offset !== 'number' || offset % 1 !== 0)
+ throw TypeError("Illegal offset: "+offset+" (not an integer)");
+ offset >>>= 0;
+ if (offset < 0 || offset + 0 > this.buffer.byteLength)
+ throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength);
+ }
+ offset += 8;
+ var capacity9 = this.buffer.byteLength;
+ if (offset > capacity9)
+ this.resize((capacity9 *= 2) > offset ? capacity9 : offset);
+ offset -= 8;
+ this.view.setFloat64(offset, value, this.littleEndian);
+ if (relative) this.offset += 8;
+ return this;
+ };
+
+ /**
+ * Writes a 64bit float. This is an alias of {@link ByteBuffer#writeFloat64}.
+ * @function
+ * @param {number} value Value to write
+ * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by `8` if omitted.
+ * @returns {!ByteBuffer} this
+ * @expose
+ */
+ ByteBufferPrototype.writeDouble = ByteBufferPrototype.writeFloat64;
+
+ /**
+ * Reads a 64bit float.
+ * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by `8` if omitted.
+ * @returns {number}
+ * @expose
+ */
+ ByteBufferPrototype.readFloat64 = function(offset) {
+ var relative = typeof offset === 'undefined';
+ if (relative) offset = this.offset;
+ if (!this.noAssert) {
+ if (typeof offset !== 'number' || offset % 1 !== 0)
+ throw TypeError("Illegal offset: "+offset+" (not an integer)");
+ offset >>>= 0;
+ if (offset < 0 || offset + 8 > this.buffer.byteLength)
+ throw RangeError("Illegal offset: 0 <= "+offset+" (+"+8+") <= "+this.buffer.byteLength);
+ }
+ var value = this.view.getFloat64(offset, this.littleEndian);
+ if (relative) this.offset += 8;
+ return value;
+ };
+
+ /**
+ * Reads a 64bit float. This is an alias of {@link ByteBuffer#readFloat64}.
+ * @function
+ * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by `8` if omitted.
+ * @returns {number}
+ * @expose
+ */
+ ByteBufferPrototype.readDouble = ByteBufferPrototype.readFloat64;
+
+
+ // types/varints/varint32
+
+ /**
+ * Maximum number of bytes required to store a 32bit base 128 variable-length integer.
+ * @type {number}
+ * @const
+ * @expose
+ */
+ ByteBuffer.MAX_VARINT32_BYTES = 5;
+
+ /**
+ * Calculates the actual number of bytes required to store a 32bit base 128 variable-length integer.
+ * @param {number} value Value to encode
+ * @returns {number} Number of bytes required. Capped to {@link ByteBuffer.MAX_VARINT32_BYTES}
+ * @expose
+ */
+ ByteBuffer.calculateVarint32 = function(value) {
+ // ref: src/google/protobuf/io/coded_stream.cc
+ value = value >>> 0;
+ if (value < 1 << 7 ) return 1;
+ else if (value < 1 << 14) return 2;
+ else if (value < 1 << 21) return 3;
+ else if (value < 1 << 28) return 4;
+ else return 5;
+ };
+
+ /**
+ * Zigzag encodes a signed 32bit integer so that it can be effectively used with varint encoding.
+ * @param {number} n Signed 32bit integer
+ * @returns {number} Unsigned zigzag encoded 32bit integer
+ * @expose
+ */
+ ByteBuffer.zigZagEncode32 = function(n) {
+ return (((n |= 0) << 1) ^ (n >> 31)) >>> 0; // ref: src/google/protobuf/wire_format_lite.h
+ };
+
+ /**
+ * Decodes a zigzag encoded signed 32bit integer.
+ * @param {number} n Unsigned zigzag encoded 32bit integer
+ * @returns {number} Signed 32bit integer
+ * @expose
+ */
+ ByteBuffer.zigZagDecode32 = function(n) {
+ return ((n >>> 1) ^ -(n & 1)) | 0; // // ref: src/google/protobuf/wire_format_lite.h
+ };
+
+ /**
+ * Writes a 32bit base 128 variable-length integer.
+ * @param {number} value Value to write
+ * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by the number of bytes
+ * written if omitted.
+ * @returns {!ByteBuffer|number} this if `offset` is omitted, else the actual number of bytes written
+ * @expose
+ */
+ ByteBufferPrototype.writeVarint32 = function(value, offset) {
+ var relative = typeof offset === 'undefined';
+ if (relative) offset = this.offset;
+ if (!this.noAssert) {
+ if (typeof value !== 'number' || value % 1 !== 0)
+ throw TypeError("Illegal value: "+value+" (not an integer)");
+ value |= 0;
+ if (typeof offset !== 'number' || offset % 1 !== 0)
+ throw TypeError("Illegal offset: "+offset+" (not an integer)");
+ offset >>>= 0;
+ if (offset < 0 || offset + 0 > this.buffer.byteLength)
+ throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength);
+ }
+ var size = ByteBuffer.calculateVarint32(value),
+ b;
+ offset += size;
+ var capacity10 = this.buffer.byteLength;
+ if (offset > capacity10)
+ this.resize((capacity10 *= 2) > offset ? capacity10 : offset);
+ offset -= size;
+ // ref: http://code.google.com/searchframe#WTeibokF6gE/trunk/src/google/protobuf/io/coded_stream.cc
+ this.view.setUint8(offset, b = value | 0x80);
+ value >>>= 0;
+ if (value >= 1 << 7) {
+ b = (value >> 7) | 0x80;
+ this.view.setUint8(offset+1, b);
+ if (value >= 1 << 14) {
+ b = (value >> 14) | 0x80;
+ this.view.setUint8(offset+2, b);
+ if (value >= 1 << 21) {
+ b = (value >> 21) | 0x80;
+ this.view.setUint8(offset+3, b);
+ if (value >= 1 << 28) {
+ this.view.setUint8(offset+4, (value >> 28) & 0x0F);
+ size = 5;
+ } else {
+ this.view.setUint8(offset+3, b & 0x7F);
+ size = 4;
+ }
+ } else {
+ this.view.setUint8(offset+2, b & 0x7F);
+ size = 3;
+ }
+ } else {
+ this.view.setUint8(offset+1, b & 0x7F);
+ size = 2;
+ }
+ } else {
+ this.view.setUint8(offset, b & 0x7F);
+ size = 1;
+ }
+ if (relative) {
+ this.offset += size;
+ return this;
+ }
+ return size;
+ };
+
+ /**
+ * Writes a zig-zag encoded 32bit base 128 variable-length integer.
+ * @param {number} value Value to write
+ * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by the number of bytes
+ * written if omitted.
+ * @returns {!ByteBuffer|number} this if `offset` is omitted, else the actual number of bytes written
+ * @expose
+ */
+ ByteBufferPrototype.writeVarint32ZigZag = function(value, offset) {
+ return this.writeVarint32(ByteBuffer.zigZagEncode32(value), offset);
+ };
+
+ /**
+ * Reads a 32bit base 128 variable-length integer.
+ * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by the number of bytes
+ * written if omitted.
+ * @returns {number|!{value: number, length: number}} The value read if offset is omitted, else the value read
+ * and the actual number of bytes read.
+ * @throws {Error} If it's not a valid varint. Has a property `truncated = true` if there is not enough data available
+ * to fully decode the varint.
+ * @expose
+ */
+ ByteBufferPrototype.readVarint32 = function(offset) {
+ var relative = typeof offset === 'undefined';
+ if (relative) offset = this.offset;
+ if (!this.noAssert) {
+ if (typeof offset !== 'number' || offset % 1 !== 0)
+ throw TypeError("Illegal offset: "+offset+" (not an integer)");
+ offset >>>= 0;
+ if (offset < 0 || offset + 1 > this.buffer.byteLength)
+ throw RangeError("Illegal offset: 0 <= "+offset+" (+"+1+") <= "+this.buffer.byteLength);
+ }
+ // ref: src/google/protobuf/io/coded_stream.cc
+ var size = 0,
+ value = 0 >>> 0,
+ temp,
+ ioffset;
+ do {
+ ioffset = offset+size;
+ if (!this.noAssert && ioffset > this.limit) {
+ var err = Error("Truncated");
+ err['truncated'] = true;
+ throw err;
+ }
+ temp = this.view.getUint8(ioffset);
+ if (size < 5)
+ value |= ((temp&0x7F)<<(7*size)) >>> 0;
+ ++size;
+ } while ((temp & 0x80) === 0x80);
+ value = value | 0; // Make sure to discard the higher order bits
+ if (relative) {
+ this.offset += size;
+ return value;
+ }
+ return {
+ "value": value,
+ "length": size
+ };
+ };
+
+ /**
+ * Reads a zig-zag encoded 32bit base 128 variable-length integer.
+ * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by the number of bytes
+ * written if omitted.
+ * @returns {number|!{value: number, length: number}} The value read if offset is omitted, else the value read
+ * and the actual number of bytes read.
+ * @throws {Error} If it's not a valid varint
+ * @expose
+ */
+ ByteBufferPrototype.readVarint32ZigZag = function(offset) {
+ var val = this.readVarint32(offset);
+ if (typeof val === 'object')
+ val["value"] = ByteBuffer.zigZagDecode32(val["value"]);
+ else
+ val = ByteBuffer.zigZagDecode32(val);
+ return val;
+ };
+
+ // types/varints/varint64
+
+ if (Long) {
+
+ /**
+ * Maximum number of bytes required to store a 64bit base 128 variable-length integer.
+ * @type {number}
+ * @const
+ * @expose
+ */
+ ByteBuffer.MAX_VARINT64_BYTES = 10;
+
+ /**
+ * Calculates the actual number of bytes required to store a 64bit base 128 variable-length integer.
+ * @param {number|!Long} value Value to encode
+ * @returns {number} Number of bytes required. Capped to {@link ByteBuffer.MAX_VARINT64_BYTES}
+ * @expose
+ */
+ ByteBuffer.calculateVarint64 = function(value) {
+ if (typeof value === 'number')
+ value = Long.fromNumber(value);
+ // ref: src/google/protobuf/io/coded_stream.cc
+ var part0 = value.toInt() >>> 0,
+ part1 = value.shiftRightUnsigned(28).toInt() >>> 0,
+ part2 = value.shiftRightUnsigned(56).toInt() >>> 0;
+ if (part2 == 0) {
+ if (part1 == 0) {
+ if (part0 < 1 << 14)
+ return part0 < 1 << 7 ? 1 : 2;
+ else
+ return part0 < 1 << 21 ? 3 : 4;
+ } else {
+ if (part1 < 1 << 14)
+ return part1 < 1 << 7 ? 5 : 6;
+ else
+ return part1 < 1 << 21 ? 7 : 8;
+ }
+ } else
+ return part2 < 1 << 7 ? 9 : 10;
+ };
+
+ /**
+ * Zigzag encodes a signed 64bit integer so that it can be effectively used with varint encoding.
+ * @param {number|!Long} value Signed long
+ * @returns {!Long} Unsigned zigzag encoded long
+ * @expose
+ */
+ ByteBuffer.zigZagEncode64 = function(value) {
+ if (typeof value === 'number')
+ value = Long.fromNumber(value, false);
+ else if (value.unsigned !== false) value = value.toSigned();
+ // ref: src/google/protobuf/wire_format_lite.h
+ return value.shiftLeft(1).xor(value.shiftRight(63)).toUnsigned();
+ };
+
+ /**
+ * Decodes a zigzag encoded signed 64bit integer.
+ * @param {!Long|number} value Unsigned zigzag encoded long or JavaScript number
+ * @returns {!Long} Signed long
+ * @expose
+ */
+ ByteBuffer.zigZagDecode64 = function(value) {
+ if (typeof value === 'number')
+ value = Long.fromNumber(value, false);
+ else if (value.unsigned !== false) value = value.toSigned();
+ // ref: src/google/protobuf/wire_format_lite.h
+ return value.shiftRightUnsigned(1).xor(value.and(Long.ONE).toSigned().negate()).toSigned();
+ };
+
+ /**
+ * Writes a 64bit base 128 variable-length integer.
+ * @param {number|Long} value Value to write
+ * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by the number of bytes
+ * written if omitted.
+ * @returns {!ByteBuffer|number} `this` if offset is omitted, else the actual number of bytes written.
+ * @expose
+ */
+ ByteBufferPrototype.writeVarint64 = function(value, offset) {
+ var relative = typeof offset === 'undefined';
+ if (relative) offset = this.offset;
+ if (!this.noAssert) {
+ if (typeof value === 'number')
+ value = Long.fromNumber(value);
+ else if (!(value && value instanceof Long))
+ throw TypeError("Illegal value: "+value+" (not an integer or Long)");
+ if (typeof offset !== 'number' || offset % 1 !== 0)
+ throw TypeError("Illegal offset: "+offset+" (not an integer)");
+ offset >>>= 0;
+ if (offset < 0 || offset + 0 > this.buffer.byteLength)
+ throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength);
+ }
+ if (typeof value === 'number')
+ value = Long.fromNumber(value, false);
+ else if (value.unsigned !== false) value = value.toSigned();
+ var size = ByteBuffer.calculateVarint64(value),
+ part0 = value.toInt() >>> 0,
+ part1 = value.shiftRightUnsigned(28).toInt() >>> 0,
+ part2 = value.shiftRightUnsigned(56).toInt() >>> 0;
+ offset += size;
+ var capacity11 = this.buffer.byteLength;
+ if (offset > capacity11)
+ this.resize((capacity11 *= 2) > offset ? capacity11 : offset);
+ offset -= size;
+ switch (size) {
+ case 10: this.view.setUint8(offset+9, (part2 >>> 7) & 0x01);
+ case 9 : this.view.setUint8(offset+8, size !== 9 ? (part2 ) | 0x80 : (part2 ) & 0x7F);
+ case 8 : this.view.setUint8(offset+7, size !== 8 ? (part1 >>> 21) | 0x80 : (part1 >>> 21) & 0x7F);
+ case 7 : this.view.setUint8(offset+6, size !== 7 ? (part1 >>> 14) | 0x80 : (part1 >>> 14) & 0x7F);
+ case 6 : this.view.setUint8(offset+5, size !== 6 ? (part1 >>> 7) | 0x80 : (part1 >>> 7) & 0x7F);
+ case 5 : this.view.setUint8(offset+4, size !== 5 ? (part1 ) | 0x80 : (part1 ) & 0x7F);
+ case 4 : this.view.setUint8(offset+3, size !== 4 ? (part0 >>> 21) | 0x80 : (part0 >>> 21) & 0x7F);
+ case 3 : this.view.setUint8(offset+2, size !== 3 ? (part0 >>> 14) | 0x80 : (part0 >>> 14) & 0x7F);
+ case 2 : this.view.setUint8(offset+1, size !== 2 ? (part0 >>> 7) | 0x80 : (part0 >>> 7) & 0x7F);
+ case 1 : this.view.setUint8(offset , size !== 1 ? (part0 ) | 0x80 : (part0 ) & 0x7F);
+ }
+ if (relative) {
+ this.offset += size;
+ return this;
+ } else {
+ return size;
+ }
+ };
+
+ /**
+ * Writes a zig-zag encoded 64bit base 128 variable-length integer.
+ * @param {number|Long} value Value to write
+ * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by the number of bytes
+ * written if omitted.
+ * @returns {!ByteBuffer|number} `this` if offset is omitted, else the actual number of bytes written.
+ * @expose
+ */
+ ByteBufferPrototype.writeVarint64ZigZag = function(value, offset) {
+ return this.writeVarint64(ByteBuffer.zigZagEncode64(value), offset);
+ };
+
+ /**
+ * Reads a 64bit base 128 variable-length integer. Requires Long.js.
+ * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by the number of bytes
+ * read if omitted.
+ * @returns {!Long|!{value: Long, length: number}} The value read if offset is omitted, else the value read and
+ * the actual number of bytes read.
+ * @throws {Error} If it's not a valid varint
+ * @expose
+ */
+ ByteBufferPrototype.readVarint64 = function(offset) {
+ var relative = typeof offset === 'undefined';
+ if (relative) offset = this.offset;
+ if (!this.noAssert) {
+ if (typeof offset !== 'number' || offset % 1 !== 0)
+ throw TypeError("Illegal offset: "+offset+" (not an integer)");
+ offset >>>= 0;
+ if (offset < 0 || offset + 1 > this.buffer.byteLength)
+ throw RangeError("Illegal offset: 0 <= "+offset+" (+"+1+") <= "+this.buffer.byteLength);
+ }
+ // ref: src/google/protobuf/io/coded_stream.cc
+ var start = offset,
+ part0 = 0,
+ part1 = 0,
+ part2 = 0,
+ b = 0;
+ b = this.view.getUint8(offset++); part0 = (b & 0x7F) ; if (b & 0x80) {
+ b = this.view.getUint8(offset++); part0 |= (b & 0x7F) << 7; if (b & 0x80) {
+ b = this.view.getUint8(offset++); part0 |= (b & 0x7F) << 14; if (b & 0x80) {
+ b = this.view.getUint8(offset++); part0 |= (b & 0x7F) << 21; if (b & 0x80) {
+ b = this.view.getUint8(offset++); part1 = (b & 0x7F) ; if (b & 0x80) {
+ b = this.view.getUint8(offset++); part1 |= (b & 0x7F) << 7; if (b & 0x80) {
+ b = this.view.getUint8(offset++); part1 |= (b & 0x7F) << 14; if (b & 0x80) {
+ b = this.view.getUint8(offset++); part1 |= (b & 0x7F) << 21; if (b & 0x80) {
+ b = this.view.getUint8(offset++); part2 = (b & 0x7F) ; if (b & 0x80) {
+ b = this.view.getUint8(offset++); part2 |= (b & 0x7F) << 7; if (b & 0x80) {
+ throw Error("Buffer overrun"); }}}}}}}}}}
+ var value = Long.fromBits(part0 | (part1 << 28), (part1 >>> 4) | (part2) << 24, false);
+ if (relative) {
+ this.offset = offset;
+ return value;
+ } else {
+ return {
+ 'value': value,
+ 'length': offset-start
+ };
+ }
+ };
+
+ /**
+ * Reads a zig-zag encoded 64bit base 128 variable-length integer. Requires Long.js.
+ * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by the number of bytes
+ * read if omitted.
+ * @returns {!Long|!{value: Long, length: number}} The value read if offset is omitted, else the value read and
+ * the actual number of bytes read.
+ * @throws {Error} If it's not a valid varint
+ * @expose
+ */
+ ByteBufferPrototype.readVarint64ZigZag = function(offset) {
+ var val = this.readVarint64(offset);
+ if (val && val['value'] instanceof Long)
+ val["value"] = ByteBuffer.zigZagDecode64(val["value"]);
+ else
+ val = ByteBuffer.zigZagDecode64(val);
+ return val;
+ };
+
+ } // Long
+
+
+ // types/strings/cstring
+
+ /**
+ * Writes a NULL-terminated UTF8 encoded string. For this to work the specified string must not contain any NULL
+ * characters itself.
+ * @param {string} str String to write
+ * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by the number of bytes
+ * contained in `str` + 1 if omitted.
+ * @returns {!ByteBuffer|number} this if offset is omitted, else the actual number of bytes written
+ * @expose
+ */
+ ByteBufferPrototype.writeCString = function(str, offset) {
+ var relative = typeof offset === 'undefined';
+ if (relative) offset = this.offset;
+ var i,
+ k = str.length;
+ if (!this.noAssert) {
+ if (typeof str !== 'string')
+ throw TypeError("Illegal str: Not a string");
+ for (i=0; i>>= 0;
+ if (offset < 0 || offset + 0 > this.buffer.byteLength)
+ throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength);
+ }
+ var start = offset;
+ // UTF8 strings do not contain zero bytes in between except for the zero character, so:
+ k = utfx.calculateUTF16asUTF8(stringSource(str))[1];
+ offset += k+1;
+ var capacity12 = this.buffer.byteLength;
+ if (offset > capacity12)
+ this.resize((capacity12 *= 2) > offset ? capacity12 : offset);
+ offset -= k+1;
+ utfx.encodeUTF16toUTF8(stringSource(str), function(b) {
+ this.view.setUint8(offset++, b);
+ }.bind(this));
+ this.view.setUint8(offset++, 0);
+ if (relative) {
+ this.offset = offset - start;
+ return this;
+ }
+ return k;
+ };
+
+ /**
+ * Reads a NULL-terminated UTF8 encoded string. For this to work the string read must not contain any NULL characters
+ * itself.
+ * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by the number of bytes
+ * read if omitted.
+ * @returns {string|!{string: string, length: number}} The string read if offset is omitted, else the string
+ * read and the actual number of bytes read.
+ * @expose
+ */
+ ByteBufferPrototype.readCString = function(offset) {
+ var relative = typeof offset === 'undefined';
+ if (relative) offset = this.offset;
+ if (!this.noAssert) {
+ if (typeof offset !== 'number' || offset % 1 !== 0)
+ throw TypeError("Illegal offset: "+offset+" (not an integer)");
+ offset >>>= 0;
+ if (offset < 0 || offset + 1 > this.buffer.byteLength)
+ throw RangeError("Illegal offset: 0 <= "+offset+" (+"+1+") <= "+this.buffer.byteLength);
+ }
+ var start = offset,
+ temp;
+ // UTF8 strings do not contain zero bytes in between except for the zero character itself, so:
+ var sd, b = -1;
+ utfx.decodeUTF8toUTF16(function() {
+ if (b === 0) return null;
+ if (offset >= this.limit)
+ throw RangeError("Illegal range: Truncated data, "+offset+" < "+this.limit);
+ return (b = this.view.getUint8(offset++)) === 0 ? null : b;
+ }.bind(this), sd = stringDestination(), true);
+ if (relative) {
+ this.offset = offset;
+ return sd();
+ } else {
+ return {
+ "string": sd(),
+ "length": offset - start
+ };
+ }
+ };
+
+ // types/strings/istring
+
+ /**
+ * Writes a length as uint32 prefixed UTF8 encoded string.
+ * @param {string} str String to write
+ * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by the number of bytes
+ * written if omitted.
+ * @returns {!ByteBuffer|number} `this` if `offset` is omitted, else the actual number of bytes written
+ * @expose
+ * @see ByteBuffer#writeVarint32
+ */
+ ByteBufferPrototype.writeIString = function(str, offset) {
+ var relative = typeof offset === 'undefined';
+ if (relative) offset = this.offset;
+ if (!this.noAssert) {
+ if (typeof str !== 'string')
+ throw TypeError("Illegal str: Not a string");
+ if (typeof offset !== 'number' || offset % 1 !== 0)
+ throw TypeError("Illegal offset: "+offset+" (not an integer)");
+ offset >>>= 0;
+ if (offset < 0 || offset + 0 > this.buffer.byteLength)
+ throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength);
+ }
+ var start = offset,
+ k;
+ k = utfx.calculateUTF16asUTF8(stringSource(str), this.noAssert)[1];
+ offset += 4+k;
+ var capacity13 = this.buffer.byteLength;
+ if (offset > capacity13)
+ this.resize((capacity13 *= 2) > offset ? capacity13 : offset);
+ offset -= 4+k;
+ this.view.setUint32(offset, k, this.littleEndian);
+ offset += 4;
+ utfx.encodeUTF16toUTF8(stringSource(str), function(b) {
+ this.view.setUint8(offset++, b);
+ }.bind(this));
+ if (offset !== start + 4 + k)
+ throw RangeError("Illegal range: Truncated data, "+offset+" == "+(offset+4+k));
+ if (relative) {
+ this.offset = offset;
+ return this;
+ }
+ return offset - start;
+ };
+
+ /**
+ * Reads a length as uint32 prefixed UTF8 encoded string.
+ * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by the number of bytes
+ * read if omitted.
+ * @returns {string|!{string: string, length: number}} The string read if offset is omitted, else the string
+ * read and the actual number of bytes read.
+ * @expose
+ * @see ByteBuffer#readVarint32
+ */
+ ByteBufferPrototype.readIString = function(offset) {
+ var relative = typeof offset === 'undefined';
+ if (relative) offset = this.offset;
+ if (!this.noAssert) {
+ if (typeof offset !== 'number' || offset % 1 !== 0)
+ throw TypeError("Illegal offset: "+offset+" (not an integer)");
+ offset >>>= 0;
+ if (offset < 0 || offset + 4 > this.buffer.byteLength)
+ throw RangeError("Illegal offset: 0 <= "+offset+" (+"+4+") <= "+this.buffer.byteLength);
+ }
+ var temp = 0,
+ start = offset,
+ str;
+ temp = this.view.getUint32(offset, this.littleEndian);
+ offset += 4;
+ var k = offset + temp,
+ sd;
+ utfx.decodeUTF8toUTF16(function() {
+ return offset < k ? this.view.getUint8(offset++) : null;
+ }.bind(this), sd = stringDestination(), this.noAssert);
+ str = sd();
+ if (relative) {
+ this.offset = offset;
+ return str;
+ } else {
+ return {
+ 'string': str,
+ 'length': offset - start
+ };
+ }
+ };
+
+ // types/strings/utf8string
+
+ /**
+ * Metrics representing number of UTF8 characters. Evaluates to `c`.
+ * @type {string}
+ * @const
+ * @expose
+ */
+ ByteBuffer.METRICS_CHARS = 'c';
+
+ /**
+ * Metrics representing number of bytes. Evaluates to `b`.
+ * @type {string}
+ * @const
+ * @expose
+ */
+ ByteBuffer.METRICS_BYTES = 'b';
+
+ /**
+ * Writes an UTF8 encoded string.
+ * @param {string} str String to write
+ * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} if omitted.
+ * @returns {!ByteBuffer|number} this if offset is omitted, else the actual number of bytes written.
+ * @expose
+ */
+ ByteBufferPrototype.writeUTF8String = function(str, offset) {
+ var relative = typeof offset === 'undefined';
+ if (relative) offset = this.offset;
+ if (!this.noAssert) {
+ if (typeof offset !== 'number' || offset % 1 !== 0)
+ throw TypeError("Illegal offset: "+offset+" (not an integer)");
+ offset >>>= 0;
+ if (offset < 0 || offset + 0 > this.buffer.byteLength)
+ throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength);
+ }
+ var k;
+ var start = offset;
+ k = utfx.calculateUTF16asUTF8(stringSource(str))[1];
+ offset += k;
+ var capacity14 = this.buffer.byteLength;
+ if (offset > capacity14)
+ this.resize((capacity14 *= 2) > offset ? capacity14 : offset);
+ offset -= k;
+ utfx.encodeUTF16toUTF8(stringSource(str), function(b) {
+ this.view.setUint8(offset++, b);
+ }.bind(this));
+ if (relative) {
+ this.offset = offset;
+ return this;
+ }
+ return offset - start;
+ };
+
+ /**
+ * Writes an UTF8 encoded string. This is an alias of {@link ByteBuffer#writeUTF8String}.
+ * @function
+ * @param {string} str String to write
+ * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} if omitted.
+ * @returns {!ByteBuffer|number} this if offset is omitted, else the actual number of bytes written.
+ * @expose
+ */
+ ByteBufferPrototype.writeString = ByteBufferPrototype.writeUTF8String;
+
+ /**
+ * Calculates the number of UTF8 characters of a string. JavaScript itself uses UTF-16, so that a string's
+ * `length` property does not reflect its actual UTF8 size if it contains code points larger than 0xFFFF.
+ * @function
+ * @param {string} str String to calculate
+ * @returns {number} Number of UTF8 characters
+ * @expose
+ */
+ ByteBuffer.calculateUTF8Chars = function(str) {
+ return utfx.calculateUTF16asUTF8(stringSource(str))[0];
+ };
+
+ /**
+ * Calculates the number of UTF8 bytes of a string.
+ * @function
+ * @param {string} str String to calculate
+ * @returns {number} Number of UTF8 bytes
+ * @expose
+ */
+ ByteBuffer.calculateUTF8Bytes = function(str) {
+ return utfx.calculateUTF16asUTF8(stringSource(str))[1];
+ };
+
+ /**
+ * Reads an UTF8 encoded string.
+ * @param {number} length Number of characters or bytes to read.
+ * @param {string=} metrics Metrics specifying what `length` is meant to count. Defaults to
+ * {@link ByteBuffer.METRICS_CHARS}.
+ * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by the number of bytes
+ * read if omitted.
+ * @returns {string|!{string: string, length: number}} The string read if offset is omitted, else the string
+ * read and the actual number of bytes read.
+ * @expose
+ */
+ ByteBufferPrototype.readUTF8String = function(length, metrics, offset) {
+ if (typeof metrics === 'number') {
+ offset = metrics;
+ metrics = undefined;
+ }
+ var relative = typeof offset === 'undefined';
+ if (relative) offset = this.offset;
+ if (typeof metrics === 'undefined') metrics = ByteBuffer.METRICS_CHARS;
+ if (!this.noAssert) {
+ if (typeof length !== 'number' || length % 1 !== 0)
+ throw TypeError("Illegal length: "+length+" (not an integer)");
+ length |= 0;
+ if (typeof offset !== 'number' || offset % 1 !== 0)
+ throw TypeError("Illegal offset: "+offset+" (not an integer)");
+ offset >>>= 0;
+ if (offset < 0 || offset + 0 > this.buffer.byteLength)
+ throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength);
+ }
+ var i = 0,
+ start = offset,
+ sd;
+ if (metrics === ByteBuffer.METRICS_CHARS) { // The same for node and the browser
+ sd = stringDestination();
+ utfx.decodeUTF8(function() {
+ return i < length && offset < this.limit ? this.view.getUint8(offset++) : null;
+ }.bind(this), function(cp) {
+ ++i; utfx.UTF8toUTF16(cp, sd);
+ }.bind(this));
+ if (i !== length)
+ throw RangeError("Illegal range: Truncated data, "+i+" == "+length);
+ if (relative) {
+ this.offset = offset;
+ return sd();
+ } else {
+ return {
+ "string": sd(),
+ "length": offset - start
+ };
+ }
+ } else if (metrics === ByteBuffer.METRICS_BYTES) {
+ if (!this.noAssert) {
+ if (typeof offset !== 'number' || offset % 1 !== 0)
+ throw TypeError("Illegal offset: "+offset+" (not an integer)");
+ offset >>>= 0;
+ if (offset < 0 || offset + length > this.buffer.byteLength)
+ throw RangeError("Illegal offset: 0 <= "+offset+" (+"+length+") <= "+this.buffer.byteLength);
+ }
+ var k = offset + length;
+ utfx.decodeUTF8toUTF16(function() {
+ return offset < k ? this.view.getUint8(offset++) : null;
+ }.bind(this), sd = stringDestination(), this.noAssert);
+ if (offset !== k)
+ throw RangeError("Illegal range: Truncated data, "+offset+" == "+k);
+ if (relative) {
+ this.offset = offset;
+ return sd();
+ } else {
+ return {
+ 'string': sd(),
+ 'length': offset - start
+ };
+ }
+ } else
+ throw TypeError("Unsupported metrics: "+metrics);
+ };
+
+ /**
+ * Reads an UTF8 encoded string. This is an alias of {@link ByteBuffer#readUTF8String}.
+ * @function
+ * @param {number} length Number of characters or bytes to read
+ * @param {number=} metrics Metrics specifying what `n` is meant to count. Defaults to
+ * {@link ByteBuffer.METRICS_CHARS}.
+ * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by the number of bytes
+ * read if omitted.
+ * @returns {string|!{string: string, length: number}} The string read if offset is omitted, else the string
+ * read and the actual number of bytes read.
+ * @expose
+ */
+ ByteBufferPrototype.readString = ByteBufferPrototype.readUTF8String;
+
+ // types/strings/vstring
+
+ /**
+ * Writes a length as varint32 prefixed UTF8 encoded string.
+ * @param {string} str String to write
+ * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by the number of bytes
+ * written if omitted.
+ * @returns {!ByteBuffer|number} `this` if `offset` is omitted, else the actual number of bytes written
+ * @expose
+ * @see ByteBuffer#writeVarint32
+ */
+ ByteBufferPrototype.writeVString = function(str, offset) {
+ var relative = typeof offset === 'undefined';
+ if (relative) offset = this.offset;
+ if (!this.noAssert) {
+ if (typeof str !== 'string')
+ throw TypeError("Illegal str: Not a string");
+ if (typeof offset !== 'number' || offset % 1 !== 0)
+ throw TypeError("Illegal offset: "+offset+" (not an integer)");
+ offset >>>= 0;
+ if (offset < 0 || offset + 0 > this.buffer.byteLength)
+ throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength);
+ }
+ var start = offset,
+ k, l;
+ k = utfx.calculateUTF16asUTF8(stringSource(str), this.noAssert)[1];
+ l = ByteBuffer.calculateVarint32(k);
+ offset += l+k;
+ var capacity15 = this.buffer.byteLength;
+ if (offset > capacity15)
+ this.resize((capacity15 *= 2) > offset ? capacity15 : offset);
+ offset -= l+k;
+ offset += this.writeVarint32(k, offset);
+ utfx.encodeUTF16toUTF8(stringSource(str), function(b) {
+ this.view.setUint8(offset++, b);
+ }.bind(this));
+ if (offset !== start+k+l)
+ throw RangeError("Illegal range: Truncated data, "+offset+" == "+(offset+k+l));
+ if (relative) {
+ this.offset = offset;
+ return this;
+ }
+ return offset - start;
+ };
+
+ /**
+ * Reads a length as varint32 prefixed UTF8 encoded string.
+ * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by the number of bytes
+ * read if omitted.
+ * @returns {string|!{string: string, length: number}} The string read if offset is omitted, else the string
+ * read and the actual number of bytes read.
+ * @expose
+ * @see ByteBuffer#readVarint32
+ */
+ ByteBufferPrototype.readVString = function(offset) {
+ var relative = typeof offset === 'undefined';
+ if (relative) offset = this.offset;
+ if (!this.noAssert) {
+ if (typeof offset !== 'number' || offset % 1 !== 0)
+ throw TypeError("Illegal offset: "+offset+" (not an integer)");
+ offset >>>= 0;
+ if (offset < 0 || offset + 1 > this.buffer.byteLength)
+ throw RangeError("Illegal offset: 0 <= "+offset+" (+"+1+") <= "+this.buffer.byteLength);
+ }
+ var temp = this.readVarint32(offset),
+ start = offset,
+ str;
+ offset += temp['length'];
+ temp = temp['value'];
+ var k = offset + temp,
+ sd = stringDestination();
+ utfx.decodeUTF8toUTF16(function() {
+ return offset < k ? this.view.getUint8(offset++) : null;
+ }.bind(this), sd, this.noAssert);
+ str = sd();
+ if (relative) {
+ this.offset = offset;
+ return str;
+ } else {
+ return {
+ 'string': str,
+ 'length': offset - start
+ };
+ }
+ };
+
+
+ /**
+ * Appends some data to this ByteBuffer. This will overwrite any contents behind the specified offset up to the appended
+ * data's length.
+ * @param {!ByteBuffer|!ArrayBuffer|!Uint8Array|string} source Data to append. If `source` is a ByteBuffer, its offsets
+ * will be modified according to the performed read operation.
+ * @param {(string|number)=} encoding Encoding if `data` is a string ("base64", "hex", "binary", defaults to "utf8")
+ * @param {number=} offset Offset to append at. Will use and increase {@link ByteBuffer#offset} by the number of bytes
+ * read if omitted.
+ * @returns {!ByteBuffer} this
+ * @expose
+ * @example A relative `<01 02>03.append(<04 05>)` will result in `<01 02 04 05>, 04 05|`
+ * @example An absolute `<01 02>03.append(04 05>, 1)` will result in `<01 04>05, 04 05|`
+ */
+ ByteBufferPrototype.append = function(source, encoding, offset) {
+ if (typeof encoding === 'number' || typeof encoding !== 'string') {
+ offset = encoding;
+ encoding = undefined;
+ }
+ var relative = typeof offset === 'undefined';
+ if (relative) offset = this.offset;
+ if (!this.noAssert) {
+ if (typeof offset !== 'number' || offset % 1 !== 0)
+ throw TypeError("Illegal offset: "+offset+" (not an integer)");
+ offset >>>= 0;
+ if (offset < 0 || offset + 0 > this.buffer.byteLength)
+ throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength);
+ }
+ if (!(source instanceof ByteBuffer))
+ source = ByteBuffer.wrap(source, encoding);
+ var length = source.limit - source.offset;
+ if (length <= 0) return this; // Nothing to append
+ offset += length;
+ var capacity16 = this.buffer.byteLength;
+ if (offset > capacity16)
+ this.resize((capacity16 *= 2) > offset ? capacity16 : offset);
+ offset -= length;
+ new Uint8Array(this.buffer, offset).set(new Uint8Array(source.buffer).subarray(source.offset, source.limit));
+ source.offset += length;
+ if (relative) this.offset += length;
+ return this;
+ };
+
+ /**
+ * Appends this ByteBuffer's contents to another ByteBuffer. This will overwrite any contents behind the specified
+ * offset up to the length of this ByteBuffer's data.
+ * @param {!ByteBuffer} target Target ByteBuffer
+ * @param {number=} offset Offset to append to. Will use and increase {@link ByteBuffer#offset} by the number of bytes
+ * read if omitted.
+ * @returns {!ByteBuffer} this
+ * @expose
+ * @see ByteBuffer#append
+ */
+ ByteBufferPrototype.appendTo = function(target, offset) {
+ target.append(this, offset);
+ return this;
+ };
+
+ /**
+ * Enables or disables assertions of argument types and offsets. Assertions are enabled by default but you can opt to
+ * disable them if your code already makes sure that everything is valid.
+ * @param {boolean} assert `true` to enable assertions, otherwise `false`
+ * @returns {!ByteBuffer} this
+ * @expose
+ */
+ ByteBufferPrototype.assert = function(assert) {
+ this.noAssert = !assert;
+ return this;
+ };
+
+ /**
+ * Gets the capacity of this ByteBuffer's backing buffer.
+ * @returns {number} Capacity of the backing buffer
+ * @expose
+ */
+ ByteBufferPrototype.capacity = function() {
+ return this.buffer.byteLength;
+ };
+
+ /**
+ * Clears this ByteBuffer's offsets by setting {@link ByteBuffer#offset} to `0` and {@link ByteBuffer#limit} to the
+ * backing buffer's capacity. Discards {@link ByteBuffer#markedOffset}.
+ * @returns {!ByteBuffer} this
+ * @expose
+ */
+ ByteBufferPrototype.clear = function() {
+ this.offset = 0;
+ this.limit = this.buffer.byteLength;
+ this.markedOffset = -1;
+ return this;
+ };
+
+ /**
+ * Creates a cloned instance of this ByteBuffer, preset with this ByteBuffer's values for {@link ByteBuffer#offset},
+ * {@link ByteBuffer#markedOffset} and {@link ByteBuffer#limit}.
+ * @param {boolean=} copy Whether to copy the backing buffer or to return another view on the same, defaults to `false`
+ * @returns {!ByteBuffer} Cloned instance
+ * @expose
+ */
+ ByteBufferPrototype.clone = function(copy) {
+ var bb = new ByteBuffer(0, this.littleEndian, this.noAssert);
+ if (copy) {
+ var buffer = new ArrayBuffer(this.buffer.byteLength);
+ new Uint8Array(buffer).set(this.buffer);
+ bb.buffer = buffer;
+ bb.view = new DataView(buffer);
+ } else {
+ bb.buffer = this.buffer;
+ bb.view = this.view;
+ }
+ bb.offset = this.offset;
+ bb.markedOffset = this.markedOffset;
+ bb.limit = this.limit;
+ return bb;
+ };
+
+ /**
+ * Compacts this ByteBuffer to be backed by a {@link ByteBuffer#buffer} of its contents' length. Contents are the bytes
+ * between {@link ByteBuffer#offset} and {@link ByteBuffer#limit}. Will set `offset = 0` and `limit = capacity` and
+ * adapt {@link ByteBuffer#markedOffset} to the same relative position if set.
+ * @param {number=} begin Offset to start at, defaults to {@link ByteBuffer#offset}
+ * @param {number=} end Offset to end at, defaults to {@link ByteBuffer#limit}
+ * @returns {!ByteBuffer} this
+ * @expose
+ */
+ ByteBufferPrototype.compact = function(begin, end) {
+ if (typeof begin === 'undefined') begin = this.offset;
+ if (typeof end === 'undefined') end = this.limit;
+ if (!this.noAssert) {
+ if (typeof begin !== 'number' || begin % 1 !== 0)
+ throw TypeError("Illegal begin: Not an integer");
+ begin >>>= 0;
+ if (typeof end !== 'number' || end % 1 !== 0)
+ throw TypeError("Illegal end: Not an integer");
+ end >>>= 0;
+ if (begin < 0 || begin > end || end > this.buffer.byteLength)
+ throw RangeError("Illegal range: 0 <= "+begin+" <= "+end+" <= "+this.buffer.byteLength);
+ }
+ if (begin === 0 && end === this.buffer.byteLength)
+ return this; // Already compacted
+ var len = end - begin;
+ if (len === 0) {
+ this.buffer = EMPTY_BUFFER;
+ this.view = null;
+ if (this.markedOffset >= 0) this.markedOffset -= begin;
+ this.offset = 0;
+ this.limit = 0;
+ return this;
+ }
+ var buffer = new ArrayBuffer(len);
+ new Uint8Array(buffer).set(new Uint8Array(this.buffer).subarray(begin, end));
+ this.buffer = buffer;
+ this.view = new DataView(buffer);
+ if (this.markedOffset >= 0) this.markedOffset -= begin;
+ this.offset = 0;
+ this.limit = len;
+ return this;
+ };
+
+ /**
+ * Creates a copy of this ByteBuffer's contents. Contents are the bytes between {@link ByteBuffer#offset} and
+ * {@link ByteBuffer#limit}.
+ * @param {number=} begin Begin offset, defaults to {@link ByteBuffer#offset}.
+ * @param {number=} end End offset, defaults to {@link ByteBuffer#limit}.
+ * @returns {!ByteBuffer} Copy
+ * @expose
+ */
+ ByteBufferPrototype.copy = function(begin, end) {
+ if (typeof begin === 'undefined') begin = this.offset;
+ if (typeof end === 'undefined') end = this.limit;
+ if (!this.noAssert) {
+ if (typeof begin !== 'number' || begin % 1 !== 0)
+ throw TypeError("Illegal begin: Not an integer");
+ begin >>>= 0;
+ if (typeof end !== 'number' || end % 1 !== 0)
+ throw TypeError("Illegal end: Not an integer");
+ end >>>= 0;
+ if (begin < 0 || begin > end || end > this.buffer.byteLength)
+ throw RangeError("Illegal range: 0 <= "+begin+" <= "+end+" <= "+this.buffer.byteLength);
+ }
+ if (begin === end)
+ return new ByteBuffer(0, this.littleEndian, this.noAssert);
+ var capacity = end - begin,
+ bb = new ByteBuffer(capacity, this.littleEndian, this.noAssert);
+ bb.offset = 0;
+ bb.limit = capacity;
+ if (bb.markedOffset >= 0) bb.markedOffset -= begin;
+ this.copyTo(bb, 0, begin, end);
+ return bb;
+ };
+
+ /**
+ * Copies this ByteBuffer's contents to another ByteBuffer. Contents are the bytes between {@link ByteBuffer#offset} and
+ * {@link ByteBuffer#limit}.
+ * @param {!ByteBuffer} target Target ByteBuffer
+ * @param {number=} targetOffset Offset to copy to. Will use and increase the target's {@link ByteBuffer#offset}
+ * by the number of bytes copied if omitted.
+ * @param {number=} sourceOffset Offset to start copying from. Will use and increase {@link ByteBuffer#offset} by the
+ * number of bytes copied if omitted.
+ * @param {number=} sourceLimit Offset to end copying from, defaults to {@link ByteBuffer#limit}
+ * @returns {!ByteBuffer} this
+ * @expose
+ */
+ ByteBufferPrototype.copyTo = function(target, targetOffset, sourceOffset, sourceLimit) {
+ var relative,
+ targetRelative;
+ if (!this.noAssert) {
+ if (!ByteBuffer.isByteBuffer(target))
+ throw TypeError("Illegal target: Not a ByteBuffer");
+ }
+ targetOffset = (targetRelative = typeof targetOffset === 'undefined') ? target.offset : targetOffset | 0;
+ sourceOffset = (relative = typeof sourceOffset === 'undefined') ? this.offset : sourceOffset | 0;
+ sourceLimit = typeof sourceLimit === 'undefined' ? this.limit : sourceLimit | 0;
+
+ if (targetOffset < 0 || targetOffset > target.buffer.byteLength)
+ throw RangeError("Illegal target range: 0 <= "+targetOffset+" <= "+target.buffer.byteLength);
+ if (sourceOffset < 0 || sourceLimit > this.buffer.byteLength)
+ throw RangeError("Illegal source range: 0 <= "+sourceOffset+" <= "+this.buffer.byteLength);
+
+ var len = sourceLimit - sourceOffset;
+ if (len === 0)
+ return target; // Nothing to copy
+
+ target.ensureCapacity(targetOffset + len);
+
+ new Uint8Array(target.buffer).set(new Uint8Array(this.buffer).subarray(sourceOffset, sourceLimit), targetOffset);
+
+ if (relative) this.offset += len;
+ if (targetRelative) target.offset += len;
+
+ return this;
+ };
+
+ /**
+ * Makes sure that this ByteBuffer is backed by a {@link ByteBuffer#buffer} of at least the specified capacity. If the
+ * current capacity is exceeded, it will be doubled. If double the current capacity is less than the required capacity,
+ * the required capacity will be used instead.
+ * @param {number} capacity Required capacity
+ * @returns {!ByteBuffer} this
+ * @expose
+ */
+ ByteBufferPrototype.ensureCapacity = function(capacity) {
+ var current = this.buffer.byteLength;
+ if (current < capacity)
+ return this.resize((current *= 2) > capacity ? current : capacity);
+ return this;
+ };
+
+ /**
+ * Overwrites this ByteBuffer's contents with the specified value. Contents are the bytes between
+ * {@link ByteBuffer#offset} and {@link ByteBuffer#limit}.
+ * @param {number|string} value Byte value to fill with. If given as a string, the first character is used.
+ * @param {number=} begin Begin offset. Will use and increase {@link ByteBuffer#offset} by the number of bytes
+ * written if omitted. defaults to {@link ByteBuffer#offset}.
+ * @param {number=} end End offset, defaults to {@link ByteBuffer#limit}.
+ * @returns {!ByteBuffer} this
+ * @expose
+ * @example `someByteBuffer.clear().fill(0)` fills the entire backing buffer with zeroes
+ */
+ ByteBufferPrototype.fill = function(value, begin, end) {
+ var relative = typeof begin === 'undefined';
+ if (relative) begin = this.offset;
+ if (typeof value === 'string' && value.length > 0)
+ value = value.charCodeAt(0);
+ if (typeof begin === 'undefined') begin = this.offset;
+ if (typeof end === 'undefined') end = this.limit;
+ if (!this.noAssert) {
+ if (typeof value !== 'number' || value % 1 !== 0)
+ throw TypeError("Illegal value: "+value+" (not an integer)");
+ value |= 0;
+ if (typeof begin !== 'number' || begin % 1 !== 0)
+ throw TypeError("Illegal begin: Not an integer");
+ begin >>>= 0;
+ if (typeof end !== 'number' || end % 1 !== 0)
+ throw TypeError("Illegal end: Not an integer");
+ end >>>= 0;
+ if (begin < 0 || begin > end || end > this.buffer.byteLength)
+ throw RangeError("Illegal range: 0 <= "+begin+" <= "+end+" <= "+this.buffer.byteLength);
+ }
+ if (begin >= end)
+ return this; // Nothing to fill
+ while (begin < end) this.view.setUint8(begin++, value);
+ if (relative) this.offset = begin;
+ return this;
+ };
+
+ /**
+ * Makes this ByteBuffer ready for a new sequence of write or relative read operations. Sets `limit = offset` and
+ * `offset = 0`. Make sure always to flip a ByteBuffer when all relative read or write operations are complete.
+ * @returns {!ByteBuffer} this
+ * @expose
+ */
+ ByteBufferPrototype.flip = function() {
+ this.limit = this.offset;
+ this.offset = 0;
+ return this;
+ };
+ /**
+ * Marks an offset on this ByteBuffer to be used later.
+ * @param {number=} offset Offset to mark. Defaults to {@link ByteBuffer#offset}.
+ * @returns {!ByteBuffer} this
+ * @throws {TypeError} If `offset` is not a valid number
+ * @throws {RangeError} If `offset` is out of bounds
+ * @see ByteBuffer#reset
+ * @expose
+ */
+ ByteBufferPrototype.mark = function(offset) {
+ offset = typeof offset === 'undefined' ? this.offset : offset;
+ if (!this.noAssert) {
+ if (typeof offset !== 'number' || offset % 1 !== 0)
+ throw TypeError("Illegal offset: "+offset+" (not an integer)");
+ offset >>>= 0;
+ if (offset < 0 || offset + 0 > this.buffer.byteLength)
+ throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength);
+ }
+ this.markedOffset = offset;
+ return this;
+ };
+ /**
+ * Sets the byte order.
+ * @param {boolean} littleEndian `true` for little endian byte order, `false` for big endian
+ * @returns {!ByteBuffer} this
+ * @expose
+ */
+ ByteBufferPrototype.order = function(littleEndian) {
+ if (!this.noAssert) {
+ if (typeof littleEndian !== 'boolean')
+ throw TypeError("Illegal littleEndian: Not a boolean");
+ }
+ this.littleEndian = !!littleEndian;
+ return this;
+ };
+
+ /**
+ * Switches (to) little endian byte order.
+ * @param {boolean=} littleEndian Defaults to `true`, otherwise uses big endian
+ * @returns {!ByteBuffer} this
+ * @expose
+ */
+ ByteBufferPrototype.LE = function(littleEndian) {
+ this.littleEndian = typeof littleEndian !== 'undefined' ? !!littleEndian : true;
+ return this;
+ };
+
+ /**
+ * Switches (to) big endian byte order.
+ * @param {boolean=} bigEndian Defaults to `true`, otherwise uses little endian
+ * @returns {!ByteBuffer} this
+ * @expose
+ */
+ ByteBufferPrototype.BE = function(bigEndian) {
+ this.littleEndian = typeof bigEndian !== 'undefined' ? !bigEndian : false;
+ return this;
+ };
+ /**
+ * Prepends some data to this ByteBuffer. This will overwrite any contents before the specified offset up to the
+ * prepended data's length. If there is not enough space available before the specified `offset`, the backing buffer
+ * will be resized and its contents moved accordingly.
+ * @param {!ByteBuffer|string|!ArrayBuffer} source Data to prepend. If `source` is a ByteBuffer, its offset will be
+ * modified according to the performed read operation.
+ * @param {(string|number)=} encoding Encoding if `data` is a string ("base64", "hex", "binary", defaults to "utf8")
+ * @param {number=} offset Offset to prepend at. Will use and decrease {@link ByteBuffer#offset} by the number of bytes
+ * prepended if omitted.
+ * @returns {!ByteBuffer} this
+ * @expose
+ * @example A relative `00<01 02 03>.prepend(<04 05>)` results in `<04 05 01 02 03>, 04 05|`
+ * @example An absolute `00<01 02 03>.prepend(<04 05>, 2)` results in `04<05 02 03>, 04 05|`
+ */
+ ByteBufferPrototype.prepend = function(source, encoding, offset) {
+ if (typeof encoding === 'number' || typeof encoding !== 'string') {
+ offset = encoding;
+ encoding = undefined;
+ }
+ var relative = typeof offset === 'undefined';
+ if (relative) offset = this.offset;
+ if (!this.noAssert) {
+ if (typeof offset !== 'number' || offset % 1 !== 0)
+ throw TypeError("Illegal offset: "+offset+" (not an integer)");
+ offset >>>= 0;
+ if (offset < 0 || offset + 0 > this.buffer.byteLength)
+ throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength);
+ }
+ if (!(source instanceof ByteBuffer))
+ source = ByteBuffer.wrap(source, encoding);
+ var len = source.limit - source.offset;
+ if (len <= 0) return this; // Nothing to prepend
+ var diff = len - offset;
+ var arrayView;
+ if (diff > 0) { // Not enough space before offset, so resize + move
+ var buffer = new ArrayBuffer(this.buffer.byteLength + diff);
+ arrayView = new Uint8Array(buffer);
+ arrayView.set(new Uint8Array(this.buffer).subarray(offset, this.buffer.byteLength), len);
+ this.buffer = buffer;
+ this.view = new DataView(buffer);
+ this.offset += diff;
+ if (this.markedOffset >= 0) this.markedOffset += diff;
+ this.limit += diff;
+ offset += diff;
+ } else {
+ arrayView = new Uint8Array(this.buffer);
+ }
+ arrayView.set(new Uint8Array(source.buffer).subarray(source.offset, source.limit), offset - len);
+ source.offset = source.limit;
+ if (relative)
+ this.offset -= len;
+ return this;
+ };
+
+ /**
+ * Prepends this ByteBuffer to another ByteBuffer. This will overwrite any contents before the specified offset up to the
+ * prepended data's length. If there is not enough space available before the specified `offset`, the backing buffer
+ * will be resized and its contents moved accordingly.
+ * @param {!ByteBuffer} target Target ByteBuffer
+ * @param {number=} offset Offset to prepend at. Will use and decrease {@link ByteBuffer#offset} by the number of bytes
+ * prepended if omitted.
+ * @returns {!ByteBuffer} this
+ * @expose
+ * @see ByteBuffer#prepend
+ */
+ ByteBufferPrototype.prependTo = function(target, offset) {
+ target.prepend(this, offset);
+ return this;
+ };
+ /**
+ * Prints debug information about this ByteBuffer's contents.
+ * @param {function(string)=} out Output function to call, defaults to console.log
+ * @expose
+ */
+ ByteBufferPrototype.printDebug = function(out) {
+ if (typeof out !== 'function') out = console.log.bind(console);
+ out(
+ this.toString()+"\n"+
+ "-------------------------------------------------------------------\n"+
+ this.toDebug(/* columns */ true)
+ );
+ };
+
+ /**
+ * Gets the number of remaining readable bytes. Contents are the bytes between {@link ByteBuffer#offset} and
+ * {@link ByteBuffer#limit}, so this returns `limit - offset`.
+ * @returns {number} Remaining readable bytes. May be negative if `offset > limit`.
+ * @expose
+ */
+ ByteBufferPrototype.remaining = function() {
+ return this.limit - this.offset;
+ };
+ /**
+ * Resets this ByteBuffer's {@link ByteBuffer#offset}. If an offset has been marked through {@link ByteBuffer#mark}
+ * before, `offset` will be set to {@link ByteBuffer#markedOffset}, which will then be discarded. If no offset has been
+ * marked, sets `offset = 0`.
+ * @returns {!ByteBuffer} this
+ * @see ByteBuffer#mark
+ * @expose
+ */
+ ByteBufferPrototype.reset = function() {
+ if (this.markedOffset >= 0) {
+ this.offset = this.markedOffset;
+ this.markedOffset = -1;
+ } else {
+ this.offset = 0;
+ }
+ return this;
+ };
+ /**
+ * Resizes this ByteBuffer to be backed by a buffer of at least the given capacity. Will do nothing if already that
+ * large or larger.
+ * @param {number} capacity Capacity required
+ * @returns {!ByteBuffer} this
+ * @throws {TypeError} If `capacity` is not a number
+ * @throws {RangeError} If `capacity < 0`
+ * @expose
+ */
+ ByteBufferPrototype.resize = function(capacity) {
+ if (!this.noAssert) {
+ if (typeof capacity !== 'number' || capacity % 1 !== 0)
+ throw TypeError("Illegal capacity: "+capacity+" (not an integer)");
+ capacity |= 0;
+ if (capacity < 0)
+ throw RangeError("Illegal capacity: 0 <= "+capacity);
+ }
+ if (this.buffer.byteLength < capacity) {
+ var buffer = new ArrayBuffer(capacity);
+ new Uint8Array(buffer).set(new Uint8Array(this.buffer));
+ this.buffer = buffer;
+ this.view = new DataView(buffer);
+ }
+ return this;
+ };
+ /**
+ * Reverses this ByteBuffer's contents.
+ * @param {number=} begin Offset to start at, defaults to {@link ByteBuffer#offset}
+ * @param {number=} end Offset to end at, defaults to {@link ByteBuffer#limit}
+ * @returns {!ByteBuffer} this
+ * @expose
+ */
+ ByteBufferPrototype.reverse = function(begin, end) {
+ if (typeof begin === 'undefined') begin = this.offset;
+ if (typeof end === 'undefined') end = this.limit;
+ if (!this.noAssert) {
+ if (typeof begin !== 'number' || begin % 1 !== 0)
+ throw TypeError("Illegal begin: Not an integer");
+ begin >>>= 0;
+ if (typeof end !== 'number' || end % 1 !== 0)
+ throw TypeError("Illegal end: Not an integer");
+ end >>>= 0;
+ if (begin < 0 || begin > end || end > this.buffer.byteLength)
+ throw RangeError("Illegal range: 0 <= "+begin+" <= "+end+" <= "+this.buffer.byteLength);
+ }
+ if (begin === end)
+ return this; // Nothing to reverse
+ Array.prototype.reverse.call(new Uint8Array(this.buffer).subarray(begin, end));
+ this.view = new DataView(this.buffer); // FIXME: Why exactly is this necessary?
+ return this;
+ };
+ /**
+ * Skips the next `length` bytes. This will just advance
+ * @param {number} length Number of bytes to skip. May also be negative to move the offset back.
+ * @returns {!ByteBuffer} this
+ * @expose
+ */
+ ByteBufferPrototype.skip = function(length) {
+ if (!this.noAssert) {
+ if (typeof length !== 'number' || length % 1 !== 0)
+ throw TypeError("Illegal length: "+length+" (not an integer)");
+ length |= 0;
+ }
+ var offset = this.offset + length;
+ if (!this.noAssert) {
+ if (offset < 0 || offset > this.buffer.byteLength)
+ throw RangeError("Illegal length: 0 <= "+this.offset+" + "+length+" <= "+this.buffer.byteLength);
+ }
+ this.offset = offset;
+ return this;
+ };
+
+ /**
+ * Slices this ByteBuffer by creating a cloned instance with `offset = begin` and `limit = end`.
+ * @param {number=} begin Begin offset, defaults to {@link ByteBuffer#offset}.
+ * @param {number=} end End offset, defaults to {@link ByteBuffer#limit}.
+ * @returns {!ByteBuffer} Clone of this ByteBuffer with slicing applied, backed by the same {@link ByteBuffer#buffer}
+ * @expose
+ */
+ ByteBufferPrototype.slice = function(begin, end) {
+ if (typeof begin === 'undefined') begin = this.offset;
+ if (typeof end === 'undefined') end = this.limit;
+ if (!this.noAssert) {
+ if (typeof begin !== 'number' || begin % 1 !== 0)
+ throw TypeError("Illegal begin: Not an integer");
+ begin >>>= 0;
+ if (typeof end !== 'number' || end % 1 !== 0)
+ throw TypeError("Illegal end: Not an integer");
+ end >>>= 0;
+ if (begin < 0 || begin > end || end > this.buffer.byteLength)
+ throw RangeError("Illegal range: 0 <= "+begin+" <= "+end+" <= "+this.buffer.byteLength);
+ }
+ var bb = this.clone();
+ bb.offset = begin;
+ bb.limit = end;
+ return bb;
+ };
+ /**
+ * Returns a copy of the backing buffer that contains this ByteBuffer's contents. Contents are the bytes between
+ * {@link ByteBuffer#offset} and {@link ByteBuffer#limit}. Will transparently {@link ByteBuffer#flip} this
+ * ByteBuffer if `offset > limit` but the actual offsets remain untouched.
+ * @param {boolean=} forceCopy If `true` returns a copy, otherwise returns a view referencing the same memory if
+ * possible. Defaults to `false`
+ * @returns {!ArrayBuffer} Contents as an ArrayBuffer
+ * @expose
+ */
+ ByteBufferPrototype.toBuffer = function(forceCopy) {
+ var offset = this.offset,
+ limit = this.limit;
+ if (offset > limit) {
+ var t = offset;
+ offset = limit;
+ limit = t;
+ }
+ if (!this.noAssert) {
+ if (typeof offset !== 'number' || offset % 1 !== 0)
+ throw TypeError("Illegal offset: Not an integer");
+ offset >>>= 0;
+ if (typeof limit !== 'number' || limit % 1 !== 0)
+ throw TypeError("Illegal limit: Not an integer");
+ limit >>>= 0;
+ if (offset < 0 || offset > limit || limit > this.buffer.byteLength)
+ throw RangeError("Illegal range: 0 <= "+offset+" <= "+limit+" <= "+this.buffer.byteLength);
+ }
+ // NOTE: It's not possible to have another ArrayBuffer reference the same memory as the backing buffer. This is
+ // possible with Uint8Array#subarray only, but we have to return an ArrayBuffer by contract. So:
+ if (!forceCopy && offset === 0 && limit === this.buffer.byteLength) {
+ return this.buffer;
+ }
+ if (offset === limit) {
+ return EMPTY_BUFFER;
+ }
+ var buffer = new ArrayBuffer(limit - offset);
+ new Uint8Array(buffer).set(new Uint8Array(this.buffer).subarray(offset, limit), 0);
+ return buffer;
+ };
+
+ /**
+ * Returns a raw buffer compacted to contain this ByteBuffer's contents. Contents are the bytes between
+ * {@link ByteBuffer#offset} and {@link ByteBuffer#limit}. Will transparently {@link ByteBuffer#flip} this
+ * ByteBuffer if `offset > limit` but the actual offsets remain untouched. This is an alias of
+ * {@link ByteBuffer#toBuffer}.
+ * @function
+ * @param {boolean=} forceCopy If `true` returns a copy, otherwise returns a view referencing the same memory.
+ * Defaults to `false`
+ * @returns {!ArrayBuffer} Contents as an ArrayBuffer
+ * @expose
+ */
+ ByteBufferPrototype.toArrayBuffer = ByteBufferPrototype.toBuffer;
+
+
+ /**
+ * Converts the ByteBuffer's contents to a string.
+ * @param {string=} encoding Output encoding. Returns an informative string representation if omitted but also allows
+ * direct conversion to "utf8", "hex", "base64" and "binary" encoding. "debug" returns a hex representation with
+ * highlighted offsets.
+ * @param {number=} begin Offset to begin at, defaults to {@link ByteBuffer#offset}
+ * @param {number=} end Offset to end at, defaults to {@link ByteBuffer#limit}
+ * @returns {string} String representation
+ * @throws {Error} If `encoding` is invalid
+ * @expose
+ */
+ ByteBufferPrototype.toString = function(encoding, begin, end) {
+ if (typeof encoding === 'undefined')
+ return "ByteBufferAB(offset="+this.offset+",markedOffset="+this.markedOffset+",limit="+this.limit+",capacity="+this.capacity()+")";
+ if (typeof encoding === 'number')
+ encoding = "utf8",
+ begin = encoding,
+ end = begin;
+ switch (encoding) {
+ case "utf8":
+ return this.toUTF8(begin, end);
+ case "base64":
+ return this.toBase64(begin, end);
+ case "hex":
+ return this.toHex(begin, end);
+ case "binary":
+ return this.toBinary(begin, end);
+ case "debug":
+ return this.toDebug();
+ case "columns":
+ return this.toColumns();
+ default:
+ throw Error("Unsupported encoding: "+encoding);
+ }
+ };
+
+ // lxiv-embeddable
+
+ /**
+ * lxiv-embeddable (c) 2014 Daniel Wirtz
+ * Released under the Apache License, Version 2.0
+ * see: https://github.com/dcodeIO/lxiv for details
+ */
+ var lxiv = function() {
+ "use strict";
+
+ /**
+ * lxiv namespace.
+ * @type {!Object.}
+ * @exports lxiv
+ */
+ var lxiv = {};
+
+ /**
+ * Character codes for output.
+ * @type {!Array.}
+ * @inner
+ */
+ var aout = [
+ 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80,
+ 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 97, 98, 99, 100, 101, 102,
+ 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118,
+ 119, 120, 121, 122, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 43, 47
+ ];
+
+ /**
+ * Character codes for input.
+ * @type {!Array.}
+ * @inner
+ */
+ var ain = [];
+ for (var i=0, k=aout.length; i>2)&0x3f]);
+ t = (b&0x3)<<4;
+ if ((b = src()) !== null) {
+ t |= (b>>4)&0xf;
+ dst(aout[(t|((b>>4)&0xf))&0x3f]);
+ t = (b&0xf)<<2;
+ if ((b = src()) !== null)
+ dst(aout[(t|((b>>6)&0x3))&0x3f]),
+ dst(aout[b&0x3f]);
+ else
+ dst(aout[t&0x3f]),
+ dst(61);
+ } else
+ dst(aout[t&0x3f]),
+ dst(61),
+ dst(61);
+ }
+ };
+
+ /**
+ * Decodes base64 char codes to bytes.
+ * @param {!function():number|null} src Characters source as a function returning the next char code respectively
+ * `null` if there are no more characters left.
+ * @param {!function(number)} dst Bytes destination as a function successively called with the next byte.
+ * @throws {Error} If a character code is invalid
+ */
+ lxiv.decode = function(src, dst) {
+ var c, t1, t2;
+ function fail(c) {
+ throw Error("Illegal character code: "+c);
+ }
+ while ((c = src()) !== null) {
+ t1 = ain[c];
+ if (typeof t1 === 'undefined') fail(c);
+ if ((c = src()) !== null) {
+ t2 = ain[c];
+ if (typeof t2 === 'undefined') fail(c);
+ dst((t1<<2)>>>0|(t2&0x30)>>4);
+ if ((c = src()) !== null) {
+ t1 = ain[c];
+ if (typeof t1 === 'undefined')
+ if (c === 61) break; else fail(c);
+ dst(((t2&0xf)<<4)>>>0|(t1&0x3c)>>2);
+ if ((c = src()) !== null) {
+ t2 = ain[c];
+ if (typeof t2 === 'undefined')
+ if (c === 61) break; else fail(c);
+ dst(((t1&0x3)<<6)>>>0|t2);
+ }
+ }
+ }
+ }
+ };
+
+ /**
+ * Tests if a string is valid base64.
+ * @param {string} str String to test
+ * @returns {boolean} `true` if valid, otherwise `false`
+ */
+ lxiv.test = function(str) {
+ return /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/.test(str);
+ };
+
+ return lxiv;
+ }();
+
+ // encodings/base64
+
+ /**
+ * Encodes this ByteBuffer's contents to a base64 encoded string.
+ * @param {number=} begin Offset to begin at, defaults to {@link ByteBuffer#offset}.
+ * @param {number=} end Offset to end at, defaults to {@link ByteBuffer#limit}.
+ * @returns {string} Base64 encoded string
+ * @expose
+ */
+ ByteBufferPrototype.toBase64 = function(begin, end) {
+ if (typeof begin === 'undefined')
+ begin = this.offset;
+ if (typeof end === 'undefined')
+ end = this.limit;
+ if (!this.noAssert) {
+ if (typeof begin !== 'number' || begin % 1 !== 0)
+ throw TypeError("Illegal begin: Not an integer");
+ begin >>>= 0;
+ if (typeof end !== 'number' || end % 1 !== 0)
+ throw TypeError("Illegal end: Not an integer");
+ end >>>= 0;
+ if (begin < 0 || begin > end || end > this.buffer.byteLength)
+ throw RangeError("Illegal range: 0 <= "+begin+" <= "+end+" <= "+this.buffer.byteLength);
+ }
+ var sd; lxiv.encode(function() {
+ return begin < end ? this.view.getUint8(begin++) : null;
+ }.bind(this), sd = stringDestination());
+ return sd();
+ };
+
+ /**
+ * Decodes a base64 encoded string to a ByteBuffer.
+ * @param {string} str String to decode
+ * @param {boolean=} littleEndian Whether to use little or big endian byte order. Defaults to
+ * {@link ByteBuffer.DEFAULT_ENDIAN}.
+ * @param {boolean=} noAssert Whether to skip assertions of offsets and values. Defaults to
+ * {@link ByteBuffer.DEFAULT_NOASSERT}.
+ * @returns {!ByteBuffer} ByteBuffer
+ * @expose
+ */
+ ByteBuffer.fromBase64 = function(str, littleEndian, noAssert) {
+ if (!noAssert) {
+ if (typeof str !== 'string')
+ throw TypeError("Illegal str: Not a string");
+ if (str.length % 4 !== 0)
+ throw TypeError("Illegal str: Length not a multiple of 4");
+ }
+ var bb = new ByteBuffer(str.length/4*3, littleEndian, noAssert),
+ i = 0;
+ lxiv.decode(stringSource(str), function(b) {
+ bb.view.setUint8(i++, b);
+ });
+ bb.limit = i;
+ return bb;
+ };
+
+ /**
+ * Encodes a binary string to base64 like `window.btoa` does.
+ * @param {string} str Binary string
+ * @returns {string} Base64 encoded string
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/Window.btoa
+ * @expose
+ */
+ ByteBuffer.btoa = function(str) {
+ return ByteBuffer.fromBinary(str).toBase64();
+ };
+
+ /**
+ * Decodes a base64 encoded string to binary like `window.atob` does.
+ * @param {string} b64 Base64 encoded string
+ * @returns {string} Binary string
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/Window.atob
+ * @expose
+ */
+ ByteBuffer.atob = function(b64) {
+ return ByteBuffer.fromBase64(b64).toBinary();
+ };
+
+ // encodings/binary
+
+ /**
+ * Encodes this ByteBuffer to a binary encoded string, that is using only characters 0x00-0xFF as bytes.
+ * @param {number=} begin Offset to begin at. Defaults to {@link ByteBuffer#offset}.
+ * @param {number=} end Offset to end at. Defaults to {@link ByteBuffer#limit}.
+ * @returns {string} Binary encoded string
+ * @throws {RangeError} If `offset > limit`
+ * @expose
+ */
+ ByteBufferPrototype.toBinary = function(begin, end) {
+ begin = typeof begin === 'undefined' ? this.offset : begin;
+ end = typeof end === 'undefined' ? this.limit : end;
+ if (!this.noAssert) {
+ if (typeof begin !== 'number' || begin % 1 !== 0)
+ throw TypeError("Illegal begin: Not an integer");
+ begin >>>= 0;
+ if (typeof end !== 'number' || end % 1 !== 0)
+ throw TypeError("Illegal end: Not an integer");
+ end >>>= 0;
+ if (begin < 0 || begin > end || end > this.buffer.byteLength)
+ throw RangeError("Illegal range: 0 <= "+begin+" <= "+end+" <= "+this.buffer.byteLength);
+ }
+ if (begin === end)
+ return "";
+ var cc = [], pt = [];
+ while (begin < end) {
+ cc.push(this.view.getUint8(begin++));
+ if (cc.length >= 1024)
+ pt.push(String.fromCharCode.apply(String, cc)),
+ cc = [];
+ }
+ return pt.join('') + String.fromCharCode.apply(String, cc);
+ };
+
+ /**
+ * Decodes a binary encoded string, that is using only characters 0x00-0xFF as bytes, to a ByteBuffer.
+ * @param {string} str String to decode
+ * @param {boolean=} littleEndian Whether to use little or big endian byte order. Defaults to
+ * {@link ByteBuffer.DEFAULT_ENDIAN}.
+ * @param {boolean=} noAssert Whether to skip assertions of offsets and values. Defaults to
+ * {@link ByteBuffer.DEFAULT_NOASSERT}.
+ * @returns {!ByteBuffer} ByteBuffer
+ * @expose
+ */
+ ByteBuffer.fromBinary = function(str, littleEndian, noAssert) {
+ if (!noAssert) {
+ if (typeof str !== 'string')
+ throw TypeError("Illegal str: Not a string");
+ }
+ var i = 0, k = str.length, charCode,
+ bb = new ByteBuffer(k, littleEndian, noAssert);
+ while (i 255)
+ throw RangeError("Illegal charCode at "+i+": 0 <= "+charCode+" <= 255");
+ bb.view.setUint8(i++, charCode);
+ }
+ bb.limit = k;
+ return bb;
+ };
+
+ // encodings/debug
+
+ /**
+ * Encodes this ByteBuffer to a hex encoded string with marked offsets. Offset symbols are:
+ * * `<` : offset,
+ * * `'` : markedOffset,
+ * * `>` : limit,
+ * * `|` : offset and limit,
+ * * `[` : offset and markedOffset,
+ * * `]` : markedOffset and limit,
+ * * `!` : offset, markedOffset and limit
+ * @param {boolean=} columns If `true` returns two columns hex + ascii, defaults to `false`
+ * @returns {string|!Array.} Debug string or array of lines if `asArray = true`
+ * @expose
+ * @example `>00'01 02<03` contains four bytes with `limit=0, markedOffset=1, offset=3`
+ * @example `00[01 02 03>` contains four bytes with `offset=markedOffset=1, limit=4`
+ * @example `00|01 02 03` contains four bytes with `offset=limit=1, markedOffset=-1`
+ * @example `|` contains zero bytes with `offset=limit=0, markedOffset=-1`
+ */
+ ByteBufferPrototype.toDebug = function(columns) {
+ var i = -1,
+ k = this.buffer.byteLength,
+ b,
+ hex = "",
+ asc = "",
+ out = "";
+ while (i 32 && b < 127 ? String.fromCharCode(b) : '.';
+ }
+ }
+ ++i;
+ if (columns) {
+ if (i > 0 && i % 16 === 0 && i !== k) {
+ while (hex.length < 3*16+3) hex += " ";
+ out += hex+asc+"\n";
+ hex = asc = "";
+ }
+ }
+ if (i === this.offset && i === this.limit)
+ hex += i === this.markedOffset ? "!" : "|";
+ else if (i === this.offset)
+ hex += i === this.markedOffset ? "[" : "<";
+ else if (i === this.limit)
+ hex += i === this.markedOffset ? "]" : ">";
+ else
+ hex += i === this.markedOffset ? "'" : (columns || (i !== 0 && i !== k) ? " " : "");
+ }
+ if (columns && hex !== " ") {
+ while (hex.length < 3*16+3) hex += " ";
+ out += hex+asc+"\n";
+ }
+ return columns ? out : hex;
+ };
+
+ /**
+ * Decodes a hex encoded string with marked offsets to a ByteBuffer.
+ * @param {string} str Debug string to decode (not be generated with `columns = true`)
+ * @param {boolean=} littleEndian Whether to use little or big endian byte order. Defaults to
+ * {@link ByteBuffer.DEFAULT_ENDIAN}.
+ * @param {boolean=} noAssert Whether to skip assertions of offsets and values. Defaults to
+ * {@link ByteBuffer.DEFAULT_NOASSERT}.
+ * @returns {!ByteBuffer} ByteBuffer
+ * @expose
+ * @see ByteBuffer#toDebug
+ */
+ ByteBuffer.fromDebug = function(str, littleEndian, noAssert) {
+ var k = str.length,
+ bb = new ByteBuffer(((k+1)/3)|0, littleEndian, noAssert);
+ var i = 0, j = 0, ch, b,
+ rs = false, // Require symbol next
+ ho = false, hm = false, hl = false, // Already has offset, markedOffset, limit?
+ fail = false;
+ while (i':
+ if (!noAssert) {
+ if (hl) {
+ fail = true; break;
+ }
+ hl = true;
+ }
+ bb.limit = j;
+ rs = false;
+ break;
+ case "'":
+ if (!noAssert) {
+ if (hm) {
+ fail = true; break;
+ }
+ hm = true;
+ }
+ bb.markedOffset = j;
+ rs = false;
+ break;
+ case ' ':
+ rs = false;
+ break;
+ default:
+ if (!noAssert) {
+ if (rs) {
+ fail = true; break;
+ }
+ }
+ b = parseInt(ch+str.charAt(i++), 16);
+ if (!noAssert) {
+ if (isNaN(b) || b < 0 || b > 255)
+ throw TypeError("Illegal str: Not a debug encoded string");
+ }
+ bb.view.setUint8(j++, b);
+ rs = true;
+ }
+ if (fail)
+ throw TypeError("Illegal str: Invalid symbol at "+i);
+ }
+ if (!noAssert) {
+ if (!ho || !hl)
+ throw TypeError("Illegal str: Missing offset or limit");
+ if (j>>= 0;
+ if (typeof end !== 'number' || end % 1 !== 0)
+ throw TypeError("Illegal end: Not an integer");
+ end >>>= 0;
+ if (begin < 0 || begin > end || end > this.buffer.byteLength)
+ throw RangeError("Illegal range: 0 <= "+begin+" <= "+end+" <= "+this.buffer.byteLength);
+ }
+ var out = new Array(end - begin),
+ b;
+ while (begin < end) {
+ b = this.view.getUint8(begin++);
+ if (b < 0x10)
+ out.push("0", b.toString(16));
+ else out.push(b.toString(16));
+ }
+ return out.join('');
+ };
+
+ /**
+ * Decodes a hex encoded string to a ByteBuffer.
+ * @param {string} str String to decode
+ * @param {boolean=} littleEndian Whether to use little or big endian byte order. Defaults to
+ * {@link ByteBuffer.DEFAULT_ENDIAN}.
+ * @param {boolean=} noAssert Whether to skip assertions of offsets and values. Defaults to
+ * {@link ByteBuffer.DEFAULT_NOASSERT}.
+ * @returns {!ByteBuffer} ByteBuffer
+ * @expose
+ */
+ ByteBuffer.fromHex = function(str, littleEndian, noAssert) {
+ if (!noAssert) {
+ if (typeof str !== 'string')
+ throw TypeError("Illegal str: Not a string");
+ if (str.length % 2 !== 0)
+ throw TypeError("Illegal str: Length not a multiple of 2");
+ }
+ var k = str.length,
+ bb = new ByteBuffer((k / 2) | 0, littleEndian),
+ b;
+ for (var i=0, j=0; i 255)
+ throw TypeError("Illegal str: Contains non-hex characters");
+ bb.view.setUint8(j++, b);
+ }
+ bb.limit = j;
+ return bb;
+ };
+
+ // utfx-embeddable
+
+ /**
+ * utfx-embeddable (c) 2014 Daniel Wirtz
+ * Released under the Apache License, Version 2.0
+ * see: https://github.com/dcodeIO/utfx for details
+ */
+ var utfx = function() {
+ "use strict";
+
+ /**
+ * utfx namespace.
+ * @inner
+ * @type {!Object.}
+ */
+ var utfx = {};
+
+ /**
+ * Maximum valid code point.
+ * @type {number}
+ * @const
+ */
+ utfx.MAX_CODEPOINT = 0x10FFFF;
+
+ /**
+ * Encodes UTF8 code points to UTF8 bytes.
+ * @param {(!function():number|null) | number} src Code points source, either as a function returning the next code point
+ * respectively `null` if there are no more code points left or a single numeric code point.
+ * @param {!function(number)} dst Bytes destination as a function successively called with the next byte
+ */
+ utfx.encodeUTF8 = function(src, dst) {
+ var cp = null;
+ if (typeof src === 'number')
+ cp = src,
+ src = function() { return null; };
+ while (cp !== null || (cp = src()) !== null) {
+ if (cp < 0x80)
+ dst(cp&0x7F);
+ else if (cp < 0x800)
+ dst(((cp>>6)&0x1F)|0xC0),
+ dst((cp&0x3F)|0x80);
+ else if (cp < 0x10000)
+ dst(((cp>>12)&0x0F)|0xE0),
+ dst(((cp>>6)&0x3F)|0x80),
+ dst((cp&0x3F)|0x80);
+ else
+ dst(((cp>>18)&0x07)|0xF0),
+ dst(((cp>>12)&0x3F)|0x80),
+ dst(((cp>>6)&0x3F)|0x80),
+ dst((cp&0x3F)|0x80);
+ cp = null;
+ }
+ };
+
+ /**
+ * Decodes UTF8 bytes to UTF8 code points.
+ * @param {!function():number|null} src Bytes source as a function returning the next byte respectively `null` if there
+ * are no more bytes left.
+ * @param {!function(number)} dst Code points destination as a function successively called with each decoded code point.
+ * @throws {RangeError} If a starting byte is invalid in UTF8
+ * @throws {Error} If the last sequence is truncated. Has an array property `bytes` holding the
+ * remaining bytes.
+ */
+ utfx.decodeUTF8 = function(src, dst) {
+ var a, b, c, d, fail = function(b) {
+ b = b.slice(0, b.indexOf(null));
+ var err = Error(b.toString());
+ err.name = "TruncatedError";
+ err['bytes'] = b;
+ throw err;
+ };
+ while ((a = src()) !== null) {
+ if ((a&0x80) === 0)
+ dst(a);
+ else if ((a&0xE0) === 0xC0)
+ ((b = src()) === null) && fail([a, b]),
+ dst(((a&0x1F)<<6) | (b&0x3F));
+ else if ((a&0xF0) === 0xE0)
+ ((b=src()) === null || (c=src()) === null) && fail([a, b, c]),
+ dst(((a&0x0F)<<12) | ((b&0x3F)<<6) | (c&0x3F));
+ else if ((a&0xF8) === 0xF0)
+ ((b=src()) === null || (c=src()) === null || (d=src()) === null) && fail([a, b, c ,d]),
+ dst(((a&0x07)<<18) | ((b&0x3F)<<12) | ((c&0x3F)<<6) | (d&0x3F));
+ else throw RangeError("Illegal starting byte: "+a);
+ }
+ };
+
+ /**
+ * Converts UTF16 characters to UTF8 code points.
+ * @param {!function():number|null} src Characters source as a function returning the next char code respectively
+ * `null` if there are no more characters left.
+ * @param {!function(number)} dst Code points destination as a function successively called with each converted code
+ * point.
+ */
+ utfx.UTF16toUTF8 = function(src, dst) {
+ var c1, c2 = null;
+ while (true) {
+ if ((c1 = c2 !== null ? c2 : src()) === null)
+ break;
+ if (c1 >= 0xD800 && c1 <= 0xDFFF) {
+ if ((c2 = src()) !== null) {
+ if (c2 >= 0xDC00 && c2 <= 0xDFFF) {
+ dst((c1-0xD800)*0x400+c2-0xDC00+0x10000);
+ c2 = null; continue;
+ }
+ }
+ }
+ dst(c1);
+ }
+ if (c2 !== null) dst(c2);
+ };
+
+ /**
+ * Converts UTF8 code points to UTF16 characters.
+ * @param {(!function():number|null) | number} src Code points source, either as a function returning the next code point
+ * respectively `null` if there are no more code points left or a single numeric code point.
+ * @param {!function(number)} dst Characters destination as a function successively called with each converted char code.
+ * @throws {RangeError} If a code point is out of range
+ */
+ utfx.UTF8toUTF16 = function(src, dst) {
+ var cp = null;
+ if (typeof src === 'number')
+ cp = src, src = function() { return null; };
+ while (cp !== null || (cp = src()) !== null) {
+ if (cp <= 0xFFFF)
+ dst(cp);
+ else
+ cp -= 0x10000,
+ dst((cp>>10)+0xD800),
+ dst((cp%0x400)+0xDC00);
+ cp = null;
+ }
+ };
+
+ /**
+ * Converts and encodes UTF16 characters to UTF8 bytes.
+ * @param {!function():number|null} src Characters source as a function returning the next char code respectively `null`
+ * if there are no more characters left.
+ * @param {!function(number)} dst Bytes destination as a function successively called with the next byte.
+ */
+ utfx.encodeUTF16toUTF8 = function(src, dst) {
+ utfx.UTF16toUTF8(src, function(cp) {
+ utfx.encodeUTF8(cp, dst);
+ });
+ };
+
+ /**
+ * Decodes and converts UTF8 bytes to UTF16 characters.
+ * @param {!function():number|null} src Bytes source as a function returning the next byte respectively `null` if there
+ * are no more bytes left.
+ * @param {!function(number)} dst Characters destination as a function successively called with each converted char code.
+ * @throws {RangeError} If a starting byte is invalid in UTF8
+ * @throws {Error} If the last sequence is truncated. Has an array property `bytes` holding the remaining bytes.
+ */
+ utfx.decodeUTF8toUTF16 = function(src, dst) {
+ utfx.decodeUTF8(src, function(cp) {
+ utfx.UTF8toUTF16(cp, dst);
+ });
+ };
+
+ /**
+ * Calculates the byte length of an UTF8 code point.
+ * @param {number} cp UTF8 code point
+ * @returns {number} Byte length
+ */
+ utfx.calculateCodePoint = function(cp) {
+ return (cp < 0x80) ? 1 : (cp < 0x800) ? 2 : (cp < 0x10000) ? 3 : 4;
+ };
+
+ /**
+ * Calculates the number of UTF8 bytes required to store UTF8 code points.
+ * @param {(!function():number|null)} src Code points source as a function returning the next code point respectively
+ * `null` if there are no more code points left.
+ * @returns {number} The number of UTF8 bytes required
+ */
+ utfx.calculateUTF8 = function(src) {
+ var cp, l=0;
+ while ((cp = src()) !== null)
+ l += utfx.calculateCodePoint(cp);
+ return l;
+ };
+
+ /**
+ * Calculates the number of UTF8 code points respectively UTF8 bytes required to store UTF16 char codes.
+ * @param {(!function():number|null)} src Characters source as a function returning the next char code respectively
+ * `null` if there are no more characters left.
+ * @returns {!Array.} The number of UTF8 code points at index 0 and the number of UTF8 bytes required at index 1.
+ */
+ utfx.calculateUTF16asUTF8 = function(src) {
+ var n=0, l=0;
+ utfx.UTF16toUTF8(src, function(cp) {
+ ++n; l += utfx.calculateCodePoint(cp);
+ });
+ return [n,l];
+ };
+
+ return utfx;
+ }();
+
+ // encodings/utf8
+
+ /**
+ * Encodes this ByteBuffer's contents between {@link ByteBuffer#offset} and {@link ByteBuffer#limit} to an UTF8 encoded
+ * string.
+ * @returns {string} Hex encoded string
+ * @throws {RangeError} If `offset > limit`
+ * @expose
+ */
+ ByteBufferPrototype.toUTF8 = function(begin, end) {
+ if (typeof begin === 'undefined') begin = this.offset;
+ if (typeof end === 'undefined') end = this.limit;
+ if (!this.noAssert) {
+ if (typeof begin !== 'number' || begin % 1 !== 0)
+ throw TypeError("Illegal begin: Not an integer");
+ begin >>>= 0;
+ if (typeof end !== 'number' || end % 1 !== 0)
+ throw TypeError("Illegal end: Not an integer");
+ end >>>= 0;
+ if (begin < 0 || begin > end || end > this.buffer.byteLength)
+ throw RangeError("Illegal range: 0 <= "+begin+" <= "+end+" <= "+this.buffer.byteLength);
+ }
+ var sd; try {
+ utfx.decodeUTF8toUTF16(function() {
+ return begin < end ? this.view.getUint8(begin++) : null;
+ }.bind(this), sd = stringDestination());
+ } catch (e) {
+ if (begin !== end)
+ throw RangeError("Illegal range: Truncated data, "+begin+" != "+end);
+ }
+ return sd();
+ };
+
+ /**
+ * Decodes an UTF8 encoded string to a ByteBuffer.
+ * @param {string} str String to decode
+ * @param {boolean=} littleEndian Whether to use little or big endian byte order. Defaults to
+ * {@link ByteBuffer.DEFAULT_ENDIAN}.
+ * @param {boolean=} noAssert Whether to skip assertions of offsets and values. Defaults to
+ * {@link ByteBuffer.DEFAULT_NOASSERT}.
+ * @returns {!ByteBuffer} ByteBuffer
+ * @expose
+ */
+ ByteBuffer.fromUTF8 = function(str, littleEndian, noAssert) {
+ if (!noAssert)
+ if (typeof str !== 'string')
+ throw TypeError("Illegal str: Not a string");
+ var bb = new ByteBuffer(utfx.calculateUTF16asUTF8(stringSource(str), true)[1], littleEndian, noAssert),
+ i = 0;
+ utfx.encodeUTF16toUTF8(stringSource(str), function(b) {
+ bb.view.setUint8(i++, b);
+ });
+ bb.limit = i;
+ return bb;
+ };
+
+
+ return ByteBuffer;
+ }
+
+ /* CommonJS */ if (typeof require === 'function' && typeof module === 'object' && module && typeof exports === 'object' && exports)
+ module['exports'] = (function() {
+ var Long; try { Long = require("long"); } catch (e) {}
+ return loadByteBuffer(Long);
+ })();
+ /* AMD */ else if (typeof define === 'function' && define["amd"])
+ define("ByteBuffer", ["Long"], function(Long) { return loadByteBuffer(Long); });
+ /* Global */ else
+ (global["dcodeIO"] = global["dcodeIO"] || {})["ByteBuffer"] = loadByteBuffer(global["dcodeIO"]["Long"]);
+
+})(this);
+
+/*
+ Copyright 2013 Daniel Wirtz
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+/**
+ * @license ProtoBuf.js (c) 2013 Daniel Wirtz
+ * Released under the Apache License, Version 2.0
+ * see: https://github.com/dcodeIO/ProtoBuf.js for details
+ */
+(function(global) {
+ "use strict";
+
+ function init(ByteBuffer) {
+
+ /**
+ * The ProtoBuf namespace.
+ * @exports ProtoBuf
+ * @namespace
+ * @expose
+ */
+ var ProtoBuf = {};
+
+ /**
+ * ProtoBuf.js version.
+ * @type {string}
+ * @const
+ * @expose
+ */
+ ProtoBuf.VERSION = "3.8.0";
+
+ /**
+ * Wire types.
+ * @type {Object.}
+ * @const
+ * @expose
+ */
+ ProtoBuf.WIRE_TYPES = {};
+
+ /**
+ * Varint wire type.
+ * @type {number}
+ * @expose
+ */
+ ProtoBuf.WIRE_TYPES.VARINT = 0;
+
+ /**
+ * Fixed 64 bits wire type.
+ * @type {number}
+ * @const
+ * @expose
+ */
+ ProtoBuf.WIRE_TYPES.BITS64 = 1;
+
+ /**
+ * Length delimited wire type.
+ * @type {number}
+ * @const
+ * @expose
+ */
+ ProtoBuf.WIRE_TYPES.LDELIM = 2;
+
+ /**
+ * Start group wire type.
+ * @type {number}
+ * @const
+ * @expose
+ */
+ ProtoBuf.WIRE_TYPES.STARTGROUP = 3;
+
+ /**
+ * End group wire type.
+ * @type {number}
+ * @const
+ * @expose
+ */
+ ProtoBuf.WIRE_TYPES.ENDGROUP = 4;
+
+ /**
+ * Fixed 32 bits wire type.
+ * @type {number}
+ * @const
+ * @expose
+ */
+ ProtoBuf.WIRE_TYPES.BITS32 = 5;
+
+ /**
+ * Packable wire types.
+ * @type {!Array.}
+ * @const
+ * @expose
+ */
+ ProtoBuf.PACKABLE_WIRE_TYPES = [
+ ProtoBuf.WIRE_TYPES.VARINT,
+ ProtoBuf.WIRE_TYPES.BITS64,
+ ProtoBuf.WIRE_TYPES.BITS32
+ ];
+
+ /**
+ * Types.
+ * @dict
+ * @type {Object.}
+ * @const
+ * @expose
+ */
+ ProtoBuf.TYPES = {
+ // According to the protobuf spec.
+ "int32": {
+ name: "int32",
+ wireType: ProtoBuf.WIRE_TYPES.VARINT
+ },
+ "uint32": {
+ name: "uint32",
+ wireType: ProtoBuf.WIRE_TYPES.VARINT
+ },
+ "sint32": {
+ name: "sint32",
+ wireType: ProtoBuf.WIRE_TYPES.VARINT
+ },
+ "int64": {
+ name: "int64",
+ wireType: ProtoBuf.WIRE_TYPES.VARINT
+ },
+ "uint64": {
+ name: "uint64",
+ wireType: ProtoBuf.WIRE_TYPES.VARINT
+ },
+ "sint64": {
+ name: "sint64",
+ wireType: ProtoBuf.WIRE_TYPES.VARINT
+ },
+ "bool": {
+ name: "bool",
+ wireType: ProtoBuf.WIRE_TYPES.VARINT
+ },
+ "double": {
+ name: "double",
+ wireType: ProtoBuf.WIRE_TYPES.BITS64
+ },
+ "string": {
+ name: "string",
+ wireType: ProtoBuf.WIRE_TYPES.LDELIM
+ },
+ "bytes": {
+ name: "bytes",
+ wireType: ProtoBuf.WIRE_TYPES.LDELIM
+ },
+ "fixed32": {
+ name: "fixed32",
+ wireType: ProtoBuf.WIRE_TYPES.BITS32
+ },
+ "sfixed32": {
+ name: "sfixed32",
+ wireType: ProtoBuf.WIRE_TYPES.BITS32
+ },
+ "fixed64": {
+ name: "fixed64",
+ wireType: ProtoBuf.WIRE_TYPES.BITS64
+ },
+ "sfixed64": {
+ name: "sfixed64",
+ wireType: ProtoBuf.WIRE_TYPES.BITS64
+ },
+ "float": {
+ name: "float",
+ wireType: ProtoBuf.WIRE_TYPES.BITS32
+ },
+ "enum": {
+ name: "enum",
+ wireType: ProtoBuf.WIRE_TYPES.VARINT
+ },
+ "message": {
+ name: "message",
+ wireType: ProtoBuf.WIRE_TYPES.LDELIM
+ },
+ "group": {
+ name: "group",
+ wireType: ProtoBuf.WIRE_TYPES.STARTGROUP
+ }
+ };
+
+ /**
+ * Minimum field id.
+ * @type {number}
+ * @const
+ * @expose
+ */
+ ProtoBuf.ID_MIN = 1;
+
+ /**
+ * Maximum field id.
+ * @type {number}
+ * @const
+ * @expose
+ */
+ ProtoBuf.ID_MAX = 0x1FFFFFFF;
+
+ /**
+ * @type {!function(new: ByteBuffer, ...[*])}
+ * @expose
+ */
+ ProtoBuf.ByteBuffer = ByteBuffer;
+
+ /**
+ * @type {?function(new: Long, ...[*])}
+ * @expose
+ */
+ ProtoBuf.Long = ByteBuffer.Long || null;
+
+ /**
+ * If set to `true`, field names will be converted from underscore notation to camel case. Defaults to `false`.
+ * Must be set prior to parsing.
+ * @type {boolean}
+ * @expose
+ */
+ ProtoBuf.convertFieldsToCamelCase = false;
+
+ /**
+ * By default, messages are populated with (setX, set_x) accessors for each field. This can be disabled by
+ * setting this to `false` prior to building messages.
+ * @type {boolean}
+ * @expose
+ */
+ ProtoBuf.populateAccessors = true;
+
+ /**
+ * @alias ProtoBuf.Util
+ * @expose
+ */
+ ProtoBuf.Util = (function() {
+ "use strict";
+
+ // Object.create polyfill
+ // ref: https://developer.mozilla.org/de/docs/JavaScript/Reference/Global_Objects/Object/create
+ if (!Object.create)
+ /** @expose */
+ Object.create = function (o) {
+ if (arguments.length > 1)
+ throw Error('Object.create polyfill only accepts the first parameter.');
+ function F() {}
+ F.prototype = o;
+ return new F();
+ };
+
+ /**
+ * ProtoBuf utilities.
+ * @exports ProtoBuf.Util
+ * @namespace
+ */
+ var Util = {};
+
+ /**
+ * Flag if running in node (fs is available) or not.
+ * @type {boolean}
+ * @const
+ * @expose
+ */
+ Util.IS_NODE = false;
+ try {
+ // There is no reliable way to detect node.js as an environment, so our
+ // best bet is to feature-detect what we actually need.
+ Util.IS_NODE =
+ typeof require === 'function' &&
+ typeof require("fs").readFileSync === 'function' &&
+ typeof require("path").resolve === 'function';
+ } catch (e) {}
+
+ /**
+ * Constructs a XMLHttpRequest object.
+ * @return {XMLHttpRequest}
+ * @throws {Error} If XMLHttpRequest is not supported
+ * @expose
+ */
+ Util.XHR = function() {
+ // No dependencies please, ref: http://www.quirksmode.org/js/xmlhttp.html
+ var XMLHttpFactories = [
+ function () {return new XMLHttpRequest()},
+ function () {return new ActiveXObject("Msxml2.XMLHTTP")},
+ function () {return new ActiveXObject("Msxml3.XMLHTTP")},
+ function () {return new ActiveXObject("Microsoft.XMLHTTP")}
+ ];
+ /** @type {?XMLHttpRequest} */
+ var xhr = null;
+ for (var i=0;i}
+ * @expose
+ */
+ ProtoBuf.Lang = {
+ OPEN: "{",
+ CLOSE: "}",
+ OPTOPEN: "[",
+ OPTCLOSE: "]",
+ OPTEND: ",",
+ EQUAL: "=",
+ END: ";",
+ STRINGOPEN: '"',
+ STRINGCLOSE: '"',
+ STRINGOPEN_SQ: "'",
+ STRINGCLOSE_SQ: "'",
+ COPTOPEN: '(',
+ COPTCLOSE: ')',
+ DELIM: /[\s\{\}=;\[\],'"\(\)]/g,
+ // KEYWORD: /^(?:package|option|import|message|enum|extend|service|syntax|extensions|group)$/,
+ RULE: /^(?:required|optional|repeated)$/,
+ TYPE: /^(?:double|float|int32|uint32|sint32|int64|uint64|sint64|fixed32|sfixed32|fixed64|sfixed64|bool|string|bytes)$/,
+ NAME: /^[a-zA-Z_][a-zA-Z_0-9]*$/,
+ TYPEDEF: /^[a-zA-Z][a-zA-Z_0-9]*$/,
+ TYPEREF: /^(?:\.?[a-zA-Z_][a-zA-Z_0-9]*)+$/,
+ FQTYPEREF: /^(?:\.[a-zA-Z][a-zA-Z_0-9]*)+$/,
+ NUMBER: /^-?(?:[1-9][0-9]*|0|0x[0-9a-fA-F]+|0[0-7]+|([0-9]*\.[0-9]+([Ee][+-]?[0-9]+)?))$/,
+ NUMBER_DEC: /^(?:[1-9][0-9]*|0)$/,
+ NUMBER_HEX: /^0x[0-9a-fA-F]+$/,
+ NUMBER_OCT: /^0[0-7]+$/,
+ NUMBER_FLT: /^[0-9]*\.[0-9]+([Ee][+-]?[0-9]+)?$/,
+ ID: /^(?:[1-9][0-9]*|0|0x[0-9a-fA-F]+|0[0-7]+)$/,
+ NEGID: /^\-?(?:[1-9][0-9]*|0|0x[0-9a-fA-F]+|0[0-7]+)$/,
+ WHITESPACE: /\s/,
+ STRING: /['"]([^'"\\]*(\\.[^"\\]*)*)['"]/g,
+ BOOL: /^(?:true|false)$/i
+ };
+
+ /**
+ * @alias ProtoBuf.DotProto
+ * @expose
+ */
+ ProtoBuf.DotProto = (function(ProtoBuf, Lang) {
+ "use strict";
+
+ /**
+ * Utilities to parse .proto files.
+ * @exports ProtoBuf.DotProto
+ * @namespace
+ */
+ var DotProto = {};
+
+ /**
+ * Constructs a new Tokenizer.
+ * @exports ProtoBuf.DotProto.Tokenizer
+ * @class prototype tokenizer
+ * @param {string} proto Proto to tokenize
+ * @constructor
+ */
+ var Tokenizer = function(proto) {
+
+ /**
+ * Source to parse.
+ * @type {string}
+ * @expose
+ */
+ this.source = ""+proto; // In case it's a buffer
+
+ /**
+ * Current index.
+ * @type {number}
+ * @expose
+ */
+ this.index = 0;
+
+ /**
+ * Current line.
+ * @type {number}
+ * @expose
+ */
+ this.line = 1;
+
+ /**
+ * Stacked values.
+ * @type {Array}
+ * @expose
+ */
+ this.stack = [];
+
+ /**
+ * Whether currently reading a string or not.
+ * @type {boolean}
+ * @expose
+ */
+ this.readingString = false;
+
+ /**
+ * Whatever character ends the string. Either a single or double quote character.
+ * @type {string}
+ * @expose
+ */
+ this.stringEndsWith = Lang.STRINGCLOSE;
+ };
+
+ /**
+ * @alias ProtoBuf.DotProto.Tokenizer.prototype
+ * @inner
+ */
+ var TokenizerPrototype = Tokenizer.prototype;
+
+ /**
+ * Reads a string beginning at the current index.
+ * @return {string} The string
+ * @throws {Error} If it's not a valid string
+ * @private
+ */
+ TokenizerPrototype._readString = function() {
+ Lang.STRING.lastIndex = this.index-1; // Include the open quote
+ var match;
+ if ((match = Lang.STRING.exec(this.source)) !== null) {
+ var s = match[1];
+ this.index = Lang.STRING.lastIndex;
+ this.stack.push(this.stringEndsWith);
+ return s;
+ }
+ throw Error("Unterminated string at line "+this.line+", index "+this.index);
+ };
+
+ /**
+ * Gets the next token and advances by one.
+ * @return {?string} Token or `null` on EOF
+ * @throws {Error} If it's not a valid proto file
+ * @expose
+ */
+ TokenizerPrototype.next = function() {
+ if (this.stack.length > 0)
+ return this.stack.shift();
+ if (this.index >= this.source.length)
+ return null; // No more tokens
+ if (this.readingString) {
+ this.readingString = false;
+ return this._readString();
+ }
+ var repeat, last;
+ do {
+ repeat = false;
+ // Strip white spaces
+ while (Lang.WHITESPACE.test(last = this.source.charAt(this.index))) {
+ this.index++;
+ if (last === "\n")
+ this.line++;
+ if (this.index === this.source.length)
+ return null;
+ }
+ // Strip comments
+ if (this.source.charAt(this.index) === '/') {
+ if (this.source.charAt(++this.index) === '/') { // Single line
+ while (this.source.charAt(this.index) !== "\n") {
+ this.index++;
+ if (this.index == this.source.length)
+ return null;
+ }
+ this.index++;
+ this.line++;
+ repeat = true;
+ } else if (this.source.charAt(this.index) === '*') { /* Block */
+ last = '';
+ while (last+(last=this.source.charAt(this.index)) !== '*/') {
+ this.index++;
+ if (last === "\n")
+ this.line++;
+ if (this.index === this.source.length)
+ return null;
+ }
+ this.index++;
+ repeat = true;
+ } else
+ throw Error("Unterminated comment at line "+this.line+": /"+this.source.charAt(this.index));
+ }
+ } while (repeat);
+ if (this.index === this.source.length) return null;
+
+ // Read the next token
+ var end = this.index;
+ Lang.DELIM.lastIndex = 0;
+ var delim = Lang.DELIM.test(this.source.charAt(end));
+ if (!delim) {
+ ++end;
+ while(end < this.source.length && !Lang.DELIM.test(this.source.charAt(end)))
+ end++;
+ } else
+ ++end;
+ var token = this.source.substring(this.index, this.index = end);
+ if (token === Lang.STRINGOPEN)
+ this.readingString = true,
+ this.stringEndsWith = Lang.STRINGCLOSE;
+ else if (token === Lang.STRINGOPEN_SQ)
+ this.readingString = true,
+ this.stringEndsWith = Lang.STRINGCLOSE_SQ;
+ return token;
+ };
+
+ /**
+ * Peeks for the next token.
+ * @return {?string} Token or `null` on EOF
+ * @throws {Error} If it's not a valid proto file
+ * @expose
+ */
+ TokenizerPrototype.peek = function() {
+ if (this.stack.length === 0) {
+ var token = this.next();
+ if (token === null)
+ return null;
+ this.stack.push(token);
+ }
+ return this.stack[0];
+ };
+
+ /**
+ * Returns a string representation of this object.
+ * @return {string} String representation as of "Tokenizer(index/length)"
+ * @expose
+ */
+ TokenizerPrototype.toString = function() {
+ return "Tokenizer("+this.index+"/"+this.source.length+" at line "+this.line+")";
+ };
+
+ /**
+ * @alias ProtoBuf.DotProto.Tokenizer
+ * @expose
+ */
+ DotProto.Tokenizer = Tokenizer;
+
+ /**
+ * Constructs a new Parser.
+ * @exports ProtoBuf.DotProto.Parser
+ * @class prototype parser
+ * @param {string} proto Protocol source
+ * @constructor
+ */
+ var Parser = function(proto) {
+
+ /**
+ * Tokenizer.
+ * @type {ProtoBuf.DotProto.Tokenizer}
+ * @expose
+ */
+ this.tn = new Tokenizer(proto);
+ };
+
+ /**
+ * @alias ProtoBuf.DotProto.Parser.prototype
+ * @inner
+ */
+ var ParserPrototype = Parser.prototype;
+
+ /**
+ * Runs the parser.
+ * @return {{package: string|null, messages: Array.