text: "use strict";
  
  Object.defineProperty(exports, "__esModule", { value: true });
  
  var errorsExports = require("./error");
  var MetadataUtils = require("./metadata");
  var type = require("./type");
  
  function validate(name, specs, passed) {
      var minArgs = specs.length;
      var maxArgs = specs.length;
      for (var i = 0; i < specs.length; i++) {
          if (specs[i].optional) {
              minArgs = i;
              break;
          }
      }
      var validLength = minArgs <= passed.length && passed.length <= maxArgs;
      if (!validLength) {
          throw errorsExports.invalidArgumentCount(minArgs, maxArgs, name, passed.length);
      }
      for (var i = 0; i < passed.length; i++) {
          try {
              specs[i].validator(passed[i]);
          } catch (e) {
              if (e instanceof Error) {
                  throw errorsExports.invalidArgument(i, name, e.message);
              } else {
                  throw errorsExports.invalidArgument(i, name, e);
              }
          }
      }
  }
  exports.validate = validate;
  
  var ArgSpec = function () {
      function ArgSpec(validator, opt_optional) {
          var self = this;
          this.validator = function (p) {
              if (self.optional && !type.isJustDef(p)) {
                  return;
              }
              validator(p);
          };
          this.optional = !!opt_optional;
      }
      return ArgSpec;
  }();
  exports.ArgSpec = ArgSpec;
  function and_(v1, v2) {
      return function (p) {
          v1(p);
          v2(p);
      };
  }
  exports.and_ = and_;
  function stringSpec(opt_validator, opt_optional) {
      function stringValidator(p) {
          if (!type.isString(p)) {
              throw 'Expected string.';
          }
      }
      var validator;
      if (opt_validator) {
          validator = and_(stringValidator, opt_validator);
      } else {
          validator = stringValidator;
      }
      return new ArgSpec(validator, opt_optional);
  }
  exports.stringSpec = stringSpec;
  function uploadDataSpec() {
      function validator(p) {
          var valid = p instanceof Uint8Array || p instanceof ArrayBuffer || type.isNativeBlobDefined() && p instanceof Blob;
          if (!valid) {
              throw 'Expected Blob or File.';
          }
      }
      return new ArgSpec(validator);
  }
  exports.uploadDataSpec = uploadDataSpec;
  function metadataSpec(opt_optional) {
      return new ArgSpec(MetadataUtils.metadataValidator, opt_optional);
  }
  exports.metadataSpec = metadataSpec;
  function nonNegativeNumberSpec() {
      function validator(p) {
          var valid = type.isNumber(p) && p >= 0;
          if (!valid) {
              throw 'Expected a number 0 or greater.';
          }
      }
      return new ArgSpec(validator);
  }
  exports.nonNegativeNumberSpec = nonNegativeNumberSpec;
  function looseObjectSpec(opt_validator, opt_optional) {
      function validator(p) {
          var isLooseObject = p === null || type.isDef(p) && p instanceof Object;
          if (!isLooseObject) {
              throw 'Expected an Object.';
          }
          if (opt_validator !== undefined && opt_validator !== null) {
              opt_validator(p);
          }
      }
      return new ArgSpec(validator, opt_optional);
  }
  exports.looseObjectSpec = looseObjectSpec;
  function nullFunctionSpec(opt_optional) {
      function validator(p) {
          var valid = p === null || type.isFunction(p);
          if (!valid) {
              throw 'Expected a Function.';
          }
      }
      return new ArgSpec(validator, opt_optional);
  }
  exports.nullFunctionSpec = nullFunctionSpec;