Lines 0.00% 0 / 14
Functions and Methods 0.00% 0 / 11
Classes and Traits 0.00% 0 / 1
Name Lines Functions and Methods CRAP Classes and Traits
StringIdentifierConverter 0.00% 0 / 14 0.00% 0 / 11 156 0.00% 0 / 1
 __construct 0.00% 0 / 1 0.00% 0 / 1 2
 createForAppIds 0.00% 0 / 1 0.00% 0 / 1 2
 createForEntityIds 0.00% 0 / 1 0.00% 0 / 1 2
 createForAreaIds 0.00% 0 / 1 0.00% 0 / 1 2
 createForFloorIds 0.00% 0 / 1 0.00% 0 / 1 2
 createForLabelIds 0.00% 0 / 1 0.00% 0 / 1 2
 createForDeviceIds 0.00% 0 / 1 0.00% 0 / 1 2
 handledClass 0.00% 0 / 1 0.00% 0 / 1 2
 keySuffix 0.00% 0 / 1 0.00% 0 / 1 2
 encodeValue 0.00% 0 / 2 0.00% 0 / 1 2
 decodeValue 0.00% 0 / 3 0.00% 0 / 1 6
1<?php
2
3declare(strict_types=1);
4
5namespace Stewart\Runtime\Json;
6
7use Closure;
8use Stewart\Contracts\App\AppId;
9use Stewart\Contracts\Entity\EntityId;
10use Stewart\Contracts\Registry\AreaId;
11use Stewart\Contracts\Registry\DeviceId;
12use Stewart\Contracts\Registry\FloorId;
13use Stewart\Contracts\Registry\LabelId;
14use Stewart\Support\Exception\JsonShapeException;
15use Stringable;
16
17/** @template T of Stringable */
18final readonly class StringIdentifierConverter implements ValueConverter
19{
20    /**
21     * @param class-string<T> $identifierClass
22     * @param Closure(string): ?T $parse
23     */
24    public function __construct(
25        private string $identifierClass,
26        private string $expected,
27        private Closure $parse,
28    ) {}
29
30    /** @return self<AppId> */
31    public static function createForAppIds(): self
32    {
33        return new self(AppId::class, 'an app id', AppId::tryFromString(...));
34    }
35
36    /** @return self<EntityId> */
37    public static function createForEntityIds(): self
38    {
39        return new self(EntityId::class, 'an entity id', EntityId::tryFromString(...));
40    }
41
42    /** @return self<AreaId> */
43    public static function createForAreaIds(): self
44    {
45        return new self(AreaId::class, 'an area id', AreaId::tryFromString(...));
46    }
47
48    /** @return self<FloorId> */
49    public static function createForFloorIds(): self
50    {
51        return new self(FloorId::class, 'a floor id', FloorId::tryFromString(...));
52    }
53
54    /** @return self<LabelId> */
55    public static function createForLabelIds(): self
56    {
57        return new self(LabelId::class, 'a label id', LabelId::tryFromString(...));
58    }
59
60    /** @return self<DeviceId> */
61    public static function createForDeviceIds(): self
62    {
63        return new self(DeviceId::class, 'a device id', DeviceId::tryFromString(...));
64    }
65
66    public function handledClass(): string
67    {
68        return $this->identifierClass;
69    }
70
71    public function keySuffix(): string
72    {
73        return '';
74    }
75
76    public function encodeValue(object $value): string
77    {
78        \assert($value instanceof $this->identifierClass);
79
80        return (string) $value;
81    }
82
83    /** @return T */
84    public function decodeValue(mixed $value, string $path): object
85    {
86        if (!\is_string($value)) {
87            throw JsonShapeException::wrongType($path, $this->expected, get_debug_type($value));
88        }
89
90        return ($this->parse)($value) ?? throw JsonShapeException::unexpectedValue($path, $this->expected, $value);
91    }
92}