• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

nette / neon / 22293166616

23 Feb 2026 04:40AM UTC coverage: 98.488%. Remained the same
22293166616

push

github

dg
added CLAUDE.md

456 of 463 relevant lines covered (98.49%)

0.98 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

95.45
/src/Neon/Node/LiteralNode.php
1
<?php declare(strict_types=1);
2

3
/**
4
 * This file is part of the Nette Framework (https://nette.org)
5
 * Copyright (c) 2004 David Grudl (https://davidgrudl.com)
6
 */
7

8
namespace Nette\Neon\Node;
9

10
use Nette\Neon\Exception;
11
use Nette\Neon\Node;
12
use function array_key_exists, base_convert, bcadd, bcmul, extension_loaded, is_bool, is_finite, is_float, is_int, is_numeric, is_string, json_encode, ord, preg_match, str_contains, strlen, substr;
13

14

15
/** @internal */
16
final class LiteralNode extends Node
17
{
18
        private const SimpleTypes = [
19
                'true' => true, 'True' => true, 'TRUE' => true, 'yes' => true, 'Yes' => true, 'YES' => true,
20
                'false' => false, 'False' => false, 'FALSE' => false, 'no' => false, 'No' => false, 'NO' => false,
21
                'null' => null, 'Null' => null, 'NULL' => null,
22
        ];
23

24
        private const PatternDatetime = '#\d\d\d\d-\d\d?-\d\d?(?:(?:[Tt]| ++)\d\d?:\d\d:\d\d(?:\.\d*+)? *+(?:Z|[-+]\d\d?(?::?\d\d)?)?)?$#DA';
25
        private const PatternHex = '#0x[0-9a-fA-F]++$#DA';
26
        private const PatternOctal = '#0o[0-7]++$#DA';
27
        private const PatternBinary = '#0b[0-1]++$#DA';
28

29

30
        public function __construct(
1✔
31
                /** @var  bool|int|float|string|\DateTimeInterface|null */
32
                public mixed $value,
33
        ) {
34
        }
1✔
35

36

37
        /** @return bool|int|float|string|\DateTimeInterface|null */
38
        public function toValue(): mixed
39
        {
40
                return $this->value;
1✔
41
        }
42

43

44
        /** @return ($isKey is true ? int|float|string : bool|int|float|string|\DateTimeImmutable|null) */
45
        public static function parse(string $value, bool $isKey = false): mixed
1✔
46
        {
47
                if (!$isKey && array_key_exists($value, self::SimpleTypes)) {
1✔
48
                        return self::SimpleTypes[$value];
1✔
49

50
                } elseif (is_numeric($value)) {
1✔
51
                        return is_int($num = $value * 1) || preg_match('#[.eE]#', $value) ? $num : $value;
1✔
52

53
                } elseif (preg_match(self::PatternHex, $value)) {
1✔
54
                        return self::baseConvert(substr($value, 2), 16);
1✔
55

56
                } elseif (preg_match(self::PatternOctal, $value)) {
1✔
57
                        return self::baseConvert(substr($value, 2), 8);
1✔
58

59
                } elseif (preg_match(self::PatternBinary, $value)) {
1✔
60
                        return self::baseConvert(substr($value, 2), 2);
1✔
61

62
                } elseif (!$isKey && preg_match(self::PatternDatetime, $value)) {
1✔
63
                        return new \DateTimeImmutable($value);
1✔
64

65
                } else {
66
                        return $value;
1✔
67
                }
68
        }
69

70

71
        public static function baseConvert(string $number, int $base): string|int
1✔
72
        {
73
                if (strlen($number) < 16) {
1✔
74
                        $res = base_convert($number, $base, 10);
1✔
75
                } elseif (!extension_loaded('bcmath')) {
1✔
76
                        throw new Exception("The number '$number' is too large, enable 'bcmath' extension to handle it.");
×
77
                } else {
78
                        $res = '0';
1✔
79
                        for ($i = 0; $i < strlen($number); $i++) {
1✔
80
                                $char = $number[$i];
1✔
81
                                $char = match (true) {
1✔
82
                                        $char >= 'a' => ord($char) - 87,
1✔
83
                                        $char >= 'A' => ord($char) - 55,
1✔
84
                                        default => $char,
1✔
85
                                };
86
                                $res = bcmul($res, (string) $base, 0);
1✔
87
                                $res = bcadd($res, (string) $char, 0);
1✔
88
                        }
89
                }
90

91
                return is_int($num = $res * 1) ? $num : $res;
1✔
92
        }
93

94

95
        public function toString(): string
96
        {
97
                if ($this->value instanceof \DateTimeInterface) {
1✔
98
                        return $this->value->format('Y-m-d H:i:s O');
1✔
99

100
                } elseif (is_string($this->value)) {
1✔
101
                        return $this->value;
1✔
102

103
                } elseif (is_float($this->value)) {
1✔
104
                        if (!is_finite($this->value)) {
1✔
105
                                throw new Exception('INF and NAN cannot be encoded to NEON');
1✔
106
                        }
107
                        $res = json_encode($this->value);
1✔
108
                        return str_contains($res, '.') ? $res : $res . '.0';
1✔
109

110
                } elseif (is_int($this->value) || is_bool($this->value) || $this->value === null) {
1✔
111

112
                        return json_encode($this->value);
1✔
113

114
                } else {
115
                        throw new \LogicException;
×
116
                }
117
        }
118
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc