1572 lines
		
	
	
		
			40 KiB
		
	
	
	
		
			HTML
		
	
	
	
			
		
		
	
	
			1572 lines
		
	
	
		
			40 KiB
		
	
	
	
		
			HTML
		
	
	
	
<script>
 | 
						|
	/*! binary.js build:0.2.2, development. Copyright(c) 2012 Eric Zhang <eric@ericzhang.com> MIT Licensed */
 | 
						|
(function(exports){
 | 
						|
/*! binarypack.js build:0.0.9, production. Copyright(c) 2012 Eric Zhang <eric@ericzhang.com> MIT Licensed */(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
 | 
						|
var BufferBuilder = require('./bufferbuilder').BufferBuilder;
 | 
						|
var binaryFeatures = require('./bufferbuilder').binaryFeatures;
 | 
						|
 | 
						|
var BinaryPack = {
 | 
						|
  unpack: function(data){
 | 
						|
    var unpacker = new Unpacker(data);
 | 
						|
    return unpacker.unpack();
 | 
						|
  },
 | 
						|
  pack: function(data){
 | 
						|
    var packer = new Packer();
 | 
						|
    packer.pack(data);
 | 
						|
    var buffer = packer.getBuffer();
 | 
						|
    return buffer;
 | 
						|
  }
 | 
						|
};
 | 
						|
 | 
						|
module.exports = BinaryPack;
 | 
						|
 | 
						|
function Unpacker (data){
 | 
						|
  // Data is ArrayBuffer
 | 
						|
  this.index = 0;
 | 
						|
  this.dataBuffer = data;
 | 
						|
  this.dataView = new Uint8Array(this.dataBuffer);
 | 
						|
  this.length = this.dataBuffer.byteLength;
 | 
						|
}
 | 
						|
 | 
						|
Unpacker.prototype.unpack = function(){
 | 
						|
  var type = this.unpack_uint8();
 | 
						|
  if (type < 0x80){
 | 
						|
    var positive_fixnum = type;
 | 
						|
    return positive_fixnum;
 | 
						|
  } else if ((type ^ 0xe0) < 0x20){
 | 
						|
    var negative_fixnum = (type ^ 0xe0) - 0x20;
 | 
						|
    return negative_fixnum;
 | 
						|
  }
 | 
						|
  var size;
 | 
						|
  if ((size = type ^ 0xa0) <= 0x0f){
 | 
						|
    return this.unpack_raw(size);
 | 
						|
  } else if ((size = type ^ 0xb0) <= 0x0f){
 | 
						|
    return this.unpack_string(size);
 | 
						|
  } else if ((size = type ^ 0x90) <= 0x0f){
 | 
						|
    return this.unpack_array(size);
 | 
						|
  } else if ((size = type ^ 0x80) <= 0x0f){
 | 
						|
    return this.unpack_map(size);
 | 
						|
  }
 | 
						|
  switch(type){
 | 
						|
    case 0xc0:
 | 
						|
      return null;
 | 
						|
    case 0xc1:
 | 
						|
      return undefined;
 | 
						|
    case 0xc2:
 | 
						|
      return false;
 | 
						|
    case 0xc3:
 | 
						|
      return true;
 | 
						|
    case 0xca:
 | 
						|
      return this.unpack_float();
 | 
						|
    case 0xcb:
 | 
						|
      return this.unpack_double();
 | 
						|
    case 0xcc:
 | 
						|
      return this.unpack_uint8();
 | 
						|
    case 0xcd:
 | 
						|
      return this.unpack_uint16();
 | 
						|
    case 0xce:
 | 
						|
      return this.unpack_uint32();
 | 
						|
    case 0xcf:
 | 
						|
      return this.unpack_uint64();
 | 
						|
    case 0xd0:
 | 
						|
      return this.unpack_int8();
 | 
						|
    case 0xd1:
 | 
						|
      return this.unpack_int16();
 | 
						|
    case 0xd2:
 | 
						|
      return this.unpack_int32();
 | 
						|
    case 0xd3:
 | 
						|
      return this.unpack_int64();
 | 
						|
    case 0xd4:
 | 
						|
      return undefined;
 | 
						|
    case 0xd5:
 | 
						|
      return undefined;
 | 
						|
    case 0xd6:
 | 
						|
      return undefined;
 | 
						|
    case 0xd7:
 | 
						|
      return undefined;
 | 
						|
    case 0xd8:
 | 
						|
      size = this.unpack_uint16();
 | 
						|
      return this.unpack_string(size);
 | 
						|
    case 0xd9:
 | 
						|
      size = this.unpack_uint32();
 | 
						|
      return this.unpack_string(size);
 | 
						|
    case 0xda:
 | 
						|
      size = this.unpack_uint16();
 | 
						|
      return this.unpack_raw(size);
 | 
						|
    case 0xdb:
 | 
						|
      size = this.unpack_uint32();
 | 
						|
      return this.unpack_raw(size);
 | 
						|
    case 0xdc:
 | 
						|
      size = this.unpack_uint16();
 | 
						|
      return this.unpack_array(size);
 | 
						|
    case 0xdd:
 | 
						|
      size = this.unpack_uint32();
 | 
						|
      return this.unpack_array(size);
 | 
						|
    case 0xde:
 | 
						|
      size = this.unpack_uint16();
 | 
						|
      return this.unpack_map(size);
 | 
						|
    case 0xdf:
 | 
						|
      size = this.unpack_uint32();
 | 
						|
      return this.unpack_map(size);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
Unpacker.prototype.unpack_uint8 = function(){
 | 
						|
  var byte = this.dataView[this.index] & 0xff;
 | 
						|
  this.index++;
 | 
						|
  return byte;
 | 
						|
};
 | 
						|
 | 
						|
Unpacker.prototype.unpack_uint16 = function(){
 | 
						|
  var bytes = this.read(2);
 | 
						|
  var uint16 =
 | 
						|
    ((bytes[0] & 0xff) * 256) + (bytes[1] & 0xff);
 | 
						|
  this.index += 2;
 | 
						|
  return uint16;
 | 
						|
}
 | 
						|
 | 
						|
Unpacker.prototype.unpack_uint32 = function(){
 | 
						|
  var bytes = this.read(4);
 | 
						|
  var uint32 =
 | 
						|
     ((bytes[0]  * 256 +
 | 
						|
       bytes[1]) * 256 +
 | 
						|
       bytes[2]) * 256 +
 | 
						|
       bytes[3];
 | 
						|
  this.index += 4;
 | 
						|
  return uint32;
 | 
						|
}
 | 
						|
 | 
						|
Unpacker.prototype.unpack_uint64 = function(){
 | 
						|
  var bytes = this.read(8);
 | 
						|
  var uint64 =
 | 
						|
   ((((((bytes[0]  * 256 +
 | 
						|
       bytes[1]) * 256 +
 | 
						|
       bytes[2]) * 256 +
 | 
						|
       bytes[3]) * 256 +
 | 
						|
       bytes[4]) * 256 +
 | 
						|
       bytes[5]) * 256 +
 | 
						|
       bytes[6]) * 256 +
 | 
						|
       bytes[7];
 | 
						|
  this.index += 8;
 | 
						|
  return uint64;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
Unpacker.prototype.unpack_int8 = function(){
 | 
						|
  var uint8 = this.unpack_uint8();
 | 
						|
  return (uint8 < 0x80 ) ? uint8 : uint8 - (1 << 8);
 | 
						|
};
 | 
						|
 | 
						|
Unpacker.prototype.unpack_int16 = function(){
 | 
						|
  var uint16 = this.unpack_uint16();
 | 
						|
  return (uint16 < 0x8000 ) ? uint16 : uint16 - (1 << 16);
 | 
						|
}
 | 
						|
 | 
						|
Unpacker.prototype.unpack_int32 = function(){
 | 
						|
  var uint32 = this.unpack_uint32();
 | 
						|
  return (uint32 < Math.pow(2, 31) ) ? uint32 :
 | 
						|
    uint32 - Math.pow(2, 32);
 | 
						|
}
 | 
						|
 | 
						|
Unpacker.prototype.unpack_int64 = function(){
 | 
						|
  var uint64 = this.unpack_uint64();
 | 
						|
  return (uint64 < Math.pow(2, 63) ) ? uint64 :
 | 
						|
    uint64 - Math.pow(2, 64);
 | 
						|
}
 | 
						|
 | 
						|
Unpacker.prototype.unpack_raw = function(size){
 | 
						|
  if ( this.length < this.index + size){
 | 
						|
    throw new Error('BinaryPackFailure: index is out of range'
 | 
						|
      + ' ' + this.index + ' ' + size + ' ' + this.length);
 | 
						|
  }
 | 
						|
  var buf = this.dataBuffer.slice(this.index, this.index + size);
 | 
						|
  this.index += size;
 | 
						|
 | 
						|
    //buf = util.bufferToString(buf);
 | 
						|
 | 
						|
  return buf;
 | 
						|
}
 | 
						|
 | 
						|
Unpacker.prototype.unpack_string = function(size){
 | 
						|
  var bytes = this.read(size);
 | 
						|
  var i = 0, str = '', c, code;
 | 
						|
  while(i < size){
 | 
						|
    c = bytes[i];
 | 
						|
    if ( c < 128){
 | 
						|
      str += String.fromCharCode(c);
 | 
						|
      i++;
 | 
						|
    } else if ((c ^ 0xc0) < 32){
 | 
						|
      code = ((c ^ 0xc0) << 6) | (bytes[i+1] & 63);
 | 
						|
      str += String.fromCharCode(code);
 | 
						|
      i += 2;
 | 
						|
    } else {
 | 
						|
      code = ((c & 15) << 12) | ((bytes[i+1] & 63) << 6) |
 | 
						|
        (bytes[i+2] & 63);
 | 
						|
      str += String.fromCharCode(code);
 | 
						|
      i += 3;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  this.index += size;
 | 
						|
  return str;
 | 
						|
}
 | 
						|
 | 
						|
Unpacker.prototype.unpack_array = function(size){
 | 
						|
  var objects = new Array(size);
 | 
						|
  for(var i = 0; i < size ; i++){
 | 
						|
    objects[i] = this.unpack();
 | 
						|
  }
 | 
						|
  return objects;
 | 
						|
}
 | 
						|
 | 
						|
Unpacker.prototype.unpack_map = function(size){
 | 
						|
  var map = {};
 | 
						|
  for(var i = 0; i < size ; i++){
 | 
						|
    var key  = this.unpack();
 | 
						|
    var value = this.unpack();
 | 
						|
    map[key] = value;
 | 
						|
  }
 | 
						|
  return map;
 | 
						|
}
 | 
						|
 | 
						|
Unpacker.prototype.unpack_float = function(){
 | 
						|
  var uint32 = this.unpack_uint32();
 | 
						|
  var sign = uint32 >> 31;
 | 
						|
  var exp  = ((uint32 >> 23) & 0xff) - 127;
 | 
						|
  var fraction = ( uint32 & 0x7fffff ) | 0x800000;
 | 
						|
  return (sign == 0 ? 1 : -1) *
 | 
						|
    fraction * Math.pow(2, exp - 23);
 | 
						|
}
 | 
						|
 | 
						|
Unpacker.prototype.unpack_double = function(){
 | 
						|
  var h32 = this.unpack_uint32();
 | 
						|
  var l32 = this.unpack_uint32();
 | 
						|
  var sign = h32 >> 31;
 | 
						|
  var exp  = ((h32 >> 20) & 0x7ff) - 1023;
 | 
						|
  var hfrac = ( h32 & 0xfffff ) | 0x100000;
 | 
						|
  var frac = hfrac * Math.pow(2, exp - 20) +
 | 
						|
    l32   * Math.pow(2, exp - 52);
 | 
						|
  return (sign == 0 ? 1 : -1) * frac;
 | 
						|
}
 | 
						|
 | 
						|
Unpacker.prototype.read = function(length){
 | 
						|
  var j = this.index;
 | 
						|
  if (j + length <= this.length) {
 | 
						|
    return this.dataView.subarray(j, j + length);
 | 
						|
  } else {
 | 
						|
    throw new Error('BinaryPackFailure: read index out of range');
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
function Packer(){
 | 
						|
  this.bufferBuilder = new BufferBuilder();
 | 
						|
}
 | 
						|
 | 
						|
Packer.prototype.getBuffer = function(){
 | 
						|
  return this.bufferBuilder.getBuffer();
 | 
						|
}
 | 
						|
 | 
						|
Packer.prototype.pack = function(value){
 | 
						|
  var type = typeof(value);
 | 
						|
  if (type == 'string'){
 | 
						|
    this.pack_string(value);
 | 
						|
  } else if (type == 'number'){
 | 
						|
    if (Math.floor(value) === value){
 | 
						|
      this.pack_integer(value);
 | 
						|
    } else{
 | 
						|
      this.pack_double(value);
 | 
						|
    }
 | 
						|
  } else if (type == 'boolean'){
 | 
						|
    if (value === true){
 | 
						|
      this.bufferBuilder.append(0xc3);
 | 
						|
    } else if (value === false){
 | 
						|
      this.bufferBuilder.append(0xc2);
 | 
						|
    }
 | 
						|
  } else if (type == 'undefined'){
 | 
						|
    this.bufferBuilder.append(0xc0);
 | 
						|
  } else if (type == 'object'){
 | 
						|
    if (value === null){
 | 
						|
      this.bufferBuilder.append(0xc0);
 | 
						|
    } else {
 | 
						|
      var constructor = value.constructor;
 | 
						|
      if (constructor == Array){
 | 
						|
        this.pack_array(value);
 | 
						|
      } else if (constructor == Blob || constructor == File) {
 | 
						|
        this.pack_bin(value);
 | 
						|
      } else if (constructor == ArrayBuffer) {
 | 
						|
        if(binaryFeatures.useArrayBufferView) {
 | 
						|
          this.pack_bin(new Uint8Array(value));
 | 
						|
        } else {
 | 
						|
          this.pack_bin(value);
 | 
						|
        }
 | 
						|
      } else if ('BYTES_PER_ELEMENT' in value){
 | 
						|
        if(binaryFeatures.useArrayBufferView) {
 | 
						|
          this.pack_bin(new Uint8Array(value.buffer));
 | 
						|
        } else {
 | 
						|
          this.pack_bin(value.buffer);
 | 
						|
        }
 | 
						|
      } else if (constructor == Object){
 | 
						|
        this.pack_object(value);
 | 
						|
      } else if (constructor == Date){
 | 
						|
        this.pack_string(value.toString());
 | 
						|
      } else if (typeof value.toBinaryPack == 'function'){
 | 
						|
        this.bufferBuilder.append(value.toBinaryPack());
 | 
						|
      } else {
 | 
						|
        throw new Error('Type "' + constructor.toString() + '" not yet supported');
 | 
						|
      }
 | 
						|
    }
 | 
						|
  } else {
 | 
						|
    throw new Error('Type "' + type + '" not yet supported');
 | 
						|
  }
 | 
						|
  this.bufferBuilder.flush();
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
Packer.prototype.pack_bin = function(blob){
 | 
						|
  var length = blob.length || blob.byteLength || blob.size;
 | 
						|
  if (length <= 0x0f){
 | 
						|
    this.pack_uint8(0xa0 + length);
 | 
						|
  } else if (length <= 0xffff){
 | 
						|
    this.bufferBuilder.append(0xda) ;
 | 
						|
    this.pack_uint16(length);
 | 
						|
  } else if (length <= 0xffffffff){
 | 
						|
    this.bufferBuilder.append(0xdb);
 | 
						|
    this.pack_uint32(length);
 | 
						|
  } else{
 | 
						|
    throw new Error('Invalid length');
 | 
						|
  }
 | 
						|
  this.bufferBuilder.append(blob);
 | 
						|
}
 | 
						|
 | 
						|
Packer.prototype.pack_string = function(str){
 | 
						|
  var length = utf8Length(str);
 | 
						|
 | 
						|
  if (length <= 0x0f){
 | 
						|
    this.pack_uint8(0xb0 + length);
 | 
						|
  } else if (length <= 0xffff){
 | 
						|
    this.bufferBuilder.append(0xd8) ;
 | 
						|
    this.pack_uint16(length);
 | 
						|
  } else if (length <= 0xffffffff){
 | 
						|
    this.bufferBuilder.append(0xd9);
 | 
						|
    this.pack_uint32(length);
 | 
						|
  } else{
 | 
						|
    throw new Error('Invalid length');
 | 
						|
  }
 | 
						|
  this.bufferBuilder.append(str);
 | 
						|
}
 | 
						|
 | 
						|
Packer.prototype.pack_array = function(ary){
 | 
						|
  var length = ary.length;
 | 
						|
  if (length <= 0x0f){
 | 
						|
    this.pack_uint8(0x90 + length);
 | 
						|
  } else if (length <= 0xffff){
 | 
						|
    this.bufferBuilder.append(0xdc)
 | 
						|
    this.pack_uint16(length);
 | 
						|
  } else if (length <= 0xffffffff){
 | 
						|
    this.bufferBuilder.append(0xdd);
 | 
						|
    this.pack_uint32(length);
 | 
						|
  } else{
 | 
						|
    throw new Error('Invalid length');
 | 
						|
  }
 | 
						|
  for(var i = 0; i < length ; i++){
 | 
						|
    this.pack(ary[i]);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
Packer.prototype.pack_integer = function(num){
 | 
						|
  if ( -0x20 <= num && num <= 0x7f){
 | 
						|
    this.bufferBuilder.append(num & 0xff);
 | 
						|
  } else if (0x00 <= num && num <= 0xff){
 | 
						|
    this.bufferBuilder.append(0xcc);
 | 
						|
    this.pack_uint8(num);
 | 
						|
  } else if (-0x80 <= num && num <= 0x7f){
 | 
						|
    this.bufferBuilder.append(0xd0);
 | 
						|
    this.pack_int8(num);
 | 
						|
  } else if ( 0x0000 <= num && num <= 0xffff){
 | 
						|
    this.bufferBuilder.append(0xcd);
 | 
						|
    this.pack_uint16(num);
 | 
						|
  } else if (-0x8000 <= num && num <= 0x7fff){
 | 
						|
    this.bufferBuilder.append(0xd1);
 | 
						|
    this.pack_int16(num);
 | 
						|
  } else if ( 0x00000000 <= num && num <= 0xffffffff){
 | 
						|
    this.bufferBuilder.append(0xce);
 | 
						|
    this.pack_uint32(num);
 | 
						|
  } else if (-0x80000000 <= num && num <= 0x7fffffff){
 | 
						|
    this.bufferBuilder.append(0xd2);
 | 
						|
    this.pack_int32(num);
 | 
						|
  } else if (-0x8000000000000000 <= num && num <= 0x7FFFFFFFFFFFFFFF){
 | 
						|
    this.bufferBuilder.append(0xd3);
 | 
						|
    this.pack_int64(num);
 | 
						|
  } else if (0x0000000000000000 <= num && num <= 0xFFFFFFFFFFFFFFFF){
 | 
						|
    this.bufferBuilder.append(0xcf);
 | 
						|
    this.pack_uint64(num);
 | 
						|
  } else{
 | 
						|
    throw new Error('Invalid integer');
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
Packer.prototype.pack_double = function(num){
 | 
						|
  var sign = 0;
 | 
						|
  if (num < 0){
 | 
						|
    sign = 1;
 | 
						|
    num = -num;
 | 
						|
  }
 | 
						|
  var exp  = Math.floor(Math.log(num) / Math.LN2);
 | 
						|
  var frac0 = num / Math.pow(2, exp) - 1;
 | 
						|
  var frac1 = Math.floor(frac0 * Math.pow(2, 52));
 | 
						|
  var b32   = Math.pow(2, 32);
 | 
						|
  var h32 = (sign << 31) | ((exp+1023) << 20) |
 | 
						|
      (frac1 / b32) & 0x0fffff;
 | 
						|
  var l32 = frac1 % b32;
 | 
						|
  this.bufferBuilder.append(0xcb);
 | 
						|
  this.pack_int32(h32);
 | 
						|
  this.pack_int32(l32);
 | 
						|
}
 | 
						|
 | 
						|
Packer.prototype.pack_object = function(obj){
 | 
						|
  var keys = Object.keys(obj);
 | 
						|
  var length = keys.length;
 | 
						|
  if (length <= 0x0f){
 | 
						|
    this.pack_uint8(0x80 + length);
 | 
						|
  } else if (length <= 0xffff){
 | 
						|
    this.bufferBuilder.append(0xde);
 | 
						|
    this.pack_uint16(length);
 | 
						|
  } else if (length <= 0xffffffff){
 | 
						|
    this.bufferBuilder.append(0xdf);
 | 
						|
    this.pack_uint32(length);
 | 
						|
  } else{
 | 
						|
    throw new Error('Invalid length');
 | 
						|
  }
 | 
						|
  for(var prop in obj){
 | 
						|
    if (obj.hasOwnProperty(prop)){
 | 
						|
      this.pack(prop);
 | 
						|
      this.pack(obj[prop]);
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
Packer.prototype.pack_uint8 = function(num){
 | 
						|
  this.bufferBuilder.append(num);
 | 
						|
}
 | 
						|
 | 
						|
Packer.prototype.pack_uint16 = function(num){
 | 
						|
  this.bufferBuilder.append(num >> 8);
 | 
						|
  this.bufferBuilder.append(num & 0xff);
 | 
						|
}
 | 
						|
 | 
						|
Packer.prototype.pack_uint32 = function(num){
 | 
						|
  var n = num & 0xffffffff;
 | 
						|
  this.bufferBuilder.append((n & 0xff000000) >>> 24);
 | 
						|
  this.bufferBuilder.append((n & 0x00ff0000) >>> 16);
 | 
						|
  this.bufferBuilder.append((n & 0x0000ff00) >>>  8);
 | 
						|
  this.bufferBuilder.append((n & 0x000000ff));
 | 
						|
}
 | 
						|
 | 
						|
Packer.prototype.pack_uint64 = function(num){
 | 
						|
  var high = num / Math.pow(2, 32);
 | 
						|
  var low  = num % Math.pow(2, 32);
 | 
						|
  this.bufferBuilder.append((high & 0xff000000) >>> 24);
 | 
						|
  this.bufferBuilder.append((high & 0x00ff0000) >>> 16);
 | 
						|
  this.bufferBuilder.append((high & 0x0000ff00) >>>  8);
 | 
						|
  this.bufferBuilder.append((high & 0x000000ff));
 | 
						|
  this.bufferBuilder.append((low  & 0xff000000) >>> 24);
 | 
						|
  this.bufferBuilder.append((low  & 0x00ff0000) >>> 16);
 | 
						|
  this.bufferBuilder.append((low  & 0x0000ff00) >>>  8);
 | 
						|
  this.bufferBuilder.append((low  & 0x000000ff));
 | 
						|
}
 | 
						|
 | 
						|
Packer.prototype.pack_int8 = function(num){
 | 
						|
  this.bufferBuilder.append(num & 0xff);
 | 
						|
}
 | 
						|
 | 
						|
Packer.prototype.pack_int16 = function(num){
 | 
						|
  this.bufferBuilder.append((num & 0xff00) >> 8);
 | 
						|
  this.bufferBuilder.append(num & 0xff);
 | 
						|
}
 | 
						|
 | 
						|
Packer.prototype.pack_int32 = function(num){
 | 
						|
  this.bufferBuilder.append((num >>> 24) & 0xff);
 | 
						|
  this.bufferBuilder.append((num & 0x00ff0000) >>> 16);
 | 
						|
  this.bufferBuilder.append((num & 0x0000ff00) >>> 8);
 | 
						|
  this.bufferBuilder.append((num & 0x000000ff));
 | 
						|
}
 | 
						|
 | 
						|
Packer.prototype.pack_int64 = function(num){
 | 
						|
  var high = Math.floor(num / Math.pow(2, 32));
 | 
						|
  var low  = num % Math.pow(2, 32);
 | 
						|
  this.bufferBuilder.append((high & 0xff000000) >>> 24);
 | 
						|
  this.bufferBuilder.append((high & 0x00ff0000) >>> 16);
 | 
						|
  this.bufferBuilder.append((high & 0x0000ff00) >>>  8);
 | 
						|
  this.bufferBuilder.append((high & 0x000000ff));
 | 
						|
  this.bufferBuilder.append((low  & 0xff000000) >>> 24);
 | 
						|
  this.bufferBuilder.append((low  & 0x00ff0000) >>> 16);
 | 
						|
  this.bufferBuilder.append((low  & 0x0000ff00) >>>  8);
 | 
						|
  this.bufferBuilder.append((low  & 0x000000ff));
 | 
						|
}
 | 
						|
 | 
						|
function _utf8Replace(m){
 | 
						|
  var code = m.charCodeAt(0);
 | 
						|
 | 
						|
  if(code <= 0x7ff) return '00';
 | 
						|
  if(code <= 0xffff) return '000';
 | 
						|
  if(code <= 0x1fffff) return '0000';
 | 
						|
  if(code <= 0x3ffffff) return '00000';
 | 
						|
  return '000000';
 | 
						|
}
 | 
						|
 | 
						|
function utf8Length(str){
 | 
						|
  if (str.length > 600) {
 | 
						|
    // Blob method faster for large strings
 | 
						|
    return (new Blob([str])).size;
 | 
						|
  } else {
 | 
						|
    return str.replace(/[^\u0000-\u007F]/g, _utf8Replace).length;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
},{"./bufferbuilder":2}],2:[function(require,module,exports){
 | 
						|
var binaryFeatures = {};
 | 
						|
binaryFeatures.useBlobBuilder = (function(){
 | 
						|
  try {
 | 
						|
    new Blob([]);
 | 
						|
    return false;
 | 
						|
  } catch (e) {
 | 
						|
    return true;
 | 
						|
  }
 | 
						|
})();
 | 
						|
 | 
						|
binaryFeatures.useArrayBufferView = !binaryFeatures.useBlobBuilder && (function(){
 | 
						|
  try {
 | 
						|
    return (new Blob([new Uint8Array([])])).size === 0;
 | 
						|
  } catch (e) {
 | 
						|
    return true;
 | 
						|
  }
 | 
						|
})();
 | 
						|
 | 
						|
module.exports.binaryFeatures = binaryFeatures;
 | 
						|
var BlobBuilder = module.exports.BlobBuilder;
 | 
						|
if (typeof window != 'undefined') {
 | 
						|
  BlobBuilder = module.exports.BlobBuilder = window.WebKitBlobBuilder ||
 | 
						|
    window.MozBlobBuilder || window.MSBlobBuilder || window.BlobBuilder;
 | 
						|
}
 | 
						|
 | 
						|
function BufferBuilder(){
 | 
						|
  this._pieces = [];
 | 
						|
  this._parts = [];
 | 
						|
}
 | 
						|
 | 
						|
BufferBuilder.prototype.append = function(data) {
 | 
						|
  if(typeof data === 'number') {
 | 
						|
    this._pieces.push(data);
 | 
						|
  } else {
 | 
						|
    this.flush();
 | 
						|
    this._parts.push(data);
 | 
						|
  }
 | 
						|
};
 | 
						|
 | 
						|
BufferBuilder.prototype.flush = function() {
 | 
						|
  if (this._pieces.length > 0) {
 | 
						|
    var buf = new Uint8Array(this._pieces);
 | 
						|
    if(!binaryFeatures.useArrayBufferView) {
 | 
						|
      buf = buf.buffer;
 | 
						|
    }
 | 
						|
    this._parts.push(buf);
 | 
						|
    this._pieces = [];
 | 
						|
  }
 | 
						|
};
 | 
						|
 | 
						|
BufferBuilder.prototype.getBuffer = function() {
 | 
						|
  this.flush();
 | 
						|
  if(binaryFeatures.useBlobBuilder) {
 | 
						|
    var builder = new BlobBuilder();
 | 
						|
    for(var i = 0, ii = this._parts.length; i < ii; i++) {
 | 
						|
      builder.append(this._parts[i]);
 | 
						|
    }
 | 
						|
    return builder.getBlob();
 | 
						|
  } else {
 | 
						|
    return new Blob(this._parts);
 | 
						|
  }
 | 
						|
};
 | 
						|
 | 
						|
module.exports.BufferBuilder = BufferBuilder;
 | 
						|
 | 
						|
},{}],3:[function(require,module,exports){
 | 
						|
var BufferBuilderExports = require('./bufferbuilder');
 | 
						|
 | 
						|
window.BufferBuilder = BufferBuilderExports.BufferBuilder;
 | 
						|
window.binaryFeatures = BufferBuilderExports.binaryFeatures;
 | 
						|
window.BlobBuilder = BufferBuilderExports.BlobBuilder;
 | 
						|
window.BinaryPack = require('./binarypack');
 | 
						|
 | 
						|
},{"./binarypack":1,"./bufferbuilder":2}]},{},[3]);
 | 
						|
/**
 | 
						|
 * Light EventEmitter. Ported from Node.js/events.js
 | 
						|
 * Eric Zhang
 | 
						|
 */
 | 
						|
 | 
						|
/**
 | 
						|
 * EventEmitter class
 | 
						|
 * Creates an object with event registering and firing methods
 | 
						|
 */
 | 
						|
function EventEmitter() {
 | 
						|
  // Initialise required storage variables
 | 
						|
  this._events = {};
 | 
						|
}
 | 
						|
 | 
						|
var isArray = Array.isArray;
 | 
						|
 | 
						|
 | 
						|
EventEmitter.prototype.addListener = function(type, listener, scope, once) {
 | 
						|
  if ('function' !== typeof listener) {
 | 
						|
    throw new Error('addListener only takes instances of Function');
 | 
						|
  }
 | 
						|
  
 | 
						|
  // To avoid recursion in the case that type == "newListeners"! Before
 | 
						|
  // adding it to the listeners, first emit "newListeners".
 | 
						|
  this.emit('newListener', type, typeof listener.listener === 'function' ?
 | 
						|
            listener.listener : listener);
 | 
						|
            
 | 
						|
  if (!this._events[type]) {
 | 
						|
    // Optimize the case of one listener. Don't need the extra array object.
 | 
						|
    this._events[type] = listener;
 | 
						|
  } else if (isArray(this._events[type])) {
 | 
						|
 | 
						|
    // If we've already got an array, just append.
 | 
						|
    this._events[type].push(listener);
 | 
						|
 | 
						|
  } else {
 | 
						|
    // Adding the second element, need to change to array.
 | 
						|
    this._events[type] = [this._events[type], listener];
 | 
						|
  }
 | 
						|
  
 | 
						|
};
 | 
						|
 | 
						|
EventEmitter.prototype.on = EventEmitter.prototype.addListener;
 | 
						|
 | 
						|
EventEmitter.prototype.once = function(type, listener, scope) {
 | 
						|
  if ('function' !== typeof listener) {
 | 
						|
    throw new Error('.once only takes instances of Function');
 | 
						|
  }
 | 
						|
 | 
						|
  var self = this;
 | 
						|
  function g() {
 | 
						|
    self.removeListener(type, g);
 | 
						|
    listener.apply(this, arguments);
 | 
						|
  };
 | 
						|
 | 
						|
  g.listener = listener;
 | 
						|
  self.on(type, g);
 | 
						|
 | 
						|
  return this;
 | 
						|
};
 | 
						|
 | 
						|
EventEmitter.prototype.removeListener = function(type, listener, scope) {
 | 
						|
  if ('function' !== typeof listener) {
 | 
						|
    throw new Error('removeListener only takes instances of Function');
 | 
						|
  }
 | 
						|
 | 
						|
  // does not use listeners(), so no side effect of creating _events[type]
 | 
						|
  if (!this._events[type]) return this;
 | 
						|
 | 
						|
  var list = this._events[type];
 | 
						|
 | 
						|
  if (isArray(list)) {
 | 
						|
    var position = -1;
 | 
						|
    for (var i = 0, length = list.length; i < length; i++) {
 | 
						|
      if (list[i] === listener ||
 | 
						|
          (list[i].listener && list[i].listener === listener))
 | 
						|
      {
 | 
						|
        position = i;
 | 
						|
        break;
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    if (position < 0) return this;
 | 
						|
    list.splice(position, 1);
 | 
						|
    if (list.length == 0)
 | 
						|
      delete this._events[type];
 | 
						|
  } else if (list === listener ||
 | 
						|
             (list.listener && list.listener === listener))
 | 
						|
  {
 | 
						|
    delete this._events[type];
 | 
						|
  }
 | 
						|
 | 
						|
  return this;
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
EventEmitter.prototype.off = EventEmitter.prototype.removeListener;
 | 
						|
 | 
						|
 | 
						|
EventEmitter.prototype.removeAllListeners = function(type) {
 | 
						|
  if (arguments.length === 0) {
 | 
						|
    this._events = {};
 | 
						|
    return this;
 | 
						|
  }
 | 
						|
 | 
						|
  // does not use listeners(), so no side effect of creating _events[type]
 | 
						|
  if (type && this._events && this._events[type]) this._events[type] = null;
 | 
						|
  return this;
 | 
						|
};
 | 
						|
 | 
						|
EventEmitter.prototype.listeners = function(type) {
 | 
						|
  if (!this._events[type]) this._events[type] = [];
 | 
						|
  if (!isArray(this._events[type])) {
 | 
						|
    this._events[type] = [this._events[type]];
 | 
						|
  }
 | 
						|
  return this._events[type];
 | 
						|
};
 | 
						|
 | 
						|
EventEmitter.prototype.emit = function(type) {
 | 
						|
  var type = arguments[0];
 | 
						|
  var handler = this._events[type];
 | 
						|
  if (!handler) return false;
 | 
						|
 | 
						|
  if (typeof handler == 'function') {
 | 
						|
    switch (arguments.length) {
 | 
						|
      // fast cases
 | 
						|
      case 1:
 | 
						|
        handler.call(this);
 | 
						|
        break;
 | 
						|
      case 2:
 | 
						|
        handler.call(this, arguments[1]);
 | 
						|
        break;
 | 
						|
      case 3:
 | 
						|
        handler.call(this, arguments[1], arguments[2]);
 | 
						|
        break;
 | 
						|
      // slower
 | 
						|
      default:
 | 
						|
        var l = arguments.length;
 | 
						|
        var args = new Array(l - 1);
 | 
						|
        for (var i = 1; i < l; i++) args[i - 1] = arguments[i];
 | 
						|
        handler.apply(this, args);
 | 
						|
    }
 | 
						|
    return true;
 | 
						|
 | 
						|
  } else if (isArray(handler)) {
 | 
						|
    var l = arguments.length;
 | 
						|
    var args = new Array(l - 1);
 | 
						|
    for (var i = 1; i < l; i++) args[i - 1] = arguments[i];
 | 
						|
 | 
						|
    var listeners = handler.slice();
 | 
						|
    for (var i = 0, l = listeners.length; i < l; i++) {
 | 
						|
      listeners[i].apply(this, args);
 | 
						|
    }
 | 
						|
    return true;
 | 
						|
  } else {
 | 
						|
    return false;
 | 
						|
  }
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
var util = {
 | 
						|
  inherits: function(ctor, superCtor) {
 | 
						|
    ctor.super_ = superCtor;
 | 
						|
    ctor.prototype = Object.create(superCtor.prototype, {
 | 
						|
      constructor: {
 | 
						|
        value: ctor,
 | 
						|
        enumerable: false,
 | 
						|
        writable: true,
 | 
						|
        configurable: true
 | 
						|
      }
 | 
						|
    });
 | 
						|
  },
 | 
						|
  extend: function(dest, source) {
 | 
						|
    for(var key in source) {
 | 
						|
      if(source.hasOwnProperty(key)) {
 | 
						|
        dest[key] = source[key];
 | 
						|
      }
 | 
						|
    }
 | 
						|
    return dest;
 | 
						|
  },
 | 
						|
  pack: BinaryPack.pack,
 | 
						|
  unpack: BinaryPack.unpack,
 | 
						|
  setZeroTimeout: (function(global) {
 | 
						|
    var timeouts = [];
 | 
						|
    var messageName = 'zero-timeout-message';
 | 
						|
 | 
						|
    // Like setTimeout, but only takes a function argument.	 There's
 | 
						|
    // no time argument (always zero) and no arguments (you have to
 | 
						|
    // use a closure).
 | 
						|
    function setZeroTimeoutPostMessage(fn) {
 | 
						|
      timeouts.push(fn);
 | 
						|
      global.postMessage(messageName, '*');
 | 
						|
    }		
 | 
						|
 | 
						|
    function handleMessage(event) {
 | 
						|
      if (event.source == global && event.data == messageName) {
 | 
						|
        if (event.stopPropagation) {
 | 
						|
          event.stopPropagation();
 | 
						|
        }
 | 
						|
        if (timeouts.length) {
 | 
						|
          timeouts.shift()();
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
    if (global.addEventListener) {
 | 
						|
      global.addEventListener('message', handleMessage, true);
 | 
						|
    } else if (global.attachEvent) {
 | 
						|
      global.attachEvent('onmessage', handleMessage);
 | 
						|
    }
 | 
						|
    return setZeroTimeoutPostMessage;
 | 
						|
  }(this))
 | 
						|
};
 | 
						|
 | 
						|
exports.util = util;
 | 
						|
 | 
						|
 | 
						|
function Stream() {
 | 
						|
  EventEmitter.call(this);
 | 
						|
}
 | 
						|
 | 
						|
util.inherits(Stream, EventEmitter);
 | 
						|
 | 
						|
Stream.prototype.pipe = function(dest, options) {
 | 
						|
  var source = this;
 | 
						|
 | 
						|
  function ondata(chunk) {
 | 
						|
    if (dest.writable) {
 | 
						|
      if (false === dest.write(chunk) && source.pause) {
 | 
						|
        source.pause();
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  source.on('data', ondata);
 | 
						|
 | 
						|
  function ondrain() {
 | 
						|
    if (source.readable && source.resume) {
 | 
						|
      source.resume();
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  dest.on('drain', ondrain);
 | 
						|
 | 
						|
  // If the 'end' option is not supplied, dest.end() will be called when
 | 
						|
  // source gets the 'end' or 'close' events.  Only dest.end() once.
 | 
						|
  if (!dest._isStdio && (!options || options.end !== false)) {
 | 
						|
    source.on('end', onend);
 | 
						|
    source.on('close', onclose);
 | 
						|
  }
 | 
						|
 | 
						|
  var didOnEnd = false;
 | 
						|
  function onend() {
 | 
						|
    if (didOnEnd) return;
 | 
						|
    didOnEnd = true;
 | 
						|
 | 
						|
    dest.end();
 | 
						|
  }
 | 
						|
 | 
						|
 | 
						|
  function onclose() {
 | 
						|
    if (didOnEnd) return;
 | 
						|
    didOnEnd = true;
 | 
						|
 | 
						|
    dest.destroy();
 | 
						|
  }
 | 
						|
 | 
						|
  // don't leave dangling pipes when there are errors.
 | 
						|
  function onerror(er) {
 | 
						|
    cleanup();
 | 
						|
    if (this.listeners('error').length === 0) {
 | 
						|
      throw er; // Unhandled stream error in pipe.
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  source.on('error', onerror);
 | 
						|
  dest.on('error', onerror);
 | 
						|
 | 
						|
  // remove all the event listeners that were added.
 | 
						|
  function cleanup() {
 | 
						|
    source.removeListener('data', ondata);
 | 
						|
    dest.removeListener('drain', ondrain);
 | 
						|
 | 
						|
    source.removeListener('end', onend);
 | 
						|
    source.removeListener('close', onclose);
 | 
						|
 | 
						|
    source.removeListener('error', onerror);
 | 
						|
    dest.removeListener('error', onerror);
 | 
						|
 | 
						|
    source.removeListener('end', cleanup);
 | 
						|
    source.removeListener('close', cleanup);
 | 
						|
 | 
						|
    dest.removeListener('end', cleanup);
 | 
						|
    dest.removeListener('close', cleanup);
 | 
						|
  }
 | 
						|
 | 
						|
  source.on('end', cleanup);
 | 
						|
  source.on('close', cleanup);
 | 
						|
 | 
						|
  dest.on('end', cleanup);
 | 
						|
  dest.on('close', cleanup);
 | 
						|
 | 
						|
  dest.emit('pipe', source);
 | 
						|
 | 
						|
  // Allow for unix-like usage: A.pipe(B).pipe(C)
 | 
						|
  return dest;
 | 
						|
};
 | 
						|
 | 
						|
exports.Stream = Stream;
 | 
						|
function BlobReadStream(source, options){
 | 
						|
  Stream.call(this);
 | 
						|
  
 | 
						|
  options = util.extend({
 | 
						|
      readDelay: 0,
 | 
						|
      paused: false
 | 
						|
  }, options);
 | 
						|
  
 | 
						|
  this._source = source;
 | 
						|
  this._start = 0;
 | 
						|
  this._readChunkSize = options.chunkSize || source.size;
 | 
						|
  this._readDelay = options.readDelay;
 | 
						|
  
 | 
						|
  this.readable = true;
 | 
						|
  this.paused = options.paused;
 | 
						|
  
 | 
						|
  this._read();
 | 
						|
}
 | 
						|
 | 
						|
util.inherits(BlobReadStream, Stream);
 | 
						|
 | 
						|
 | 
						|
BlobReadStream.prototype.pause = function(){
 | 
						|
  this.paused = true;
 | 
						|
};
 | 
						|
 | 
						|
BlobReadStream.prototype.resume = function(){
 | 
						|
  this.paused = false;
 | 
						|
  this._read();
 | 
						|
};
 | 
						|
 | 
						|
BlobReadStream.prototype.destroy = function(){
 | 
						|
  this.readable = false;
 | 
						|
  clearTimeout(this._timeoutId);
 | 
						|
};
 | 
						|
 | 
						|
BlobReadStream.prototype._read = function(){
 | 
						|
    
 | 
						|
  var self = this;
 | 
						|
  
 | 
						|
  function emitReadChunk(){
 | 
						|
    self._emitReadChunk();
 | 
						|
  }
 | 
						|
  
 | 
						|
  var readDelay = this._readDelay;
 | 
						|
  if (readDelay !== 0){
 | 
						|
    this._timeoutId = setTimeout(emitReadChunk, readDelay);
 | 
						|
  } else {
 | 
						|
    util.setZeroTimeout(emitReadChunk);
 | 
						|
  }
 | 
						|
    
 | 
						|
};
 | 
						|
 | 
						|
BlobReadStream.prototype._emitReadChunk = function(){
 | 
						|
    
 | 
						|
  if(this.paused || !this.readable) return;
 | 
						|
  
 | 
						|
  var chunkSize = Math.min(this._source.size - this._start, this._readChunkSize);
 | 
						|
  
 | 
						|
  if(chunkSize === 0){
 | 
						|
      this.readable = false;
 | 
						|
      this.emit("end");
 | 
						|
      return;
 | 
						|
  }
 | 
						|
  
 | 
						|
  var sourceEnd = this._start + chunkSize;
 | 
						|
  var chunk = (this._source.slice || this._source.webkitSlice || this._source.mozSlice).call(this._source, this._start, sourceEnd);
 | 
						|
  
 | 
						|
  this._start = sourceEnd;
 | 
						|
  this._read();
 | 
						|
  
 | 
						|
  this.emit("data", chunk);
 | 
						|
  
 | 
						|
};
 | 
						|
 | 
						|
/*
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
function BlobWriteStream(options){
 | 
						|
    
 | 
						|
    stream.Stream.call(this);
 | 
						|
    
 | 
						|
    options = _.extend({
 | 
						|
        onFull: onFull,
 | 
						|
        onEnd: function(){},
 | 
						|
        minBlockAllocSize: 0,
 | 
						|
        drainDelay:0
 | 
						|
    }, options);
 | 
						|
    
 | 
						|
    this._onFull = options.onFull;
 | 
						|
    this._onEnd = options.onEnd;
 | 
						|
    this._onWrite = options.onWrite;
 | 
						|
    
 | 
						|
    this._minBlockAllocSize = options.minBlockAllocSize;
 | 
						|
    this._maxBlockAllocSize = options.maxBlockAllocSize;
 | 
						|
    this._drainDelay = options.drainDelay;
 | 
						|
    
 | 
						|
    this._buffer = new Buffer(options.minBlockAllocSize);
 | 
						|
    this._destination = this._buffer;
 | 
						|
    this._destinationPos = 0;
 | 
						|
    
 | 
						|
    this._writeQueue = [];
 | 
						|
    this._pendingOnFull = false;
 | 
						|
    this._pendingQueueDrain = false;
 | 
						|
    
 | 
						|
    this.writable = true;
 | 
						|
    this.bytesWritten = 0;
 | 
						|
}
 | 
						|
 | 
						|
util.inherits(BlobWriteStream, stream.Stream);
 | 
						|
 | 
						|
BlobWriteStream.prototype.getBuffer = function(){
 | 
						|
    return this._buffer;
 | 
						|
};
 | 
						|
 | 
						|
BlobWriteStream.prototype.write = function(data, encoding){
 | 
						|
    
 | 
						|
    if(!this.writable){
 | 
						|
        throw new Error("stream is not writable");
 | 
						|
    }
 | 
						|
    
 | 
						|
    if(!Buffer.isBuffer(data)){
 | 
						|
        data = new Buffer(data, encoding);
 | 
						|
    }
 | 
						|
    
 | 
						|
    if(data.length){
 | 
						|
        this._writeQueue.push(data);
 | 
						|
    }
 | 
						|
    
 | 
						|
    this._commit();
 | 
						|
    
 | 
						|
    return this._writeQueue.length === 0;
 | 
						|
};
 | 
						|
 | 
						|
BlobWriteStream.prototype._commit = function(){
 | 
						|
    
 | 
						|
    var self = this;
 | 
						|
    
 | 
						|
    var destination = this._destination;
 | 
						|
    var writeQueue = this._writeQueue;
 | 
						|
    
 | 
						|
    var startDestinationPos = this._destinationPos;
 | 
						|
    
 | 
						|
    while(writeQueue.length && destination.length){
 | 
						|
        
 | 
						|
        var head = writeQueue[0];
 | 
						|
        
 | 
						|
        var copySize = Math.min(destination.length, head.length);
 | 
						|
        
 | 
						|
        head.copy(destination, 0, 0, copySize);
 | 
						|
        
 | 
						|
        head = head.slice(copySize);
 | 
						|
        destination = destination.slice(copySize);
 | 
						|
        
 | 
						|
        this.bytesWritten += copySize;
 | 
						|
        this._destinationPos += copySize;
 | 
						|
        
 | 
						|
        if(head.length === 0){
 | 
						|
            writeQueue.shift();
 | 
						|
        }
 | 
						|
        else{
 | 
						|
            writeQueue[0] = head;
 | 
						|
        }
 | 
						|
    }
 | 
						|
    
 | 
						|
    this._destination = destination;
 | 
						|
    
 | 
						|
    bytesCommitted = this._destinationPos - startDestinationPos;
 | 
						|
    if(bytesCommitted){
 | 
						|
        if(this._onWrite){
 | 
						|
            
 | 
						|
            if(writeQueue.length){
 | 
						|
                this._pendingQueueDrain = true;
 | 
						|
            }
 | 
						|
            
 | 
						|
            // By locking destination the buffer is frozen and the onWrite
 | 
						|
            // callback cannot miss any write commits
 | 
						|
            this._destination = emptyBuffer;
 | 
						|
            
 | 
						|
            var consumer = this._onWrite;
 | 
						|
            this._onWrite = null;
 | 
						|
            
 | 
						|
            consumer.call(this, function(nextCallback){
 | 
						|
                util.setZeroTimeout(function(){
 | 
						|
                    self._destination = destination;
 | 
						|
                    self._onWrite = nextCallback;
 | 
						|
                    self._commit();
 | 
						|
                });
 | 
						|
            }, consumer);
 | 
						|
            
 | 
						|
            return;
 | 
						|
        }
 | 
						|
    }
 | 
						|
    
 | 
						|
    if(writeQueue.length){
 | 
						|
        
 | 
						|
        this._pendingQueueDrain = true;
 | 
						|
        this._growBuffer();
 | 
						|
    }
 | 
						|
    else if(this._pendingQueueDrain){
 | 
						|
        
 | 
						|
        this._pendingQueueDrain = false;
 | 
						|
        
 | 
						|
        if(this._drainDelay !== 0){
 | 
						|
            setTimeout(function(){
 | 
						|
                self.emit("drain");
 | 
						|
            }, this._drainDelay);
 | 
						|
        }
 | 
						|
        else{
 | 
						|
            util.setZeroTimeout(function(){
 | 
						|
                self.emit("drain");
 | 
						|
            });
 | 
						|
        }
 | 
						|
    }
 | 
						|
};
 | 
						|
 | 
						|
BlobWriteStream.prototype._growBuffer = function(){
 | 
						|
    
 | 
						|
    var self = this;
 | 
						|
    var writeQueue = this._writeQueue;
 | 
						|
    
 | 
						|
    var requestSize = this._minBlockAllocSize;
 | 
						|
    
 | 
						|
    var maxBlockAllocSize = this._maxBlockAllocSize;
 | 
						|
    var add = (maxBlockAllocSize === undefined ? function(a, b){return a + b;} : function(a, b){return Math.min(a + b, maxBlockAllocSize);});
 | 
						|
    
 | 
						|
    for(var i = 0, queueLength = writeQueue.length; i < queueLength; i++){
 | 
						|
        requestSize = add(requestSize, writeQueue[i].length);
 | 
						|
    }
 | 
						|
    
 | 
						|
    // Prevent concurrent onFull callbacks
 | 
						|
    if(this._pendingOnFull){
 | 
						|
        return;
 | 
						|
    }
 | 
						|
    this._pendingOnFull = true;
 | 
						|
    
 | 
						|
    this._onFull(this._buffer, requestSize, function(buffer, destination){
 | 
						|
        util.setZeroTimeout(function(){
 | 
						|
            
 | 
						|
            self._pendingOnFull = false;
 | 
						|
            
 | 
						|
            if(!destination){
 | 
						|
                if(self.writable){
 | 
						|
                    self.emit("error", new Error("buffer is full"));
 | 
						|
                }
 | 
						|
                self.destroy();
 | 
						|
                return;
 | 
						|
            }
 | 
						|
            
 | 
						|
            self._buffer = buffer;
 | 
						|
            self._destination = destination;
 | 
						|
            
 | 
						|
            self._commit();
 | 
						|
        });
 | 
						|
    });
 | 
						|
};
 | 
						|
 | 
						|
BlobWriteStream.prototype.end = function(data, encoding){
 | 
						|
    
 | 
						|
    var self = this;
 | 
						|
    
 | 
						|
    function _end(){
 | 
						|
        self.writable = false;
 | 
						|
        self._onEnd();
 | 
						|
    }
 | 
						|
    
 | 
						|
    if(data){
 | 
						|
        if(this.write(data, encoding)){
 | 
						|
            _end();
 | 
						|
        }else{
 | 
						|
            self.writable = false;
 | 
						|
            this.once("drain", _end);
 | 
						|
        }
 | 
						|
    }
 | 
						|
    else{
 | 
						|
        _end();
 | 
						|
    }
 | 
						|
};
 | 
						|
 | 
						|
BlobWriteStream.prototype.destroy = function(){
 | 
						|
    this.writable = false;
 | 
						|
    this._pendingQueueDrain = false;
 | 
						|
    this._writeQueue = [];
 | 
						|
};
 | 
						|
 | 
						|
BlobWriteStream.prototype.consume = function(consume){
 | 
						|
    
 | 
						|
    this._buffer = this._buffer.slice(consume);
 | 
						|
    this._destinationPos -= consume;
 | 
						|
};
 | 
						|
 | 
						|
BlobWriteStream.prototype.getCommittedSlice = function(){
 | 
						|
    return this._buffer.slice(0, this._destinationPos);
 | 
						|
};
 | 
						|
 | 
						|
function onFull(buffer, extraSize, callback){
 | 
						|
    var newBuffer = new Buffer(buffer.length + extraSize);
 | 
						|
    buffer.copy(newBuffer);
 | 
						|
    callback(newBuffer, newBuffer.slice(buffer.length));
 | 
						|
}
 | 
						|
*/
 | 
						|
exports.BlobReadStream = BlobReadStream;
 | 
						|
 | 
						|
function BinaryStream(socket, id, create, meta) {
 | 
						|
  if (!(this instanceof BinaryStream)) return new BinaryStream(options);
 | 
						|
  
 | 
						|
  var self = this;
 | 
						|
  
 | 
						|
  Stream.call(this);
 | 
						|
 | 
						|
  
 | 
						|
  this.id = id;
 | 
						|
  this._socket = socket;
 | 
						|
    
 | 
						|
  this.writable = true;
 | 
						|
  this.readable = true;
 | 
						|
  this.paused = false;
 | 
						|
  
 | 
						|
  this._closed = false;
 | 
						|
  this._ended = false;
 | 
						|
  
 | 
						|
  if(create) {
 | 
						|
    // This is a stream we are creating
 | 
						|
    this._write(1, meta, this.id);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
util.inherits(BinaryStream, Stream);
 | 
						|
 | 
						|
 | 
						|
BinaryStream.prototype._onDrain = function() {
 | 
						|
  if(!this.paused) {
 | 
						|
    this.emit('drain');
 | 
						|
  }
 | 
						|
};
 | 
						|
 | 
						|
BinaryStream.prototype._onClose = function() {
 | 
						|
  // Emit close event
 | 
						|
  if (this._closed) {
 | 
						|
    return;
 | 
						|
  }
 | 
						|
  this.readable = false;
 | 
						|
  this.writable = false;
 | 
						|
  this._closed = true;
 | 
						|
  this.emit('close');
 | 
						|
};
 | 
						|
 | 
						|
BinaryStream.prototype._onError = function(error){
 | 
						|
  this.readable = false;
 | 
						|
  this.writable = false;
 | 
						|
  this.emit('error', error);
 | 
						|
};
 | 
						|
 | 
						|
// Write stream
 | 
						|
 | 
						|
BinaryStream.prototype._onPause = function() {
 | 
						|
  // Emit pause event
 | 
						|
  this.paused = true;
 | 
						|
  this.emit('pause');
 | 
						|
};
 | 
						|
 | 
						|
BinaryStream.prototype._onResume = function() {
 | 
						|
  // Emit resume event
 | 
						|
  this.paused = false;
 | 
						|
  this.emit('resume');
 | 
						|
  this.emit('drain');
 | 
						|
};
 | 
						|
 | 
						|
BinaryStream.prototype._write = function(code, data, bonus) {
 | 
						|
  if (this._socket.readyState !== this._socket.constructor.OPEN) {
 | 
						|
    return false;
 | 
						|
  }
 | 
						|
  var message = util.pack([code, data, bonus]);
 | 
						|
  return this._socket.send(message) !== false;
 | 
						|
};
 | 
						|
 | 
						|
BinaryStream.prototype.write = function(data) {
 | 
						|
  if(this.writable) {
 | 
						|
    var out = this._write(2, data, this.id);
 | 
						|
    return !this.paused && out;
 | 
						|
  } else {
 | 
						|
    this.emit('error', new Error('Stream is not writable'));
 | 
						|
    return false;
 | 
						|
  }
 | 
						|
};
 | 
						|
 | 
						|
BinaryStream.prototype.end = function() {
 | 
						|
  this._ended = true;
 | 
						|
  this.readable = false;
 | 
						|
  this._write(5, null, this.id);
 | 
						|
};
 | 
						|
 | 
						|
BinaryStream.prototype.destroy = BinaryStream.prototype.destroySoon = function() {
 | 
						|
  this._onClose();
 | 
						|
  this._write(6, null, this.id);
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
// Read stream
 | 
						|
 | 
						|
BinaryStream.prototype._onEnd = function() {
 | 
						|
  if(this._ended) { 
 | 
						|
    return;
 | 
						|
  }
 | 
						|
  this._ended = true;
 | 
						|
  this.readable = false;
 | 
						|
  this.emit('end');
 | 
						|
};
 | 
						|
 | 
						|
BinaryStream.prototype._onData = function(data) {
 | 
						|
  // Dispatch 
 | 
						|
  this.emit('data', data);
 | 
						|
};
 | 
						|
 | 
						|
BinaryStream.prototype.pause = function() {
 | 
						|
  this._onPause();
 | 
						|
  this._write(3, null, this.id);
 | 
						|
};
 | 
						|
 | 
						|
BinaryStream.prototype.resume = function() {
 | 
						|
  this._onResume();
 | 
						|
  this._write(4, null, this.id);
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
function BinaryClient(socket, options) {
 | 
						|
  if (!(this instanceof BinaryClient)) return new BinaryClient(socket, options);
 | 
						|
  
 | 
						|
  EventEmitter.call(this);
 | 
						|
  
 | 
						|
  var self = this;
 | 
						|
  
 | 
						|
  this._options = util.extend({
 | 
						|
    chunkSize: 40960
 | 
						|
  }, options);
 | 
						|
  
 | 
						|
  this.streams = {};
 | 
						|
  
 | 
						|
  if(typeof socket === 'string') {
 | 
						|
    this._nextId = 0;
 | 
						|
    this._socket = new WebSocket(socket);
 | 
						|
  } else {
 | 
						|
    // Use odd numbered ids for server originated streams
 | 
						|
    this._nextId = 1;
 | 
						|
    this._socket = socket;
 | 
						|
  }
 | 
						|
  
 | 
						|
  this._socket.binaryType = 'arraybuffer';
 | 
						|
  
 | 
						|
  this._socket.addEventListener('open', function(){
 | 
						|
    self.emit('open');
 | 
						|
  });
 | 
						|
  this._socket.addEventListener('error', function(error){
 | 
						|
    var ids = Object.keys(self.streams);
 | 
						|
    for (var i = 0, ii = ids.length; i < ii; i++) {
 | 
						|
      self.streams[ids[i]]._onError(error);
 | 
						|
    }
 | 
						|
    self.emit('error', error);
 | 
						|
  });
 | 
						|
  this._socket.addEventListener('close', function(code, message){
 | 
						|
    var ids = Object.keys(self.streams);
 | 
						|
    for (var i = 0, ii = ids.length; i < ii; i++) {
 | 
						|
      self.streams[ids[i]]._onClose();
 | 
						|
    }
 | 
						|
    self.emit('close', code, message);
 | 
						|
  });
 | 
						|
  this._socket.addEventListener('message', function(data, flags){
 | 
						|
    util.setZeroTimeout(function(){
 | 
						|
  
 | 
						|
      // Message format
 | 
						|
      // [type, payload, bonus ]
 | 
						|
      //
 | 
						|
      // Reserved
 | 
						|
      // [ 0  , X , X ]
 | 
						|
      // 
 | 
						|
      //
 | 
						|
      // New stream
 | 
						|
      // [ 1  , Meta , new streamId ]
 | 
						|
      // 
 | 
						|
      //
 | 
						|
      // Data
 | 
						|
      // [ 2  , Data , streamId ]
 | 
						|
      // 
 | 
						|
      //
 | 
						|
      // Pause
 | 
						|
      // [ 3  , null , streamId ]
 | 
						|
      // 
 | 
						|
      //
 | 
						|
      // Resume
 | 
						|
      // [ 4  , null , streamId ]
 | 
						|
      // 
 | 
						|
      //
 | 
						|
      // End
 | 
						|
      // [ 5  , null , streamId ]
 | 
						|
      // 
 | 
						|
      //
 | 
						|
      // Close
 | 
						|
      // [ 6  , null , streamId ]
 | 
						|
      // 
 | 
						|
      
 | 
						|
      data = data.data;
 | 
						|
      
 | 
						|
      try {
 | 
						|
          data = util.unpack(data);
 | 
						|
      } catch (ex) {
 | 
						|
          return self.emit('error', new Error('Received unparsable message: ' + ex));
 | 
						|
      }
 | 
						|
      if (!(data instanceof Array))
 | 
						|
          return self.emit('error', new Error('Received non-array message'));
 | 
						|
      if (data.length != 3)
 | 
						|
          return self.emit('error', new Error('Received message with wrong part count: ' + data.length));
 | 
						|
      if ('number' != typeof data[0])
 | 
						|
          return self.emit('error', new Error('Received message with non-number type: ' + data[0]));
 | 
						|
      
 | 
						|
      switch(data[0]) {
 | 
						|
        case 0:
 | 
						|
          // Reserved
 | 
						|
          break;
 | 
						|
        case 1:
 | 
						|
          var meta = data[1];
 | 
						|
          var streamId = data[2];
 | 
						|
          var binaryStream = self._receiveStream(streamId);
 | 
						|
          self.emit('stream', binaryStream, meta);
 | 
						|
          break;
 | 
						|
        case 2:
 | 
						|
          var payload = data[1];
 | 
						|
          var streamId = data[2];
 | 
						|
          var binaryStream = self.streams[streamId];
 | 
						|
          if(binaryStream) {
 | 
						|
            binaryStream._onData(payload);
 | 
						|
          } else {
 | 
						|
            self.emit('error', new Error('Received `data` message for unknown stream: ' + streamId));
 | 
						|
          }
 | 
						|
          break;
 | 
						|
        case 3:
 | 
						|
          var streamId = data[2];
 | 
						|
          var binaryStream = self.streams[streamId];
 | 
						|
          if(binaryStream) {
 | 
						|
            binaryStream._onPause();
 | 
						|
          } else {
 | 
						|
            self.emit('error', new Error('Received `pause` message for unknown stream: ' + streamId));
 | 
						|
          }
 | 
						|
          break;
 | 
						|
        case 4:
 | 
						|
          var streamId = data[2];
 | 
						|
          var binaryStream = self.streams[streamId];
 | 
						|
          if(binaryStream) {
 | 
						|
            binaryStream._onResume();
 | 
						|
          } else {
 | 
						|
            self.emit('error', new Error('Received `resume` message for unknown stream: ' + streamId));
 | 
						|
          }
 | 
						|
          break;
 | 
						|
        case 5:
 | 
						|
          var streamId = data[2];
 | 
						|
          var binaryStream = self.streams[streamId];
 | 
						|
          if(binaryStream) {
 | 
						|
            binaryStream._onEnd();
 | 
						|
          } else {
 | 
						|
            self.emit('error', new Error('Received `end` message for unknown stream: ' + streamId));
 | 
						|
          }
 | 
						|
          break;
 | 
						|
        case 6:
 | 
						|
          var streamId = data[2];
 | 
						|
          var binaryStream = self.streams[streamId];
 | 
						|
          if(binaryStream) {
 | 
						|
            binaryStream._onClose();
 | 
						|
          } else {
 | 
						|
            self.emit('error', new Error('Received `close` message for unknown stream: ' + streamId));
 | 
						|
          }
 | 
						|
          break;
 | 
						|
        default:
 | 
						|
          self.emit('error', new Error('Unrecognized message type received: ' + data[0]));
 | 
						|
      }
 | 
						|
    });
 | 
						|
  });
 | 
						|
}
 | 
						|
 | 
						|
util.inherits(BinaryClient, EventEmitter);
 | 
						|
 | 
						|
BinaryClient.prototype.send = function(data, meta){
 | 
						|
  var stream = this.createStream(meta);
 | 
						|
  if(data instanceof Stream) {
 | 
						|
    data.pipe(stream);
 | 
						|
  } else if (util.isNode === true) {
 | 
						|
    if(Buffer.isBuffer(data)) {
 | 
						|
      (new BufferReadStream(data, {chunkSize: this._options.chunkSize})).pipe(stream);
 | 
						|
    } else {
 | 
						|
      stream.write(data);
 | 
						|
    } 
 | 
						|
  } else if (util.isNode !== true) {
 | 
						|
    if(data.constructor == Blob || data.constructor == File) {
 | 
						|
      (new BlobReadStream(data, {chunkSize: this._options.chunkSize})).pipe(stream);
 | 
						|
    } else if (data.constructor == ArrayBuffer) {
 | 
						|
      var blob;
 | 
						|
      if(binaryFeatures.useArrayBufferView) {
 | 
						|
        data = new Uint8Array(data);
 | 
						|
      }
 | 
						|
      if(binaryFeatures.useBlobBuilder) {
 | 
						|
        var builder = new BlobBuilder();
 | 
						|
        builder.append(data);
 | 
						|
        blob = builder.getBlob()
 | 
						|
      } else {
 | 
						|
        blob = new Blob([data]);
 | 
						|
      }
 | 
						|
      (new BlobReadStream(blob, {chunkSize: this._options.chunkSize})).pipe(stream);
 | 
						|
    } else if (typeof data === 'object' && 'BYTES_PER_ELEMENT' in data) {
 | 
						|
      var blob;
 | 
						|
      if(!binaryFeatures.useArrayBufferView) {
 | 
						|
        // Warn
 | 
						|
        data = data.buffer;
 | 
						|
      }
 | 
						|
      if(binaryFeatures.useBlobBuilder) {
 | 
						|
        var builder = new BlobBuilder();
 | 
						|
        builder.append(data);
 | 
						|
        blob = builder.getBlob()
 | 
						|
      } else {
 | 
						|
        blob = new Blob([data]);
 | 
						|
      }
 | 
						|
      (new BlobReadStream(blob, {chunkSize: this._options.chunkSize})).pipe(stream);
 | 
						|
    } else {
 | 
						|
      stream.write(data);
 | 
						|
    }
 | 
						|
  }
 | 
						|
  return stream;
 | 
						|
};
 | 
						|
 | 
						|
BinaryClient.prototype._receiveStream = function(streamId){
 | 
						|
  var self = this;
 | 
						|
  var binaryStream = new BinaryStream(this._socket, streamId, false);
 | 
						|
  binaryStream.on('close', function(){
 | 
						|
    delete self.streams[streamId];
 | 
						|
  });
 | 
						|
  this.streams[streamId] = binaryStream;
 | 
						|
  return binaryStream;
 | 
						|
};
 | 
						|
 | 
						|
BinaryClient.prototype.createStream = function(meta){
 | 
						|
  if(this._socket.readyState !== WebSocket.OPEN) {
 | 
						|
    throw new Error('Client is not yet connected or has closed');
 | 
						|
    return;
 | 
						|
  }
 | 
						|
  var self = this;
 | 
						|
  var streamId = this._nextId;
 | 
						|
  this._nextId += 2;
 | 
						|
  var binaryStream = new BinaryStream(this._socket, streamId, true, meta);
 | 
						|
  binaryStream.on('close', function(){
 | 
						|
    delete self.streams[streamId];
 | 
						|
  });
 | 
						|
  this.streams[streamId] = binaryStream;
 | 
						|
  return binaryStream;
 | 
						|
};
 | 
						|
 | 
						|
BinaryClient.prototype.close = BinaryClient.prototype.destroy = function() {
 | 
						|
  this._socket.close();
 | 
						|
};
 | 
						|
 | 
						|
exports.BinaryClient = BinaryClient;
 | 
						|
 | 
						|
})(this);
 | 
						|
	
 | 
						|
</script> |