public function cast(mixed $value, TypeCastContext $context): Result
{
$type = $context->getReflectionType();
if ($type === null) {
return Result::success($value);
}
if (!$type instanceof ReflectionNamedType && !$type instanceof ReflectionUnionType) {
return Result::fail();
}
$types = $type instanceof ReflectionNamedType
? [$type]
: array_filter(
$type->getTypes(),
static fn(mixed $type) => $type instanceof ReflectionNamedType,
);
foreach ($types as $t) {
if ($value === null && $t->allowsNull()) {
return Result::success(null);
}
if (!$t->isBuiltin()) {
continue;
}
switch ($t->getName()) {
case 'string':
if (is_string($value)) {
return Result::success($value);
}
break;
case 'int':
if (is_int($value)) {
return Result::success($value);
}
break;
case 'float':
if (is_float($value)) {
return Result::success($value);
}
break;
case 'bool':
if (is_bool($value)) {
return Result::success($value);
}
break;
case 'array':
if (is_array($value)) {
return Result::success($value);
}
break;
}
}
foreach ($types as $t) {
if (!$t->isBuiltin()) {
$class = $t->getName();
if ($value instanceof $class) {
return Result::success($value);
}
continue;
}
switch ($t->getName()) {
case 'string':
if (is_scalar($value) || $value === null || $value instanceof Stringable) {
return Result::success((string) $value);
}
break;
case 'int':
if (is_bool($value) || is_float($value) || $value === null) {
return Result::success((int) $value);
}
if ($value instanceof Stringable || is_string($value)) {
return Result::success((int) NumericHelper::normalize($value));
}
break;
case 'float':
if (is_int($value) || is_bool($value) || $value === null) {
return Result::success((float) $value);
}
if ($value instanceof Stringable || is_string($value)) {
return Result::success((float) NumericHelper::normalize($value));
}
break;
case 'bool':
if (is_scalar($value) || $value === null || is_array($value) || is_object($value)) {
return Result::success((bool) $value);
}
break;
}
}
return Result::fail();
}
Signup or Login in order to comment.