Lines 57.14% 12 / 21
Functions and Methods 50.00% 2 / 4
Classes and Traits 0.00% 0 / 1
Name Lines Functions and Methods CRAP Classes and Traits
ChannelTransport 57.14% 12 / 21 50.00% 2 / 4 20.52 0.00% 0 / 1
 __construct 100.00% 1 / 1 100.00% 1 / 1 1
 send 66.66% 4 / 6 0.00% 0 / 1 3.33
 receive 41.66% 5 / 12 0.00% 0 / 1 13.15
 close 100.00% 2 / 2 100.00% 1 / 1 1
1<?php
2
3declare(strict_types=1);
4
5namespace Stewart\Runtime\Ipc;
6
7use Amp\Sync\Channel;
8use Amp\Sync\ChannelException;
9use Stewart\Runtime\Exception\TransportError;
10use Stewart\Runtime\Exception\TransportException;
11use Stewart\Runtime\Ipc\Wire\IpcCodec;
12use Throwable;
13
14final class ChannelTransport implements Transport
15{
16    private bool $closed = false;
17
18    /** @param Channel<string, string> $channel */
19    public function __construct(
20        private readonly Channel $channel,
21        private readonly IpcCodec $codecs,
22    ) {}
23
24    public function send(object $message): void
25    {
26        if ($this->closed) {
27            throw TransportException::createForReason(TransportError::Closed);
28        }
29
30        $frame = $this->codecs->encodeMessage($message);
31
32        try {
33            $this->channel->send($frame);
34        } catch (ChannelException $e) {
35            throw TransportException::createForReason(TransportError::SendFailed, $e);
36        }
37    }
38
39    public function receive(): ?object
40    {
41        if ($this->closed) {
42            return null;
43        }
44
45        try {
46            $frame = $this->channel->receive();
47        } catch (ChannelException $e) {
48            throw TransportException::createForReason(TransportError::PeerDisconnected, $e);
49        } catch (Throwable $e) {
50            throw TransportException::createForReason(TransportError::ReceiveFailed, $e);
51        }
52
53        if ($frame === null) {
54            return null;
55        }
56
57        if (!\is_string($frame)) {
58            throw TransportException::createForReason(TransportError::UnexpectedMessage, actualType: get_debug_type($frame));
59        }
60
61        return $this->codecs->decodeMessage($frame);
62    }
63
64    public function close(): void
65    {
66        $this->closed = true;
67        $this->channel->close();
68    }
69}