# File lib/stringvalidator.rb, line 172
  def self.validate(rule, str)
    if rule == Integer then
      begin
        return Integer(str)
      rescue ArgumentError
        raise Error::NotInteger.new(str, rule)
      end
    end
    if rule == Float then
      begin
        return Float(str)
      rescue ArgumentError
        raise Error::NotFloat.new(str, rule)
      end
    end
    case rule
    when Range then
      if rule.first.is_a? Integer and rule.last.is_a? Integer then
        validate(Integer, str)
        raise Error::OutOfRange.new(str, rule) unless rule.include?(str.to_i)
        return str.to_i
      elsif rule.first.is_a? Numeric then
        validate(Float, str)
        raise Error::OutOfRange.new(str, rule) unless rule.include?(str.to_f)
        return str.to_f
      end
      raise  Error::OutOfRange.new(str, rule) unless rule.include?(str)
      return str
    when Regexp then
      raise Error::RegexpMismatch.new(str, rule) unless rule =~ str
      return str
    when Proc then
      ret = rule.call(str)
      return ret if ret
      raise Error::InvalidValue.new(str, rule)
    when Array then
      rule.each do |i|
        begin
          return self.validate(i, str)
        rescue Error
          nil
        end
      end
      raise Error::InvalidValue.new(str, rule)
    when Hash then
      ret = {}
      rule.each do |k,v|
        case k
        when :any
          ret[k] = self.validate(v, str)
        when :all
          ret[k] = v.map do |i|
            self.validate(i, str)
          end
        when :rule
          ret[k] = self.validate(v, str)
        when :length
          begin
            self.validate v, str.length.to_s
            ret[k] = str
          rescue Error
            raise Error::InvalidLength.new(str, rule)
          end
        when :maxlength
          raise Error::TooLong.new(str, rule) unless str.length <= v
          ret[k] = str
        when :minlength
          raise Error::TooShort.new(str, rule) unless str.length >= v
          ret[k] = str
        when :charlength
          begin
            self.validate v, str.split(//).length.to_s
            ret[k] = str
          rescue Error
            raise Error::InvalidLength.new(str, rule)
          end
        when :maxcharlength
          raise Error::TooLong.new(str, rule) unless str.split(//).length <= v
          ret[k] = str
        when :mincharlength
          raise Error::TooShort.new(str, rule) unless str.split(//).length >= v
          ret[k] = str
        else
          raise ArgumentError, "Invalid key: #{k}"
        end
      end
      return ret
    when Class then
      begin
        return rule.new(str)
      rescue
        raise Error::InvalidValue.new(str, rule)
      end
    else
      return rule if rule.to_s == str
    end
    raise Error::InvalidValue.new(str, rule)
  end