Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
9 / 9
100.00% covered (success)
100.00%
2 / 2
CRAP
100.00% covered (success)
100.00%
1 / 1
DelimitedMessage
100.00% covered (success)
100.00%
9 / 9
100.00% covered (success)
100.00%
2 / 2
6
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 from
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
100.00%
1 / 1
5
1<?php
2
3declare(strict_types=1);
4
5namespace AqwSocketClient\Messages;
6
7use AqwSocketClient\Enums\DelimitedMessageType;
8use AqwSocketClient\Interfaces\MessageInterface;
9use Override;
10use Psl\Str;
11use Psl\Vec;
12
13/**
14 * Represents a server message that is formatted using a **delimiter**
15 * (e.g., the '%' character).
16 *
17 * This class handles the parsing of the delimited string, extracting the
18 * message type and the subsequent data payload.
19 */
20final class DelimitedMessage implements MessageInterface
21{
22    /**
23     * @param DelimitedMessageType $type The enumerated type of the delimited message.
24     * @param array<int, string> $data An array containing the payload data of the message,
25     * following the message type.
26     */
27    private function __construct(
28        public readonly DelimitedMessageType $type,
29        public readonly array $data,
30        public readonly string $raw,
31    ) {}
32
33    /**
34     * Attempts to create a DelimitedMessage object by parsing the raw string.
35     *
36     * The method validates the message format (starts and ends with '%'),
37     * extracts the parts, identifies the message type, and separates the data payload.
38     *
39     * @param string $message The raw string data received from the socket.
40     * @return DelimitedMessage|false The newly created message object, or **false**
41     * if the message format is invalid or the message type cannot be determined.
42     */
43    #[Override]
44    public static function from(string $message): DelimitedMessage|false
45    {
46        if (!Str\starts_with($message, '%') && !Str\ends_with($message, '%')) {
47            return false;
48        }
49
50        $parts = Vec\filter(Str\split($message, '%'), static fn(string $part): bool => $part !== '');
51        $parts = Vec\filter_with_key($parts, static fn(int $k, string $_): bool => $k !== 0 && $k !== 2);
52
53        $type = DelimitedMessageType::tryFrom($parts[0]);
54        if ($type === null) {
55            return false;
56        }
57
58        return new self($type, Vec\slice($parts, 1), $message);
59    }
60}