text: // Copyright (c) 2012, Mark Cavage. All rights reserved.
  // Copyright 2021 Joyent, Inc.
  
  var assert = require('assert');
  var Stream = require('stream').Stream;
  var util = require('util');
  
  
  ///--- Globals
  
  /* JSSTYLED */
  var UUID_REGEXP = /^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}$/;
  
  
  ///--- Internal
  
  function _capitalize(str) {
      return (str.charAt(0).toUpperCase() + str.slice(1));
  }
  
  function _toss(name, expected, oper, arg, actual) {
      throw new assert.AssertionError({
          message: util.format('%s (%s) is required', name, expected),
          actual: (actual === undefined) ? typeof (arg) : actual(arg),
          expected: expected,
          operator: oper || '===',
          stackStartFunction: _toss.caller
      });
  }
  
  function _getClass(arg) {
      return (Object.prototype.toString.call(arg).slice(8, -1));
  }
  
  function noop() {
      // Why even bother with asserts?
  }
  
  
  ///--- Exports
  
  var types = {
      bool: {
          check: function (arg) { return typeof (arg) === 'boolean'; }
      },
      func: {
          check: function (arg) { return typeof (arg) === 'function'; }
      },
      string: {
          check: function (arg) { return typeof (arg) === 'string'; }
      },
      object: {
          check: function (arg) {
              return typeof (arg) === 'object' && arg !== null;
          }
      },
      number: {
          check: function (arg) {
              return typeof (arg) === 'number' && !isNaN(arg);
          }
      },
      finite: {
          check: function (arg) {
              return typeof (arg) === 'number' && !isNaN(arg) && isFinite(arg);
          }
      },
      buffer: {
          check: function (arg) { return Buffer.isBuffer(arg); },
          operator: 'Buffer.isBuffer'
      },
      array: {
          check: function (arg) { return Array.isArray(arg); },
          operator: 'Array.isArray'
      },
      stream: {
          check: function (arg) { return arg instanceof Stream; },
          operator: 'instanceof',
          actual: _getClass
      },
      date: {
          check: function (arg) { return arg instanceof Date; },
          operator: 'instanceof',
          actual: _getClass
      },
      regexp: {
          check: function (arg) { return arg instanceof RegExp; },
          operator: 'instanceof',
          actual: _getClass
      },
      uuid: {
          check: function (arg) {
              return typeof (arg) === 'string' && UUID_REGEXP.test(arg);
          },
          operator: 'isUUID'
      }
  };
  
  function _setExports(ndebug) {
      var keys = Object.keys(types);
      var out;
  
      /* re-export standard assert */
      if (process.env.NODE_NDEBUG) {
          out = noop;
      } else {
          out = function (arg, msg) {
              if (!arg) {
                  _toss(msg, 'true', arg);
              }
          };
      }
  
      /* standard checks */
      keys.forEach(function (k) {
          if (ndebug) {
              out[k] = noop;
              return;
          }
          var type = types[k];
          out[k] = function (arg, msg) {
              if (!type.check(arg)) {
                  _toss(msg, k, type.operator, arg, type.actual);
              }
          };
      });
  
      /* optional checks */
      keys.forEach(function (k) {
          var name = 'optional' + _capitalize(k);
          if (ndebug) {
              out[name] = noop;
              return;
          }
          var type = types[k];
          out[name] = function (arg, msg) {
              if (arg === undefined || arg === null) {
                  return;
              }
              if (!type.check(arg)) {
                  _toss(msg, k, type.operator, arg, type.actual);
              }
          };
      });
  
      /* arrayOf checks */
      keys.forEach(function (k) {
          var name = 'arrayOf' + _capitalize(k);
          if (ndebug) {
              out[name] = noop;
              return;
          }
          var type = types[k];
          var expected = '[' + k + ']';
          out[name] = function (arg, msg) {
              if (!Array.isArray(arg)) {
                  _toss(msg, expected, type.operator, arg, type.actual);
              }
              var i;
              for (i = 0; i < arg.length; i++) {
                  if (!type.check(arg[i])) {
                      _toss(msg, expected, type.operator, arg, type.actual);
                  }
              }
          };
      });
  
      /* optionalArrayOf checks */
      keys.forEach(function (k) {
          var name = 'optionalArrayOf' + _capitalize(k);
          if (ndebug) {
              out[name] = noop;
              return;
          }
          var type = types[k];
          var expected = '[' + k + ']';
          out[name] = function (arg, msg) {
              if (arg === undefined || arg === null) {
                  return;
              }
              if (!Array.isArray(arg)) {
                  _toss(msg, expected, type.operator, arg, type.actual);
              }
              var i;
              for (i = 0; i < arg.length; i++) {
                  if (!type.check(arg[i])) {
                      _toss(msg, expected, type.operator, arg, type.actual);
                  }
              }
          };
      });
  
      /* re-export built-in assertions */
      Object.keys(assert).forEach(function (k) {
          if (k === 'AssertionError') {
              out[k] = assert[k];
              return;
          }
          if (ndebug) {
              out[k] = noop;
              return;
          }
          out[k] = assert[k];
      });
  
      /* export ourselves (for unit tests _only_) */
      out._setExports = _setExports;
  
      return out;
  }
  
  module.exports = _setExports(process.env.NODE_NDEBUG);
  