Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
8.70% covered (danger)
8.70%
2 / 23
40.00% covered (danger)
40.00%
2 / 5
CRAP
0.00% covered (danger)
0.00%
0 / 1
FfiCdataNormalizer
8.70% covered (danger)
8.70%
2 / 23
40.00% covered (danger)
40.00%
2 / 5
141.64
0.00% covered (danger)
0.00%
0 / 1
 supportsNormalization
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 normalize
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
12
 supportsDenormalization
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 denormalize
0.00% covered (danger)
0.00%
0 / 10
0.00% covered (danger)
0.00%
0 / 1
12
 getType
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
30
1<?php
2namespace Apie\Serializer\Normalizers;
3
4use Apie\Core\Lists\ItemHashmap;
5use Apie\Core\Lists\ItemList;
6use Apie\Serializer\Context\ApieSerializerContext;
7use Apie\Serializer\Interfaces\DenormalizerInterface;
8use Apie\Serializer\Interfaces\NormalizerInterface;
9use FFI;
10use FFI\CData;
11use Psr\Http\Message\UploadedFileInterface;
12
13class FfiCdataNormalizer implements NormalizerInterface, DenormalizerInterface
14{
15    public function supportsNormalization(mixed $object, ApieSerializerContext $apieSerializerContext): bool
16    {
17        return $object instanceof CData;
18    }
19
20    public function normalize(mixed $object, ApieSerializerContext $apieSerializerContext): string|int|float|bool|null|ItemList|ItemHashmap
21    {
22        $typeName = FFI::typeof($object)->getName();
23        if (preg_match('/^(.+)\[(\d+)\]$/', $typeName, $matches)) {
24            $values = [];
25            for ($index = 0; $index < (int) $matches[2]; $index++) {
26                $values[] = $object[$index];
27            }
28            return new ItemList($values);
29        }
30
31        return $object->cdata;
32    }
33
34    public function supportsDenormalization(string|int|float|bool|null|ItemList|ItemHashmap|UploadedFileInterface $object, string $desiredType, ApieSerializerContext $apieSerializerContext): bool
35    {
36        return $desiredType === CData::class;
37    }
38
39    public function denormalize(string|int|float|bool|null|ItemList|ItemHashmap|UploadedFileInterface $object, string $desiredType, ApieSerializerContext $apieSerializerContext): CData
40    {
41        if ($object instanceof ItemList) {
42            $values = $object->toArray();
43            $type = self::getType($values[0] ?? null);
44            $result = FFI::cdef()->new($type . '[' . count($values) . ']');
45            foreach ($values as $index => $value) {
46                $result[$index] = $value;
47            }
48            return $result;
49        }
50
51        $result = FFI::cdef()->new(self::getType($object));
52        // @phpstan-ignore-next-line property.notFound
53        $result->cdata = $object;
54        return $result;
55    }
56
57    private static function getType(mixed $value): string
58    {
59        return match (true) {
60            is_bool($value) => 'bool',
61            is_int($value) => 'int',
62            is_float($value) => 'double',
63            default => 'char',
64        };
65    }
66}