text: var NATIVE = require('./native')
  var ERRORS = require('./errors')
  
  function _Buffer (value) {
    return Buffer.isBuffer(value)
  }
  
  function Hex (value) {
    return typeof value === 'string' && /^([0-9a-f]{2})+$/i.test(value)
  }
  
  function _LengthN (type, length) {
    var name = type.toJSON()
  
    function Length (value) {
      if (!type(value)) return false
      if (value.length === length) return true
  
      throw ERRORS.tfCustomError(name + '(Length: ' + length + ')', name + '(Length: ' + value.length + ')')
    }
    Length.toJSON = function () { return name }
  
    return Length
  }
  
  var _ArrayN = _LengthN.bind(null, NATIVE.Array)
  var _BufferN = _LengthN.bind(null, _Buffer)
  var _HexN = _LengthN.bind(null, Hex)
  var _StringN = _LengthN.bind(null, NATIVE.String)
  
  function Range (a, b, f) {
    f = f || NATIVE.Number
    function _range (value, strict) {
      return f(value, strict) && (value > a) && (value < b)
    }
    _range.toJSON = function () {
      return `${f.toJSON()} between [${a}, ${b}]`
    }
    return _range
  }
  
  var UINT53_MAX = Math.pow(2, 53) - 1
  
  function Finite (value) {
    return typeof value === 'number' && isFinite(value)
  }
  function Int8 (value) { return ((value << 24) >> 24) === value }
  function Int16 (value) { return ((value << 16) >> 16) === value }
  function Int32 (value) { return (value | 0) === value }
  function UInt8 (value) { return (value & 0xff) === value }
  function UInt16 (value) { return (value & 0xffff) === value }
  function UInt32 (value) { return (value >>> 0) === value }
  function UInt53 (value) {
    return typeof value === 'number' &&
      value >= 0 &&
      value <= UINT53_MAX &&
      Math.floor(value) === value
  }
  
  var types = {
    ArrayN: _ArrayN,
    Buffer: _Buffer,
    BufferN: _BufferN,
    Finite: Finite,
    Hex: Hex,
    HexN: _HexN,
    Int8: Int8,
    Int16: Int16,
    Int32: Int32,
    Range: Range,
    StringN: _StringN,
    UInt8: UInt8,
    UInt16: UInt16,
    UInt32: UInt32,
    UInt53: UInt53
  }
  
  for (var typeName in types) {
    types[typeName].toJSON = function (t) {
      return t
    }.bind(null, typeName)
  }
  
  module.exports = types
  