Passed
Branch feature/first-release (5d23f8)
by Andrea Marco
10:49
created

JsonParser::lazyPointers()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 7
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 3

Importance

Changes 0
Metric Value
cc 3
eloc 3
c 0
b 0
f 0
nc 3
nop 1
dl 0
loc 7
ccs 4
cts 4
cp 1
crap 3
rs 10
1
<?php
2
3
namespace Cerbero\JsonParser;
4
5
use Cerbero\JsonParser\Decoders\DecodedValue;
6
use Cerbero\JsonParser\Decoders\Decoder;
7
use Cerbero\JsonParser\Exceptions\SyntaxException;
8
use Cerbero\JsonParser\Pointers\Pointer;
9
use Cerbero\JsonParser\Sources\AnySource;
10
use Closure;
11
use IteratorAggregate;
12
use Traversable;
13
14
/**
15
 * The JSON parser entry-point.
16
 *
17
 * @implements IteratorAggregate<string|int, mixed>
18
 */
19
final class JsonParser implements IteratorAggregate
20
{
21
    /**
22
     * The configuration.
23
     *
24
     * @var Config
25
     */
26
    private Config $config;
27
28
    /**
29
     * The parser.
30
     *
31
     * @var Parser
32
     */
33
    private Parser $parser;
34
35
    /**
36
     * Instantiate the class.
37
     *
38
     * @param mixed $source
39
     */
40 152
    public function __construct(mixed $source)
41
    {
42 152
        $this->config = new Config();
43 152
        $this->parser = Parser::for(new AnySource($source, $this->config));
44
    }
45
46
    /**
47
     * Statically instantiate the class
48
     *
49
     * @param mixed $source
50
     * @return self
51
     */
52 140
    public static function parse(mixed $source): self
53
    {
54 140
        return new self($source);
55
    }
56
57
    /**
58
     * Retrieve the lazily iterable JSON
59
     *
60
     * @return Traversable<string|int, mixed>
61
     */
62 140
    public function getIterator(): Traversable
63
    {
64
        try {
65 140
            yield from $this->parser;
66 15
        } catch (SyntaxException $e) {
0 ignored issues
show
Unused Code introduced by
catch (\Cerbero\JsonPars...ons\SyntaxException $e) is not reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
67 11
            $e->setPosition($this->parser->position());
68 11
            ($this->config->onSyntaxError)($e);
69
        }
70
    }
71
72
    /**
73
     * Set the JSON pointers
74
     *
75
     * @param string[]|array<string, Closure> $pointers
76
     * @return self
77
     */
78 39
    public function pointers(array $pointers): self
79
    {
80 39
        foreach ($pointers as $pointer => $callback) {
81 39
            $callback instanceof Closure ? $this->pointer($pointer, $callback) : $this->pointer($callback);
82
        }
83
84 31
        return $this;
85
    }
86
87
    /**
88
     * Set a JSON pointer
89
     *
90
     * @param string $pointer
91
     * @param Closure|null $callback
92
     * @return self
93
     */
94 107
    public function pointer(string $pointer, Closure $callback = null): self
95
    {
96 107
        $this->config->pointers->add(new Pointer($pointer, false, $callback));
97
98 103
        return $this;
99
    }
100
101
    /**
102
     * Set the lazy JSON pointers
103
     *
104
     * @param string[]|array<string, Closure> $pointers
105
     * @return self
106
     */
107 4
    public function lazyPointers(array $pointers): self
108
    {
109 4
        foreach ($pointers as $pointer => $callback) {
110 4
            $callback instanceof Closure ? $this->lazyPointer($pointer, $callback) : $this->lazyPointer($callback);
111
        }
112
113 4
        return $this;
114
    }
115
116
    /**
117
     * Set a lazy JSON pointer
118
     *
119
     * @param string $pointer
120
     * @param Closure|null $callback
121
     * @return self
122
     */
123 9
    public function lazyPointer(string $pointer, Closure $callback = null): self
124
    {
125 9
        $this->config->pointers->add(new Pointer($pointer, true, $callback));
126
127 9
        return $this;
128
    }
129
130
    /**
131
     * Traverse the lazily iterable JSON
132
     *
133
     * @param Closure|null $callback
134
     * @return void
135
     */
136 16
    public function traverse(Closure $callback = null): void
137
    {
138 16
        $callback ??= fn () => true;
139
140 16
        foreach ($this as $key => $value) {
141 9
            $callback($value, $key, $this);
142
        }
143
    }
144
145
    /**
146
     * Set the JSON decoder
147
     *
148
     * @param Decoder $decoder
149
     * @return self
150
     */
151
    public function decoder(Decoder $decoder): self
152
    {
153
        $this->config->decoder = $decoder;
154
155
        return $this;
156
    }
157
158
    /**
159
     * Retrieve the parsing progress
160
     *
161
     * @return Progress
162
     */
163
    public function progress(): Progress
164
    {
165
        return $this->parser->progress();
166
    }
167
168
    /**
169
     * The number of bytes to read in each chunk
170
     *
171
     * @param int<1, max> $bytes
172
     * @return self
173
     */
174
    public function bytes(int $bytes): self
175
    {
176
        $this->config->bytes = $bytes;
177
178
        return $this;
179
    }
180
181
    /**
182
     * Set the patch to apply during a decoding error
183
     *
184
     * @param mixed $patch
185
     * @return self
186
     */
187 4
    public function patchDecodingError(mixed $patch = null): self
188
    {
189 4
        return $this->onDecodingError(function (DecodedValue $decoded) use ($patch) {
190 4
            $decoded->value = is_callable($patch) ? $patch($decoded) : $patch;
191 4
        });
192
    }
193
194
    /**
195
     * Set the logic to run during a decoding error
196
     *
197
     * @param Closure $callback
198
     * @return self
199
     */
200 5
    public function onDecodingError(Closure $callback): self
201
    {
202 5
        $this->config->onDecodingError = $callback;
203
204 5
        return $this;
205
    }
206
207
    /**
208
     * Set the logic to run during a syntax error
209
     *
210
     * @param Closure $callback
211
     * @return self
212
     */
213 1
    public function onSyntaxError(Closure $callback): self
214
    {
215 1
        $this->config->onSyntaxError = $callback;
216
217 1
        return $this;
218
    }
219
}
220