text: "use strict";
  var __extends = (this && this.__extends) || (function () {
      var extendStatics = function (d, b) {
          extendStatics = Object.setPrototypeOf ||
              ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
              function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
          return extendStatics(d, b);
      };
      return function (d, b) {
          if (typeof b !== "function" && b !== null)
              throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
          extendStatics(d, b);
          function __() { this.constructor = d; }
          d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
      };
  })();
  Object.defineProperty(exports, "__esModule", { value: true });
  exports.ArrayCoder = exports.unpack = exports.pack = void 0;
  var logger_1 = require("@ethersproject-bsc/logger");
  var _version_1 = require("../_version");
  var logger = new logger_1.Logger(_version_1.version);
  var abstract_coder_1 = require("./abstract-coder");
  var anonymous_1 = require("./anonymous");
  function pack(writer, coders, values) {
      var arrayValues = null;
      if (Array.isArray(values)) {
          arrayValues = values;
      }
      else if (values && typeof (values) === "object") {
          var unique_1 = {};
          arrayValues = coders.map(function (coder) {
              var name = coder.localName;
              if (!name) {
                  logger.throwError("cannot encode object for signature with missing names", logger_1.Logger.errors.INVALID_ARGUMENT, {
                      argument: "values",
                      coder: coder,
                      value: values
                  });
              }
              if (unique_1[name]) {
                  logger.throwError("cannot encode object for signature with duplicate names", logger_1.Logger.errors.INVALID_ARGUMENT, {
                      argument: "values",
                      coder: coder,
                      value: values
                  });
              }
              unique_1[name] = true;
              return values[name];
          });
      }
      else {
          logger.throwArgumentError("invalid tuple value", "tuple", values);
      }
      if (coders.length !== arrayValues.length) {
          logger.throwArgumentError("types/value length mismatch", "tuple", values);
      }
      var staticWriter = new abstract_coder_1.Writer(writer.wordSize);
      var dynamicWriter = new abstract_coder_1.Writer(writer.wordSize);
      var updateFuncs = [];
      coders.forEach(function (coder, index) {
          var value = arrayValues[index];
          if (coder.dynamic) {
              // Get current dynamic offset (for the future pointer)
              var dynamicOffset_1 = dynamicWriter.length;
              // Encode the dynamic value into the dynamicWriter
              coder.encode(dynamicWriter, value);
              // Prepare to populate the correct offset once we are done
              var updateFunc_1 = staticWriter.writeUpdatableValue();
              updateFuncs.push(function (baseOffset) {
                  updateFunc_1(baseOffset + dynamicOffset_1);
              });
          }
          else {
              coder.encode(staticWriter, value);
          }
      });
      // Backfill all the dynamic offsets, now that we know the static length
      updateFuncs.forEach(function (func) { func(staticWriter.length); });
      var length = writer.appendWriter(staticWriter);
      length += writer.appendWriter(dynamicWriter);
      return length;
  }
  exports.pack = pack;
  function unpack(reader, coders) {
      var values = [];
      // A reader anchored to this base
      var baseReader = reader.subReader(0);
      coders.forEach(function (coder) {
          var value = null;
          if (coder.dynamic) {
              var offset = reader.readValue();
              var offsetReader = baseReader.subReader(offset.toNumber());
              try {
                  value = coder.decode(offsetReader);
              }
              catch (error) {
                  // Cannot recover from this
                  if (error.code === logger_1.Logger.errors.BUFFER_OVERRUN) {
                      throw error;
                  }
                  value = error;
                  value.baseType = coder.name;
                  value.name = coder.localName;
                  value.type = coder.type;
              }
          }
          else {
              try {
                  value = coder.decode(reader);
              }
              catch (error) {
                  // Cannot recover from this
                  if (error.code === logger_1.Logger.errors.BUFFER_OVERRUN) {
                      throw error;
                  }
                  value = error;
                  value.baseType = coder.name;
                  value.name = coder.localName;
                  value.type = coder.type;
              }
          }
          if (value != undefined) {
              values.push(value);
          }
      });
      // We only output named properties for uniquely named coders
      var uniqueNames = coders.reduce(function (accum, coder) {
          var name = coder.localName;
          if (name) {
              if (!accum[name]) {
                  accum[name] = 0;
              }
              accum[name]++;
          }
          return accum;
      }, {});
      // Add any named parameters (i.e. tuples)
      coders.forEach(function (coder, index) {
          var name = coder.localName;
          if (!name || uniqueNames[name] !== 1) {
              return;
          }
          if (name === "length") {
              name = "_length";
          }
          if (values[name] != null) {
              return;
          }
          var value = values[index];
          if (value instanceof Error) {
              Object.defineProperty(values, name, {
                  get: function () { throw value; }
              });
          }
          else {
              values[name] = value;
          }
      });
      var _loop_1 = function (i) {
          var value = values[i];
          if (value instanceof Error) {
              Object.defineProperty(values, i, {
                  get: function () { throw value; }
              });
          }
      };
      for (var i = 0; i < values.length; i++) {
          _loop_1(i);
      }
      return Object.freeze(values);
  }
  exports.unpack = unpack;
  var ArrayCoder = /** @class */ (function (_super) {
      __extends(ArrayCoder, _super);
      function ArrayCoder(coder, length, localName) {
          var _this = this;
          var type = (coder.type + "[" + (length >= 0 ? length : "") + "]");
          var dynamic = (length === -1 || coder.dynamic);
          _this = _super.call(this, "array", type, localName, dynamic) || this;
          _this.coder = coder;
          _this.length = length;
          return _this;
      }
      ArrayCoder.prototype.defaultValue = function () {
          // Verifies the child coder is valid (even if the array is dynamic or 0-length)
          var defaultChild = this.coder.defaultValue();
          var result = [];
          for (var i = 0; i < this.length; i++) {
              result.push(defaultChild);
          }
          return result;
      };
      ArrayCoder.prototype.encode = function (writer, value) {
          if (!Array.isArray(value)) {
              this._throwError("expected array value", value);
          }
          var count = this.length;
          if (count === -1) {
              count = value.length;
              writer.writeValue(value.length);
          }
          logger.checkArgumentCount(value.length, count, "coder array" + (this.localName ? (" " + this.localName) : ""));
          var coders = [];
          for (var i = 0; i < value.length; i++) {
              coders.push(this.coder);
          }
          return pack(writer, coders, value);
      };
      ArrayCoder.prototype.decode = function (reader) {
          var count = this.length;
          if (count === -1) {
              count = reader.readValue().toNumber();
          }
          var coders = [];
          for (var i = 0; i < count; i++) {
              coders.push(new anonymous_1.AnonymousCoder(this.coder));
          }
          return reader.coerce(this.name, unpack(reader, coders));
      };
      return ArrayCoder;
  }(abstract_coder_1.Coder));
  exports.ArrayCoder = ArrayCoder;
  //# sourceMappingURL=array.js.map