text: var __importDefault = (this && this.__importDefault) || function (mod) {
      return (mod && mod.__esModule) ? mod : { "default": mod };
  };
  var __importStar = (this && this.__importStar) || function (mod) {
      if (mod && mod.__esModule) return mod;
      var result = {};
      if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
      result["default"] = mod;
      return result;
  };
  define(["require", "exports", "jsbi", "./JsbiSupport", "./IonBinary", "./IonUnicode", "./IonDecimal", "./IonTypes", "./IonConstants", "./IonTimestamp", "./SignAndMagnitudeInt", "./JsbiSerde"], function (require, exports, jsbi_1, JsbiSupport_1, IonBinary, IonUnicode_1, IonDecimal_1, IonTypes_1, IonConstants_1, IonTimestamp_1, SignAndMagnitudeInt_1, JsbiSerde_1) {
      "use strict";
      Object.defineProperty(exports, "__esModule", { value: true });
      jsbi_1 = __importDefault(jsbi_1);
      IonBinary = __importStar(IonBinary);
      SignAndMagnitudeInt_1 = __importDefault(SignAndMagnitudeInt_1);
      const DEBUG_FLAG = true;
      const EOF = -1;
      const ERROR = -2;
      const TB_UNUSED__ = 15;
      const TB_DATAGRAM = 20;
      const TB_SEXP_CLOSE = 21;
      const TB_LIST_CLOSE = 22;
      const TB_STRUCT_CLOSE = 23;
      function get_ion_type(rt) {
          switch (rt) {
              case IonBinary.TB_NULL: return IonTypes_1.IonTypes.NULL;
              case IonBinary.TB_BOOL: return IonTypes_1.IonTypes.BOOL;
              case IonBinary.TB_INT: return IonTypes_1.IonTypes.INT;
              case IonBinary.TB_NEG_INT: return IonTypes_1.IonTypes.INT;
              case IonBinary.TB_FLOAT: return IonTypes_1.IonTypes.FLOAT;
              case IonBinary.TB_DECIMAL: return IonTypes_1.IonTypes.DECIMAL;
              case IonBinary.TB_TIMESTAMP: return IonTypes_1.IonTypes.TIMESTAMP;
              case IonBinary.TB_SYMBOL: return IonTypes_1.IonTypes.SYMBOL;
              case IonBinary.TB_STRING: return IonTypes_1.IonTypes.STRING;
              case IonBinary.TB_CLOB: return IonTypes_1.IonTypes.CLOB;
              case IonBinary.TB_BLOB: return IonTypes_1.IonTypes.BLOB;
              case IonBinary.TB_SEXP: return IonTypes_1.IonTypes.SEXP;
              case IonBinary.TB_LIST: return IonTypes_1.IonTypes.LIST;
              case IonBinary.TB_STRUCT: return IonTypes_1.IonTypes.STRUCT;
              default: return undefined;
          }
      }
      const TS_SHIFT = 5;
      const TS_MASK = 0x1f;
      function encode_type_stack(type_, len) {
          var ts = (len << TS_SHIFT) | (type_ & TS_MASK);
          return ts;
      }
      function decode_type_stack_type(ts) {
          return ts & TS_MASK;
      }
      function decode_type_stack_len(ts) {
          return ts >>> TS_SHIFT;
      }
      const VINT_SHIFT = 7;
      const VINT_MASK = 0x7f;
      const VINT_FLAG = 0x80;
      function high_nibble(tb) {
          return ((tb >> IonBinary.TYPE_SHIFT) & IonBinary.NIBBLE_MASK);
      }
      function low_nibble(tb) {
          return (tb & IonBinary.NIBBLE_MASK);
      }
      const empty_array = [];
      const ivm_sid = IonConstants_1.IVM.sid;
      const ivm_image_0 = IonConstants_1.IVM.binary[0];
      const ivm_image_1 = IonConstants_1.IVM.binary[1];
      const ivm_image_2 = IonConstants_1.IVM.binary[2];
      const ivm_image_3 = IonConstants_1.IVM.binary[3];
      class ParserBinaryRaw {
          constructor(source) {
              this._raw_type = EOF;
              this._len = -1;
              this._curr = undefined;
              this._null = false;
              this._fid = -1;
              this._as = -1;
              this._ae = -1;
              this._a = [];
              this._ts = [TB_DATAGRAM];
              this._in_struct = false;
              this._in = source;
          }
          static _readFloatFrom(input, numberOfBytes) {
              let tempBuf;
              switch (numberOfBytes) {
                  case 0:
                      return 0.0;
                  case 4:
                      tempBuf = new DataView(input.chunk(4).buffer);
                      return tempBuf.getFloat32(0, false);
                  case 8:
                      tempBuf = new DataView(input.chunk(8).buffer);
                      return tempBuf.getFloat64(0, false);
                  case 15:
                      return null;
                  default:
                      throw new Error("Illegal float length: " + numberOfBytes);
              }
          }
          static _readVarUnsignedIntFrom(input) {
              let numberOfBits = 0;
              let byte;
              let magnitude = 0;
              while (true) {
                  byte = input.next();
                  magnitude = (magnitude << 7) | (byte & 0x7F);
                  numberOfBits += 7;
                  if (byte & 0x80) {
                      break;
                  }
              }
              if (numberOfBits > 31) {
                  throw new Error("VarUInt values larger than 31 bits must be read using LongInt.");
              }
              return magnitude;
          }
          static _readVarSignedIntFrom(input) {
              let v = input.next(), byte;
              let isNegative = v & 0x40;
              let stopBit = v & 0x80;
              v &= 0x3F;
              let bits = 6;
              while (!stopBit) {
                  byte = input.next();
                  stopBit = byte & 0x80;
                  byte &= 0x7F;
                  v <<= 7;
                  v |= byte;
                  bits += 7;
              }
              if (bits > 32) {
                  throw new Error("VarInt values larger than 32 bits must be read using LongInt");
              }
              return isNegative ? -v : v;
          }
          static _readSignedIntFrom(input, numberOfBytes) {
              if (numberOfBytes == 0) {
                  return new SignAndMagnitudeInt_1.default(JsbiSupport_1.JsbiSupport.ZERO);
              }
              let bytes = input.view(numberOfBytes);
              let isNegative = (bytes[0] & 0x80) == 0x80;
              let numbers = Array.prototype.slice.call(bytes);
              numbers[0] = bytes[0] & 0x7F;
              let magnitude = JsbiSerde_1.JsbiSerde.fromUnsignedBytes(numbers);
              return new SignAndMagnitudeInt_1.default(magnitude, isNegative);
          }
          static _readUnsignedIntAsBigIntFrom(input, numberOfBytes) {
              return JsbiSerde_1.JsbiSerde.fromUnsignedBytes(Array.prototype.slice.call(input.view(numberOfBytes)));
          }
          static _readUnsignedIntAsNumberFrom(input, numberOfBytes) {
              let value = 0;
              let bytesRead = 0;
              let bytesAvailable = input.getRemaining();
              let byte;
              if (numberOfBytes < 1) {
                  return 0;
              }
              else if (numberOfBytes > 6) {
                  throw new Error(`Attempted to read a ${numberOfBytes}-byte unsigned integer,`
                      + ` which is too large for a to be stored in a number without losing precision.`);
              }
              if (bytesAvailable < numberOfBytes) {
                  throw new Error(`Attempted to read a ${numberOfBytes}-byte unsigned integer,`
                      + ` but only ${bytesAvailable} bytes were available.`);
              }
              while (bytesRead < numberOfBytes) {
                  byte = input.next();
                  bytesRead++;
                  value *= 256;
                  value = value + byte;
              }
              return value;
          }
          static readDecimalValueFrom(input, numberOfBytes) {
              let initialPosition = input.position();
              let exponent = ParserBinaryRaw._readVarSignedIntFrom(input);
              let numberOfExponentBytes = input.position() - initialPosition;
              let numberOfCoefficientBytes = numberOfBytes - numberOfExponentBytes;
              let signedInt = ParserBinaryRaw._readSignedIntFrom(input, numberOfCoefficientBytes);
              let isNegative = signedInt.isNegative;
              let coefficient = isNegative ? jsbi_1.default.unaryMinus(signedInt.magnitude) : signedInt.magnitude;
              return IonDecimal_1.Decimal._fromBigIntCoefficient(isNegative, coefficient, exponent);
          }
          next() {
              if (this._curr === undefined && this._len > 0) {
                  this._in.skip(this._len);
              }
              else {
                  this.clear_value();
              }
              if (this._in_struct) {
                  this._fid = this.readVarUnsignedInt();
              }
              return this.load_next();
          }
          stepIn() {
              var len, ts, t = this;
              switch (t._raw_type) {
                  case IonBinary.TB_STRUCT:
                  case IonBinary.TB_LIST:
                  case IonBinary.TB_SEXP:
                      break;
                  default:
                      throw new Error("you can only 'stepIn' to a container");
              }
              len = t._in.getRemaining() - t._len;
              ts = encode_type_stack(t._raw_type, len);
              t._ts.push(ts);
              t._in_struct = (t._raw_type === IonBinary.TB_STRUCT);
              t._in.setRemaining(t._len);
              t.clear_value();
          }
          stepOut() {
              var parent_type, ts, l, r, t = this;
              if (t._ts.length < 2) {
                  throw new Error("you can't stepOut unless you stepped in");
              }
              ts = t._ts.pop();
              l = decode_type_stack_len(ts);
              parent_type = decode_type_stack_type(t._ts[t._ts.length - 1]);
              t._in_struct = (parent_type === IonBinary.TB_STRUCT);
              t.clear_value();
              r = t._in.getRemaining();
              t._in.skip(r);
              t._in.setRemaining(l);
          }
          isNull() {
              return this._null;
          }
          depth() {
              return this._ts.length - 1;
          }
          getFieldId() {
              return this._fid;
          }
          hasAnnotations() {
              return (this._as >= 0);
          }
          getAnnotations() {
              var a, t = this;
              if ((t._a === undefined) || (t._a.length === 0)) {
                  t.load_annotation_values();
              }
              return t._a;
          }
          getAnnotation(index) {
              var a, t = this;
              if ((t._a === undefined) || (t._a.length === 0)) {
                  t.load_annotation_values();
              }
              return t._a[index];
          }
          ionType() {
              return get_ion_type(this._raw_type);
          }
          _getSid() {
              this.load_value();
              if (this._raw_type == IonBinary.TB_SYMBOL) {
                  return this._curr === undefined ? null : this._curr;
              }
              return null;
          }
          _stringRepresentation() {
              let t = this;
              switch (t._raw_type) {
                  case IonBinary.TB_NULL:
                  case IonBinary.TB_BOOL:
                  case IonBinary.TB_INT:
                  case IonBinary.TB_NEG_INT:
                  case IonBinary.TB_FLOAT:
                  case IonBinary.TB_DECIMAL:
                  case IonBinary.TB_TIMESTAMP:
                  case IonBinary.TB_SYMBOL:
                  case IonBinary.TB_STRING:
                      break;
                  default:
                      throw new Error("Cannot convert to string.");
              }
              if (t.isNull()) {
                  switch (t._raw_type) {
                      case IonBinary.TB_BOOL:
                      case IonBinary.TB_INT:
                      case IonBinary.TB_NEG_INT:
                      case IonBinary.TB_FLOAT:
                      case IonBinary.TB_DECIMAL:
                      case IonBinary.TB_TIMESTAMP:
                      case IonBinary.TB_SYMBOL:
                      case IonBinary.TB_STRING:
                          "null." + t.ionType().name;
                          break;
                  }
              }
              else {
                  t.load_value();
                  switch (t._raw_type) {
                      case IonBinary.TB_BOOL:
                      case IonBinary.TB_INT:
                      case IonBinary.TB_NEG_INT:
                      case IonBinary.TB_DECIMAL:
                      case IonBinary.TB_TIMESTAMP:
                          return t._curr.toString();
                      case IonBinary.TB_FLOAT:
                          let s = t.numberValue().toString();
                          if (s.indexOf("e") === -1)
                              return s + "e0";
                      case IonBinary.TB_STRING:
                          if (t._null) {
                              return null;
                          }
                          return t._curr;
                  }
              }
          }
          byteValue() {
              switch (this._raw_type) {
                  case IonBinary.TB_NULL:
                      return null;
                  case IonBinary.TB_CLOB:
                  case IonBinary.TB_BLOB:
                      if (this.isNull()) {
                          return null;
                      }
                      this.load_value();
                      return this._curr;
                  default:
                      throw new Error('Current value is not a blob or clob.');
              }
          }
          booleanValue() {
              switch (this._raw_type) {
                  case IonBinary.TB_NULL:
                      return null;
                  case IonBinary.TB_BOOL:
                      if (this.isNull()) {
                          return null;
                      }
                      return this._curr;
              }
              throw new Error('Current value is not a Boolean.');
          }
          decimalValue() {
              switch (this._raw_type) {
                  case IonBinary.TB_NULL:
                      return null;
                  case IonBinary.TB_DECIMAL:
                      if (this.isNull()) {
                          return null;
                      }
                      this.load_value();
                      return this._curr;
              }
              throw new Error('Current value is not a decimal.');
          }
          bigIntValue() {
              switch (this._raw_type) {
                  case IonBinary.TB_NULL:
                      return null;
                  case IonBinary.TB_INT:
                  case IonBinary.TB_NEG_INT:
                      if (this.isNull()) {
                          return null;
                      }
                      this.load_value();
                      return this._curr;
                  default:
                      throw new Error('bigIntValue() was called when the current value was not an int.');
              }
          }
          numberValue() {
              switch (this._raw_type) {
                  case IonBinary.TB_NULL:
                      return null;
                  case IonBinary.TB_INT:
                  case IonBinary.TB_NEG_INT:
                      if (this.isNull()) {
                          return null;
                      }
                      this.load_value();
                      let bigInt = this._curr;
                      return JsbiSupport_1.JsbiSupport.clampToSafeIntegerRange(bigInt);
                  case IonBinary.TB_FLOAT:
                      if (this.isNull()) {
                          return null;
                      }
                      this.load_value();
                      return this._curr;
                  default:
                      throw new Error('Current value is not a float or int.');
              }
          }
          stringValue() {
              switch (this._raw_type) {
                  case IonBinary.TB_NULL:
                      return null;
                  case IonBinary.TB_STRING:
                  case IonBinary.TB_SYMBOL:
                      if (this.isNull()) {
                          return null;
                      }
                      this.load_value();
                      return this._curr;
              }
              throw new Error('Current value is not a string or symbol.');
          }
          timestampValue() {
              switch (this._raw_type) {
                  case IonBinary.TB_NULL:
                      return null;
                  case IonBinary.TB_TIMESTAMP:
                      if (this.isNull()) {
                          return null;
                      }
                      this.load_value();
                      return this._curr;
              }
              throw new Error('Current value is not a timestamp.');
          }
          read_binary_float() {
              return ParserBinaryRaw._readFloatFrom(this._in, this._len);
          }
          readVarUnsignedInt() {
              return ParserBinaryRaw._readVarUnsignedIntFrom(this._in);
          }
          readVarSignedInt() {
              return ParserBinaryRaw._readVarSignedIntFrom(this._in);
          }
          readUnsignedIntAsBigInt() {
              return ParserBinaryRaw._readUnsignedIntAsBigIntFrom(this._in, this._len);
          }
          readUnsignedIntAsNumber() {
              return ParserBinaryRaw._readUnsignedIntAsNumberFrom(this._in, this._len);
          }
          read_decimal_value() {
              return ParserBinaryRaw.readDecimalValueFrom(this._in, this._len);
          }
          read_timestamp_value() {
              if (!(this._len > 0)) {
                  return null;
              }
              let offset;
              let year;
              let month;
              let day;
              let hour;
              let minute;
              let secondInt;
              let fractionalSeconds = IonDecimal_1.Decimal.ZERO;
              let precision = IonTimestamp_1.TimestampPrecision.YEAR;
              let end = this._in.position() + this._len;
              offset = this.readVarSignedInt();
              if (this._in.position() < end) {
                  year = this.readVarUnsignedInt();
              }
              else {
                  throw new Error('Timestamps must include a year.');
              }
              if (this._in.position() < end) {
                  month = this.readVarUnsignedInt();
                  precision = IonTimestamp_1.TimestampPrecision.MONTH;
              }
              if (this._in.position() < end) {
                  day = this.readVarUnsignedInt();
                  precision = IonTimestamp_1.TimestampPrecision.DAY;
              }
              if (this._in.position() < end) {
                  hour = this.readVarUnsignedInt();
                  if (this._in.position() >= end) {
                      throw new Error('Timestamps with an hour must include a minute.');
                  }
                  else {
                      minute = this.readVarUnsignedInt();
                  }
                  precision = IonTimestamp_1.TimestampPrecision.HOUR_AND_MINUTE;
              }
              if (this._in.position() < end) {
                  secondInt = this.readVarUnsignedInt();
                  precision = IonTimestamp_1.TimestampPrecision.SECONDS;
              }
              if (this._in.position() < end) {
                  let exponent = this.readVarSignedInt();
                  let coefficient = JsbiSupport_1.JsbiSupport.ZERO;
                  let isNegative = false;
                  if (this._in.position() < end) {
                      let deserializedSignedInt = ParserBinaryRaw._readSignedIntFrom(this._in, end - this._in.position());
                      isNegative = deserializedSignedInt._isNegative;
                      coefficient = deserializedSignedInt._magnitude;
                  }
                  let dec = IonDecimal_1.Decimal._fromBigIntCoefficient(isNegative, coefficient, exponent);
                  let [_, fractionStr] = IonTimestamp_1.Timestamp._splitSecondsDecimal(dec);
                  fractionalSeconds = IonDecimal_1.Decimal.parse(secondInt + '.' + fractionStr);
              }
              let msSinceEpoch = Date.UTC(year, month ? month - 1 : 0, day ? day : 1, hour ? hour : 0, minute ? minute : 0, secondInt ? secondInt : 0, 0);
              msSinceEpoch = IonTimestamp_1.Timestamp._adjustMsSinceEpochIfNeeded(year, msSinceEpoch);
              let date = new Date(msSinceEpoch);
              return IonTimestamp_1.Timestamp._valueOf(date, offset, fractionalSeconds, precision);
          }
          read_string_value() {
              return IonUnicode_1.decodeUtf8(this._in.chunk(this._len));
          }
          clear_value() {
              this._raw_type = EOF;
              this._curr = undefined;
              this._a = empty_array;
              this._as = -1;
              this._null = false;
              this._fid = -1;
              this._len = -1;
          }
          load_length(tb) {
              let t = this;
              t._len = low_nibble(tb);
              switch (t._len) {
                  case 1:
                      if (high_nibble(tb) === IonBinary.TB_STRUCT) {
                          t._len = this.readVarUnsignedInt();
                      }
                      t._null = false;
                      break;
                  case IonBinary.LEN_VAR:
                      t._null = false;
                      t._len = this.readVarUnsignedInt();
                      break;
                  case IonBinary.LEN_NULL:
                      t._null = true;
                      t._len = 0;
                      break;
                  default:
                      t._null = false;
                      break;
              }
          }
          load_next() {
              let t = this;
              var rt, tb;
              t._as = -1;
              if (t._in.is_empty()) {
                  t.clear_value();
                  return undefined;
              }
              tb = t._in.next();
              rt = high_nibble(tb);
              t.load_length(tb);
              if (rt === IonBinary.TB_ANNOTATION) {
                  if (t._len < 1 && t.depth() === 0) {
                      rt = t.load_ivm();
                  }
                  else {
                      rt = t.load_annotations();
                  }
              }
              switch (rt) {
                  case IonBinary.TB_NULL:
                      t._null = true;
                      break;
                  case IonBinary.TB_BOOL:
                      if (t._len === 0 || t._len === 1) {
                          t._curr = t._len === 1;
                          t._len = 0;
                      }
                      break;
              }
              t._raw_type = rt;
              return rt;
          }
          load_annotations() {
              let t = this;
              var tb, type_, annotation_len;
              if (t._len < 1 && t.depth() === 0) {
                  type_ = t.load_ivm();
              }
              else {
                  annotation_len = this.readVarUnsignedInt();
                  t._as = t._in.position();
                  t._in.skip(annotation_len);
                  t._ae = t._in.position();
                  tb = t._in.next();
                  t.load_length(tb);
                  type_ = high_nibble(tb);
              }
              return type_;
          }
          load_ivm() {
              let t = this;
              var span = t._in;
              if (span.next() !== ivm_image_1)
                  throw new Error("invalid binary Ion at " + span.position());
              if (span.next() !== ivm_image_2)
                  throw new Error("invalid binary Ion at " + span.position());
              if (span.next() !== ivm_image_3)
                  throw new Error("invalid binary Ion at " + span.position());
              t._curr = ivm_sid;
              t._len = 0;
              return IonBinary.TB_SYMBOL;
          }
          load_annotation_values() {
              let t = this;
              var a, b, pos, limit, arr;
              if ((pos = t._as) < 0)
                  return;
              arr = [];
              limit = t._ae;
              a = 0;
              while (pos < limit) {
                  b = t._in.valueAt(pos);
                  pos++;
                  a = (a << VINT_SHIFT) | (b & VINT_MASK);
                  if ((b & VINT_FLAG) !== 0) {
                      arr.push(a);
                      a = 0;
                  }
              }
              t._a = arr;
          }
          _readIntegerMagnitude() {
              if (this._len === 0) {
                  return JsbiSupport_1.JsbiSupport.ZERO;
              }
              return this.readUnsignedIntAsBigInt();
          }
          load_value() {
              if (this._curr != undefined)
                  return;
              if (this.isNull())
                  return null;
              switch (this._raw_type) {
                  case IonBinary.TB_BOOL:
                      break;
                  case IonBinary.TB_INT:
                      this._curr = this._readIntegerMagnitude();
                      break;
                  case IonBinary.TB_NEG_INT:
                      this._curr = jsbi_1.default.unaryMinus(this._readIntegerMagnitude());
                      break;
                  case IonBinary.TB_FLOAT:
                      this._curr = this.read_binary_float();
                      break;
                  case IonBinary.TB_DECIMAL:
                      if (this._len === 0) {
                          this._curr = IonDecimal_1.Decimal.ZERO;
                      }
                      else {
                          this._curr = this.read_decimal_value();
                      }
                      break;
                  case IonBinary.TB_TIMESTAMP:
                      this._curr = this.read_timestamp_value();
                      break;
                  case IonBinary.TB_SYMBOL:
                      this._curr = this.readUnsignedIntAsNumber();
                      break;
                  case IonBinary.TB_STRING:
                      this._curr = this.read_string_value();
                      break;
                  case IonBinary.TB_CLOB:
                  case IonBinary.TB_BLOB:
                      if (this.isNull())
                          break;
                      this._curr = this._in.chunk(this._len);
                      break;
                  default:
                      throw new Error('Unexpected type: ' + this._raw_type);
              }
          }
      }
      exports.ParserBinaryRaw = ParserBinaryRaw;
  });
  //# sourceMappingURL=IonParserBinaryRaw.js.map