Lines 100.00% 13 / 13
Methods 100.00% 2 / 2
Classes 100.00% 1 / 1
Name Lines Methods CRAP
 parse 100.00% 4 / 4 100.00% 1 / 1 1
 decompress 100.00% 9 / 9 100.00% 1 / 1 4
13final readonly class MessageParser
14{
15    private const string COMPRESSED_PREFIX = 'Z';
16
17    /** @return Option\Option<Message> */
18    public static function parse(string $raw): Option\Option
19    {
20        return self::decompress($raw)
21            ->andThen(static fn(string $message): Option\Option => XmlMessage::from($message)->or(JsonMessage::from(
22                $message,
23            ))->or(DelimitedMessage::from($message)));
24    }
25
26    /** @return Option\Option<string> */
27    private static function decompress(string $raw): Option\Option
28    {
29        if (!str_starts_with($raw, self::COMPRESSED_PREFIX)) {
30            return Option\some($raw);
31        }
32
33        $compressed = base64_decode(substr($raw, offset: 1), strict: true);
34        if ($compressed === false) {
35            return Option\none();
36        }
37
38        set_error_handler(static fn(): bool => true);
39        try {
40            $message = gzuncompress($compressed);
41        } finally {
42            restore_error_handler();
43        }
44
45        return $message === false ? Option\none() : Option\some($message);
46    }
47}