Lines
95.23%
20 / 21
Functions and Methods
75.00%
3 / 4
Classes and Traits
0.00%
0 / 1
| Name | Lines | Functions and Methods | CRAP | Classes and Traits | ||||||
|---|---|---|---|---|---|---|---|---|---|---|
| MqttMessageConverter | 95.23% | 20 / 21 | 75.00% | 3 / 4 | 9 | 0.00% | 0 / 1 | |||
| handledClass | 100.00% | 1 / 1 | 100.00% | 1 / 1 | 1 | |||||
| keySuffix | 100.00% | 1 / 1 | 100.00% | 1 / 1 | 1 | |||||
| encodeValue | 100.00% | 7 / 7 | 100.00% | 1 / 1 | 1 | |||||
| decodeValue | 91.66% | 11 / 12 | 0.00% | 0 / 1 | 6.02 | |||||
| 1 | <?php | |
| 2 | ||
| 3 | declare(strict_types=1); | |
| 4 | ||
| 5 | namespace Stewart\Runtime\Ipc\Wire; | |
| 6 | ||
| 7 | use Stewart\Contracts\Mqtt\MqttMessage; | |
| 8 | use Stewart\Contracts\Mqtt\MqttQos; | |
| 9 | use Stewart\Runtime\Json\ValueConverter; | |
| 10 | use Stewart\Support\Exception\JsonShapeException; | |
| 11 | use Stewart\Support\Json\JsonShape; | |
| 12 | ||
| 13 | // Payloads are bytes and IPC frames are JSON, so the payload travels base64-encoded. | |
| 14 | final readonly class MqttMessageConverter implements ValueConverter | |
| 15 | { | |
| 16 | public function handledClass(): string | |
| 17 | { | |
| 18 | return MqttMessage::class; | |
| 19 | } | |
| 20 | ||
| 21 | public function keySuffix(): string | |
| 22 | { | |
| 23 | return ''; | |
| 24 | } | |
| 25 | ||
| 26 | /** @return array{topic: string, payload_base64: string, qos: int, retain: bool} */ | |
| 27 | public function encodeValue(object $value): array | |
| 28 | { | |
| 29 | \assert($value instanceof MqttMessage); | |
| 30 | ||
| 31 | return [ | |
| 32 | 'topic' => $value->topic, | |
| 33 | 'payload_base64' => base64_encode($value->payload), | |
| 34 | 'qos' => $value->qos->value, | |
| 35 | 'retain' => $value->retain, | |
| 36 | ]; | |
| 37 | } | |
| 38 | ||
| 39 | /** @throws JsonShapeException */ | |
| 40 | public function decodeValue(mixed $value, string $path): MqttMessage | |
| 41 | { | |
| 42 | if (!\is_array($value)) { | |
| 43 | throw JsonShapeException::wrongType($path, 'an object', get_debug_type($value)); | |
| 44 | } | |
| 45 | ||
| 46 | $payload = base64_decode(JsonShape::requireString($value, 'payload_base64'), true); | |
| 47 | $qos = \is_int($value['qos'] ?? null) ? MqttQos::tryFrom($value['qos']) : null; | |
| 48 | $retain = $value['retain'] ?? null; | |
| 49 | ||
| 50 | if ($payload === false) { | |
| 51 | throw JsonShapeException::unexpectedValue($path . '.payload_base64', 'base64 text', $value['payload_base64']); | |
| 52 | } | |
| 53 | ||
| 54 | if ($qos === null) { | |
| 55 | throw JsonShapeException::unexpectedValue($path . '.qos', '0 or 1', $value['qos'] ?? null); | |
| 56 | } | |
| 57 | ||
| 58 | if (!\is_bool($retain)) { | |
| 59 | throw JsonShapeException::wrongType($path . '.retain', 'a boolean', get_debug_type($retain)); | |
| 60 | } | |
| 61 | ||
| 62 | return new MqttMessage(JsonShape::requireString($value, 'topic'), $payload, $qos, $retain); | |
| 63 | } | |
| 64 | } |