text: // Generated by IcedCoffeeScript 1.7.1-b
  (function() {
    var C, PpBuffer, U32MAX, Unpacker, bufeq, default_ext, modes, pack, pow2, twos_compl_inv, _ref, _ref1;
  
    C = require('./const').C;
  
    _ref = require('./buffer'), bufeq = _ref.bufeq, PpBuffer = _ref.PpBuffer;
  
    _ref1 = require('./util'), pow2 = _ref1.pow2, twos_compl_inv = _ref1.twos_compl_inv, U32MAX = _ref1.U32MAX;
  
    pack = require('./pack').pack;
  
    modes = {
      NONE: 0,
      BINARY: 1,
      START: 2
    };
  
    default_ext = function(type, raw) {
      return {
        type: type,
        raw: raw
      };
    };
  
    exports.Unpacker = Unpacker = (function() {
      function Unpacker(b, _opts) {
        this._opts = _opts != null ? _opts : {};
        this._orig_buffer = b;
        this._buffer = new PpBuffer(b);
        this._ext = this._opts.ext || (this._opts.no_ext ? null : default_ext);
      }
  
      Unpacker.prototype.u_buf = function(n) {
        return this._buffer.read_buffer(n);
      };
  
      Unpacker.prototype.u_str = function(n) {
        return this.u_buf(n).toString('utf8');
      };
  
      Unpacker.prototype.u_bin = function(n) {
        return this.u_buf(n);
      };
  
      Unpacker.prototype.u_ext = function(n) {
        var buf, typ;
        typ = this.u_uint8();
        buf = this.u_buf(n);
        if (this._opts.ext != null) {
          return this._opts.ext(typ, buf);
        } else {
          throw new Error("No ext hook but got message type: " + typ);
        }
      };
  
      Unpacker.prototype.u_array = function(n) {
        var i, _i, _results;
        _results = [];
        for (i = _i = 0; 0 <= n ? _i < n : _i > n; i = 0 <= n ? ++_i : --_i) {
          _results.push(this.u());
        }
        return _results;
      };
  
      Unpacker.prototype.u_map = function(n) {
        var i, key, keys, ret, _i, _j, _ref2;
        ret = {};
        keys = [];
        for (i = _i = 0; 0 <= n ? _i < n : _i > n; i = 0 <= n ? ++_i : --_i) {
          key = this.u();
          keys.push(key);
          if (ret[key] != null) {
            throw new Error("duplicate key '" + key + "'");
          }
          ret[key] = this.u();
        }
        if (this._opts.strict) {
          for (i = _j = 0, _ref2 = keys.length - 1; 0 <= _ref2 ? _j < _ref2 : _j > _ref2; i = 0 <= _ref2 ? ++_j : --_j) {
            if (keys[i] > keys[i + 1]) {
              throw new Error("unsorted object keys in strict mode: " + keys[i] + " > " + keys[i + 1]);
            }
          }
        }
        return ret;
      };
  
      Unpacker.prototype.u_uint8 = function() {
        return this._buffer.read_uint8();
      };
  
      Unpacker.prototype.u_uint16 = function() {
        return this._buffer.read_uint16();
      };
  
      Unpacker.prototype.u_uint32 = function() {
        return this._buffer.read_uint32();
      };
  
      Unpacker.prototype.u_int8 = function() {
        return this._buffer.read_int8();
      };
  
      Unpacker.prototype.u_int16 = function() {
        return this._buffer.read_int16();
      };
  
      Unpacker.prototype.u_int32 = function() {
        return this._buffer.read_int32();
      };
  
      Unpacker.prototype.u_uint64 = function() {
        return (this.u_uint32() * U32MAX) + this.u_uint32();
      };
  
      Unpacker.prototype.u_double = function() {
        return this._buffer.read_float64();
      };
  
      Unpacker.prototype.u_float = function() {
        return this._buffer.read_float32();
      };
  
      Unpacker.prototype.u_int64 = function() {
        var a, b, i, _ref2;
        _ref2 = (function() {
          var _i, _results;
          _results = [];
          for (i = _i = 0; _i < 2; i = ++_i) {
            _results.push(this.u_uint32());
          }
          return _results;
        }).call(this), a = _ref2[0], b = _ref2[1];
        return U32MAX * (a - U32MAX) + b;
      };
  
      Unpacker.prototype.u = function() {
        var b, l;
        if ((b = this.u_uint8()) <= C.positive_fix_max) {
          return b;
        } else if (b >= C.negative_fix_min && b <= C.negative_fix_max) {
          return twos_compl_inv(b, 8);
        } else if (b >= C.fix_str_min && b <= C.fix_str_max) {
          l = b & C.fix_str_count_mask;
          return this.u_str(l);
        } else if (b >= C.fix_array_min && b <= C.fix_array_max) {
          l = b & C.fix_array_count_mask;
          return this.u_array(l);
        } else if (b >= C.fix_map_min && b <= C.fix_map_max) {
          l = b & C.fix_map_count_mask;
          return this.u_map(l);
        } else {
          switch (b) {
            case C["null"]:
              return null;
            case C["true"]:
              return true;
            case C["false"]:
              return false;
            case C.uint8:
              return this.u_uint8();
            case C.uint16:
              return this.u_uint16();
            case C.uint32:
              return this.u_uint32();
            case C.uint64:
              return this.u_uint64();
            case C.int8:
              return this.u_int8();
            case C.int16:
              return this.u_int16();
            case C.int32:
              return this.u_int32();
            case C.int64:
              return this.u_int64();
            case C.double:
              return this.u_double();
            case C.float:
              return this.u_float();
            case C.str8:
              return this.u_str(this.u_uint8());
            case C.str16:
              return this.u_str(this.u_uint16());
            case C.str32:
              return this.u_str(this.u_uint32());
            case C.bin8:
              return this.u_bin(this.u_uint8());
            case C.bin16:
              return this.u_bin(this.u_uint16());
            case C.bin32:
              return this.u_bin(this.u_uint32());
            case C.array16:
              return this.u_array(this.u_uint16());
            case C.array32:
              return this.u_array(this.u_uint32());
            case C.map16:
              return this.u_map(this.u_uint16());
            case C.map32:
              return this.u_map(this.u_uint32());
            case C.fix_ext1:
              return this.u_ext(1);
            case C.fix_ext2:
              return this.u_ext(2);
            case C.fix_ext4:
              return this.u_ext(4);
            case C.fix_ext8:
              return this.u_ext(8);
            case C.fix_ext16:
              return this.u_ext(16);
            case C.ext8:
              return this.u_ext(this.u_uint8());
            case C.ext16:
              return this.u_ext(this.u_uint16());
            case C.ext32:
              return this.u_ext(this.u_uint32());
            default:
              throw new Error("unhandled type " + b);
          }
        }
      };
  
      Unpacker.prototype.unpack = function() {
        var a, b, our_encoding, res;
        res = this.u();
        if (this._opts.strict) {
          our_encoding = pack(res, {
            sort_keys: true
          });
          if ((a = our_encoding.length) !== (b = this._orig_buffer.length)) {
            throw new Error("encoding size mismatch: wanted " + a + " but got " + b);
          } else if (!bufeq(our_encoding, this._orig_buffer)) {
            throw new Error("Got non-standard encoding in strict mode");
          }
        }
        return res;
      };
  
      return Unpacker;
  
    })();
  
    exports.unpack = function(x, opts) {
      var unpacker;
      if (opts == null) {
        opts = {};
      }
      unpacker = new Unpacker(x, opts);
      return unpacker.unpack();
    };
  
  }).call(this);
  