protected function processRules(string $field, string $label = null, $value, $rules = null, array $data): bool
	{
		// If the if_exist rule is defined...
		if (in_array('if_exist', $rules))
		{
			// and the current field does not exists in the input data
			// we can return true. Ignoring all other rules to this field.
			if (! array_key_exists($field, $data))
			{
				return true;
			}
			// Otherwise remove the if_exist rule and continue the process
			$rules = array_diff($rules, ['if_exist']);
		}

		if (in_array('permit_empty', $rules))
		{
			if (! in_array('required', $rules) && (is_array($value) ? empty($value) : (trim($value) === '')))
			{
				return true;
			}

			$rules = array_diff($rules, ['permit_empty']);
		}

		foreach ($rules as $rule)
		{
			$callable = is_callable($rule);
			$passed   = false;

			// Rules can contain parameters: max_length[5]
			$param = false;
			if (! $callable && preg_match('/(.*?)\[(.*)\]/', $rule, $match))
			{
				$rule  = $match[1];
				$param = $match[2];
			}

			// Placeholder for custom errors from the rules.
			$error = null;

			// If it's a callable, call and and get out of here.
			if ($callable)
			{
				$passed = $param === false ? $rule($value) : $rule($value, $param, $data);
			}
			else
			{
				$found = false;

				// Check in our rulesets
				foreach ($this->ruleSetInstances as $set)
				{
					if (! method_exists($set, $rule))
					{
						continue;
					}

					$found = true;

					$passed = $param === false ? $set->$rule($value, $error)
						: $set->$rule($value, $param, $data, $error);
					break;
				}

				// If the rule wasn't found anywhere, we
				// should throw an exception so the developer can find it.
				if (! $found)
				{
					throw ValidationException::forRuleNotFound($rule);
				}
			}

			// Set the error message if we didn't survive.
			if ($passed === false)
			{
				$this->errors[$field] = is_null($error) ? $this->getErrorMessage($rule, $field, $label, $param)
					: $error;

				return false;
			}
		}

		return true;
	}