Skip to content

Commit

Permalink
All rules initialize Type lazily
Browse files Browse the repository at this point in the history
  • Loading branch information
mabar committed Jan 1, 2025
1 parent 1796ba2 commit 404ac47
Show file tree
Hide file tree
Showing 6 changed files with 48 additions and 20 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
- `ReflectorMetaSource` is marked as `@internal`
- `Rule`
- `resolveArgs()` accepts `ArgsFieldContext` instead of `ArgsContext`
- all rules initialize `Type` lazily (performance optimization)
- `ArrayOfRule`
- check during metadata parsing that default value is an array when `mergeDefaults` is enabled

Expand Down
6 changes: 4 additions & 2 deletions src/Rules/AllOfRule.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,12 @@ final class AllOfRule extends CompoundRule
public function processValue($value, Args $args, FieldContext $context)
{
$initValue = $value;
$type = $this->createType($args, $context);
$type = null;
$anyValidationFailed = false;

foreach ($args->rules as $key => $nestedRuleMeta) {
if ($anyValidationFailed) {
$type ??= $this->createType($args, $context);
$type->setSubtypeSkipped($key);

continue;
Expand All @@ -43,12 +44,13 @@ public function processValue($value, Args $args, FieldContext $context)
);
} catch (ValueDoesNotMatch | InvalidData $exception) {
$exception->dropValue(); // May be mutated by rules
$type ??= $this->createType($args, $context);
$type->overwriteInvalidSubtype($key, $exception);
$anyValidationFailed = true;
}
}

if ($anyValidationFailed) {
if ($type !== null && $anyValidationFailed) {
throw ValueDoesNotMatch::create($type, Value::of($initValue));
}

Expand Down
6 changes: 4 additions & 2 deletions src/Rules/AnyOfRule.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,12 @@ final class AnyOfRule extends CompoundRule
*/
public function processValue($value, Args $args, FieldContext $context)
{
$type = $this->createType($args, $context);
$type = null;
$anyValidationSucceeded = false;

foreach ($args->rules as $key => $nestedRuleMeta) {
if ($anyValidationSucceeded) {
$type ??= $this->createType($args, $context);
$type->setSubtypeSkipped($key);

continue;
Expand All @@ -43,11 +44,12 @@ public function processValue($value, Args $args, FieldContext $context)

$anyValidationSucceeded = true;
} catch (ValueDoesNotMatch | InvalidData $exception) {
$type ??= $this->createType($args, $context);
$type->overwriteInvalidSubtype($key, $exception);
}
}

if (!$anyValidationSucceeded) {
if ($type !== null && !$anyValidationSucceeded) {
throw ValueDoesNotMatch::create($type, Value::none());
}

Expand Down
18 changes: 15 additions & 3 deletions src/Rules/ArrayOfRule.php
Original file line number Diff line number Diff line change
Expand Up @@ -103,19 +103,23 @@ public function getArgsType(): string
public function processValue($value, Args $args, FieldContext $context): array
{
$initValue = $value;
$type = $this->createType($args, $context);

if (!is_array($value)) {
$type = $this->createType($args, $context);
$type->markInvalid();

throw ValueDoesNotMatch::create($type, Value::of($initValue));
}

$type = null;

if ($args->minItems !== null && count($value) < $args->minItems) {
$type = $this->createType($args, $context);
$type->markParameterInvalid(self::MinItems);
}

if ($args->maxItems !== null && count($value) > $args->maxItems) {
$type ??= $this->createType($args, $context);
$type->markParameterInvalid(self::MaxItems);

throw ValueDoesNotMatch::create($type, Value::of($initValue));
Expand All @@ -142,6 +146,7 @@ public function processValue($value, Args $args, FieldContext $context): array
try {
$key = $keyRule->processValue($key, $keyArgs, $context->createClone());
} catch (ValueDoesNotMatch | InvalidData $exception) {
$type ??= $this->createType($args, $context);
$type->addInvalidKey($key, $exception);
}
}
Expand All @@ -153,6 +158,7 @@ public function processValue($value, Args $args, FieldContext $context): array
$context->createClone(),
);
} catch (ValueDoesNotMatch | InvalidData $exception) {
$type ??= $this->createType($args, $context);
$type->addInvalidValue($key, $exception);
// Remove invalid value because only valid values are expected beyond this point
// Invalid keys are fine because we don't work them beyond
Expand All @@ -170,12 +176,18 @@ public function processValue($value, Args $args, FieldContext $context): array
$context->createClone(),
);
} catch (ValueDoesNotMatch | InvalidData $exception) {
$type ??= $this->createType($args, $context);
$type->addInvalidValue($key, $exception);
}
}

$hasInvalidParameters = $type->hasInvalidParameters();
if ($hasInvalidParameters || $type->hasInvalidPairs()) {
if (
$type !== null
&& (
($hasInvalidParameters = $type->hasInvalidParameters())
|| $type->hasInvalidPairs()
)
) {
throw ValueDoesNotMatch::create(
$type,
$hasInvalidParameters ? Value::of($initValue) : Value::none(),
Expand Down
17 changes: 14 additions & 3 deletions src/Rules/ListOfRule.php
Original file line number Diff line number Diff line change
Expand Up @@ -76,19 +76,22 @@ public function getArgsType(): string
public function processValue($value, Args $args, FieldContext $context): array
{
$initValue = $value;
$type = $this->createType($args, $context);
$type = null;

if (!is_array($value)) {
$type = $this->createType($args, $context);
$type->markInvalid();

throw ValueDoesNotMatch::create($type, Value::of($initValue));
}

if ($args->minItems !== null && count($value) < $args->minItems) {
$type = $this->createType($args, $context);
$type->markParameterInvalid(self::MinItems);
}

if ($args->maxItems !== null && count($value) > $args->maxItems) {
$type ??= $this->createType($args, $context);
$type->markParameterInvalid(self::MaxItems);

throw ValueDoesNotMatch::create($type, Value::of($initValue));
Expand All @@ -107,6 +110,7 @@ public function processValue($value, Args $args, FieldContext $context): array
$keyType = $this->createKeyType();
$keyType->markParameterInvalid(self::Continuous);

$type ??= $this->createType($args, $context);
$type->addInvalidKey(
$key,
ValueDoesNotMatch::create($keyType, Value::of($key)),
Expand All @@ -124,6 +128,7 @@ public function processValue($value, Args $args, FieldContext $context): array
$context->createClone(),
);
} catch (ValueDoesNotMatch | InvalidData $exception) {
$type ??= $this->createType($args, $context);
$type->addInvalidValue($key, $exception);
// Remove invalid value because only valid values are expected beyond this point
// Invalid keys are fine because we don't work them beyond
Expand All @@ -141,12 +146,18 @@ public function processValue($value, Args $args, FieldContext $context): array
$context->createClone(),
);
} catch (ValueDoesNotMatch | InvalidData $exception) {
$type ??= $this->createType($args, $context);
$type->addInvalidValue($key, $exception);
}
}

$hasInvalidParameters = $type->hasInvalidParameters();
if ($hasInvalidParameters || $type->hasInvalidPairs()) {
if (
$type !== null
&& (
($hasInvalidParameters = $type->hasInvalidParameters())
|| $type->hasInvalidPairs()
)
) {
throw ValueDoesNotMatch::create(
$type,
$hasInvalidParameters ? Value::of($initValue) : Value::none(),
Expand Down
20 changes: 10 additions & 10 deletions src/Rules/ScalarRule.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,19 +29,19 @@ final class ScalarRule implements Rule
*/
public function processValue($value, Args $args, FieldContext $context)
{
if (is_scalar($value)) {
return $value;
}
if (!is_scalar($value)) {
$type = $this->createType($args, $context);
foreach ($this->getSubtypes() as $key => $subtype) {
$type->overwriteInvalidSubtype(
$key,
ValueDoesNotMatch::create($subtype, Value::none()),
);
}

$type = $this->createType($args, $context);
foreach ($this->getSubtypes() as $key => $subtype) {
$type->overwriteInvalidSubtype(
$key,
ValueDoesNotMatch::create($subtype, Value::none()),
);
throw ValueDoesNotMatch::create($type, Value::of($value));
}

throw ValueDoesNotMatch::create($type, Value::of($value));
return $value;
}

public function createType(Args $args, TypeContext $context): CompoundType
Expand Down

0 comments on commit 404ac47

Please sign in to comment.