# File lib/kwalify/validator.rb, line 75
    def _validate(value, rule, path, errors, done, uniq_table, recursive=true)
      #if Types.collection?(value)
      if !Types.scalar?(value)
        #if done[value.__id__]
        #  rule2 = done[value.__id__]
        #  if rule2.is_a?(Rule)
        #    return if rule.equal?(rule2)
        #    done[value.__id__] = [rule2, rule]
        #  elsif rule2.is_a?(Array)
        #    return if rule2.any? {|r| r.equal?(rule)}
        #    done[value.__id__] << rule
        #  else
        #    raise "unreachable"
        #  end
        #end
        return if done[value.__id__]     # avoid infinite loop
        done[value.__id__] = rule
      end
      if rule.required && value.nil?
        #* key=:required_novalue  msg="value required but none."
        errors << validate_error(:required_novalue, rule, path, value)
        return
      end
      if rule.type_class && !value.nil? && !value.is_a?(rule.type_class)
        unless rule.classobj && value.is_a?(rule.classobj)
          #* key=:type_unmatch  msg="not a %s."
          errors << validate_error(:type_unmatch, rule, path, value, [Kwalify.word(rule.type)])
          return
        end
      end
      #
      n = errors.length
      if rule.sequence
        _validate_sequence(value, rule, path, errors, done, uniq_table, recursive)
      elsif rule.mapping
        _validate_mapping(value, rule, path, errors, done, uniq_table, recursive)
      else
        _validate_scalar(value, rule, path, errors, done, uniq_table)
      end
      return unless errors.length == n
      #
      #path_str = path.is_a?(Array) ? '/'+path.join('/') : path
      #validate_hook(value, rule, path_str, errors)
      #@block.call(value, rule, path_str, errors) if @block
      validate_hook(value, rule, path, errors)
      @block.call(value, rule, path, errors) if @block
    end