Leverage PHP 8.1 features

This commit is contained in:
Andrea Marco Sartori 2023-06-14 23:59:46 +02:00
parent 7cb1d906e0
commit 3a0d6fe660
23 changed files with 72 additions and 125 deletions

View File

@ -16,7 +16,7 @@ final class ConfigurableDecoder
*
* @param Config $config
*/
public function __construct(private Config $config)
public function __construct(private readonly Config $config)
{
}

View File

@ -10,21 +10,6 @@ use Throwable;
*/
final class DecodedValue
{
/**
* Instantiate the class.
*
* @param mixed $value
*/
private function __construct(
public bool $succeeded,
public mixed $value = null,
public ?string $error = null,
public ?int $code = null,
public ?Throwable $exception = null,
public ?string $json = null,
) {
}
/**
* Retrieve a successfully decoded value
*
@ -47,4 +32,19 @@ final class DecodedValue
{
return new self(false, null, $e->getMessage(), $e->getCode(), $e, $json);
}
/**
* Instantiate the class.
*
* @param mixed $value
*/
private function __construct(
public readonly bool $succeeded,
public mixed $value = null,
public readonly ?string $error = null,
public readonly ?int $code = null,
public readonly ?Throwable $exception = null,
public readonly ?string $json = null,
) {
}
}

View File

@ -14,7 +14,7 @@ final class JsonDecoder extends AbstractDecoder
* @param bool $decodesToArray
* @param int<1, max> $depth
*/
public function __construct(private bool $decodesToArray = true, private int $depth = 512)
public function __construct(private readonly bool $decodesToArray = true, private readonly int $depth = 512)
{
}

View File

@ -14,7 +14,7 @@ final class SimdjsonDecoder extends AbstractDecoder
* @param bool $decodesToArray
* @param int $depth
*/
public function __construct(private bool $decodesToArray = true, private int $depth = 512)
public function __construct(private readonly bool $decodesToArray = true, private readonly int $depth = 512)
{
}

View File

@ -16,7 +16,7 @@ final class DecodingException extends Exception implements JsonParserException
*
* @param DecodedValue $decoded
*/
public function __construct(public DecodedValue $decoded)
public function __construct(public readonly DecodedValue $decoded)
{
parent::__construct('Decoding error: ' . $decoded->error, (int) $decoded->code);
}

View File

@ -17,7 +17,7 @@ class IntersectingPointersException extends Exception implements JsonParserExcep
* @param Pointer $pointer1
* @param Pointer $pointer2
*/
public function __construct(public Pointer $pointer1, public Pointer $pointer2)
public function __construct(public readonly Pointer $pointer1, public readonly Pointer $pointer2)
{
parent::__construct("The pointers [$pointer1] and [$pointer2] are intersecting");
}

View File

@ -15,7 +15,7 @@ final class InvalidPointerException extends Exception implements JsonParserExcep
*
* @param string $pointer
*/
public function __construct(public string $pointer)
public function __construct(public readonly string $pointer)
{
parent::__construct("The string [$pointer] is not a valid JSON pointer");
}

View File

@ -22,7 +22,7 @@ final class SyntaxException extends Exception implements JsonParserException
*
* @param string $value
*/
public function __construct(public string $value)
public function __construct(public readonly string $value)
{
parent::__construct("Syntax error: unexpected '$value'");
}

View File

@ -15,7 +15,7 @@ final class UnsupportedSourceException extends Exception implements JsonParserEx
*
* @param mixed $source
*/
public function __construct(public mixed $source)
public function __construct(public readonly mixed $source)
{
parent::__construct('Unable to load JSON from the provided source');
}

View File

@ -27,21 +27,32 @@ final class JsonParser implements IteratorAggregate
*
* @var Config
*/
private Config $config;
private readonly Config $config;
/**
* The lexer.
*
* @var Lexer
*/
private Lexer $lexer;
private readonly Lexer $lexer;
/**
* The parser.
*
* @var Parser
*/
private Parser $parser;
private readonly Parser $parser;
/**
* Instantiate the class statically
*
* @param mixed $source
* @return self
*/
public static function parse(mixed $source): self
{
return new self($source);
}
/**
* Instantiate the class.
@ -55,17 +66,6 @@ final class JsonParser implements IteratorAggregate
$this->parser = new Parser($this->lexer->getIterator(), $this->config);
}
/**
* Instantiate the class statically
*
* @param mixed $source
* @return self
*/
public static function parse(mixed $source): self
{
return new self($source);
}
/**
* Retrieve the lazily iterable JSON
*

View File

@ -22,21 +22,14 @@ final class Pointer implements Stringable
*
* @var string[]
*/
private array $referenceTokens;
public readonly array $referenceTokens;
/**
* The pointer depth.
*
* @var int
*/
private int $depth;
/**
* The pointer callback.
*
* @var Closure
*/
private ?Closure $callback;
public readonly int $depth;
/**
* Whether the pointer was found.
@ -52,11 +45,13 @@ final class Pointer implements Stringable
* @param bool $isLazy
* @param Closure|null $callback
*/
public function __construct(private string $pointer, private bool $isLazy = false, Closure $callback = null)
{
public function __construct(
private readonly string $pointer,
public readonly bool $isLazy = false,
private readonly ?Closure $callback = null,
) {
$this->referenceTokens = $this->toReferenceTokens();
$this->depth = count($this->referenceTokens);
$this->callback = $callback;
}
/**
@ -76,36 +71,6 @@ final class Pointer implements Stringable
return array_slice($referenceTokens, 1);
}
/**
* Determine whether the pointer is lazy
*
* @return bool
*/
public function isLazy(): bool
{
return $this->isLazy;
}
/**
* Retrieve the reference tokens
*
* @return string[]
*/
public function referenceTokens(): array
{
return $this->referenceTokens;
}
/**
* Retrieve the JSON pointer depth
*
* @return int
*/
public function depth(): int
{
return $this->depth;
}
/**
* Call the pointer callback
*

View File

@ -76,7 +76,7 @@ final class Pointers
$originalTree = $tree->original();
foreach ($this->pointers as $pointer) {
if ($pointer->referenceTokens() == $originalTree) {
if ($pointer->referenceTokens == $originalTree) {
return $this->matching = $pointer;
}

View File

@ -13,13 +13,6 @@ use Traversable;
*/
abstract class Source implements IteratorAggregate
{
/**
* The configuration.
*
* @var Config
*/
protected Config $config;
/**
* The cached size of the JSON source.
*
@ -57,14 +50,15 @@ abstract class Source implements IteratorAggregate
abstract protected function calculateSize(): ?int;
/**
* Enforce the factory method to instantiate the class.
* Instantiate the class.
*
* @param mixed $source
* @param Config|null $config
*/
final public function __construct(protected mixed $source, Config $config = null)
{
$this->config = $config ?: new Config();
final public function __construct(
protected readonly mixed $source,
protected readonly Config $config = new Config(),
) {
}
/**

View File

@ -18,7 +18,7 @@ final class Comma extends Token
*/
public function mutateState(State $state): void
{
$state->expectsKey = $state->tree()->inObject();
$state->expectsKey = $state->tree->inObject();
$state->expectedToken = $state->expectsKey ? Tokens::SCALAR_STRING : Tokens::VALUE_ANY;
}
}

View File

@ -25,16 +25,14 @@ final class CompoundBegin extends Token
*/
public function mutateState(State $state): void
{
$tree = $state->tree();
if ($this->shouldLazyLoad = $this->shouldLazyLoad && $tree->depth() >= 0) {
$state->expectedToken = $tree->inObject() ? Tokens::AFTER_OBJECT_VALUE : Tokens::AFTER_ARRAY_VALUE;
if ($this->shouldLazyLoad = $this->shouldLazyLoad && $state->tree->depth() >= 0) {
$state->expectedToken = $state->tree->inObject() ? Tokens::AFTER_OBJECT_VALUE : Tokens::AFTER_ARRAY_VALUE;
return;
}
$state->expectsKey = $beginsObject = $this->value == '{';
$state->expectedToken = $beginsObject ? Tokens::AFTER_OBJECT_BEGIN : Tokens::AFTER_ARRAY_BEGIN;
$tree->deepen($beginsObject);
$state->tree->deepen($beginsObject);
}
/**

View File

@ -18,9 +18,9 @@ final class CompoundEnd extends Token
*/
public function mutateState(State $state): void
{
$state->tree()->emerge();
$state->tree->emerge();
$state->expectedToken = $state->tree()->inObject() ? Tokens::AFTER_OBJECT_VALUE : Tokens::AFTER_ARRAY_VALUE;
$state->expectedToken = $state->tree->inObject() ? Tokens::AFTER_OBJECT_VALUE : Tokens::AFTER_ARRAY_VALUE;
}
/**

View File

@ -18,7 +18,7 @@ final class Constant extends Token
*/
public function mutateState(State $state): void
{
$state->expectedToken = $state->tree()->inObject() ? Tokens::AFTER_OBJECT_VALUE : Tokens::AFTER_ARRAY_VALUE;
$state->expectedToken = $state->tree->inObject() ? Tokens::AFTER_OBJECT_VALUE : Tokens::AFTER_ARRAY_VALUE;
}
/**

View File

@ -25,7 +25,7 @@ final class Lexer implements IteratorAggregate
*
* @var Progress
*/
private Progress $progress;
private readonly Progress $progress;
/**
* The current position.
@ -39,7 +39,7 @@ final class Lexer implements IteratorAggregate
*
* @param Source $source
*/
public function __construct(private Source $source)
public function __construct(private readonly Source $source)
{
$this->progress = new Progress();
}

View File

@ -25,7 +25,7 @@ final class Parser implements IteratorAggregate
*
* @var ConfigurableDecoder
*/
private ConfigurableDecoder $decoder;
private readonly ConfigurableDecoder $decoder;
/**
* Whether the parser is fast-forwarding.
@ -40,7 +40,7 @@ final class Parser implements IteratorAggregate
* @param Generator<int, Token> $tokens
* @param Config $config
*/
public function __construct(private Generator $tokens, private Config $config)
public function __construct(private readonly Generator $tokens, private readonly Config $config)
{
$this->decoder = new ConfigurableDecoder($config);
}
@ -63,13 +63,13 @@ final class Parser implements IteratorAggregate
$state->mutateByToken($token);
if (!$token->endsChunk() || $state->tree()->isDeep()) {
if (!$token->endsChunk() || $state->tree->isDeep()) {
continue;
}
if ($state->hasBuffer()) {
/** @var string|int $key */
$key = $this->decoder->decode($state->key());
$key = $this->decoder->decode($state->tree->currentKey());
$value = $this->decoder->decode($state->value());
yield $key => $state->callPointer($value, $key);

View File

@ -31,7 +31,7 @@ final class ScalarString extends Token
return;
}
$state->expectedToken = $state->tree()->inObject() ? Tokens::AFTER_OBJECT_VALUE : Tokens::AFTER_ARRAY_VALUE;
$state->expectedToken = $state->tree->inObject() ? Tokens::AFTER_OBJECT_VALUE : Tokens::AFTER_ARRAY_VALUE;
}
/**

View File

@ -20,7 +20,7 @@ final class Tokenizer
*
* @var array<int, Token>
*/
private array $tokensMap;
private array $tokensMap = [];
/**
* Retrieve the singleton instance

View File

@ -20,7 +20,7 @@ final class State
*
* @var Tree
*/
private Tree $tree;
public readonly Tree $tree;
/**
* The JSON buffer.
@ -49,7 +49,7 @@ final class State
* @param Pointers $pointers
* @param Closure $lazyLoad
*/
public function __construct(private Pointers $pointers, private Closure $lazyLoad)
public function __construct(private readonly Pointers $pointers, private readonly Closure $lazyLoad)
{
$this->tree = new Tree($pointers);
}
@ -64,16 +64,6 @@ final class State
return $this->tree;
}
/**
* Retrieve the current key of the JSON tree
*
* @return string|int
*/
public function key(): string|int
{
return $this->tree->currentKey();
}
/**
* Determine whether the parser can stop parsing
*
@ -109,7 +99,7 @@ final class State
if ($this->tree->isMatched() && ((!$this->expectsKey && $token->isValue()) || $this->tree->isDeep())) {
$pointer = $this->pointers->markAsFound();
if ($token instanceof CompoundBegin && $pointer->isLazy()) {
if ($token instanceof CompoundBegin && $pointer->isLazy) {
$this->buffer = ($this->lazyLoad)();
$token->shouldLazyLoad = true;
} else {

View File

@ -46,7 +46,7 @@ final class Tree
*
* @param Pointers $pointers
*/
public function __construct(private Pointers $pointers)
public function __construct(private readonly Pointers $pointers)
{
}
@ -121,7 +121,7 @@ final class Tree
{
$pointer = $this->pointers->matching();
return $pointer == '' ? $this->depth > 0 : $this->depth >= $pointer->depth();
return $pointer == '' ? $this->depth > 0 : $this->depth >= $pointer->depth;
}
/**
@ -135,7 +135,7 @@ final class Tree
{
$pointer = $this->pointers->matching();
if ($pointer != '' && $this->depth >= $pointer->depth()) {
if ($pointer != '' && $this->depth >= $pointer->depth) {
return;
} elseif ($expectsKey) {
$this->traverseKey($token);
@ -191,7 +191,7 @@ final class Tree
array_splice($this->inObjectByDepth, $offset);
}
$referenceTokens = $this->pointers->matchTree($this)->referenceTokens();
$referenceTokens = $this->pointers->matchTree($this)->referenceTokens;
$this->wildcarded[$this->depth] = ($referenceTokens[$this->depth] ?? null) == '-' ? '-' : $index;
if (count($this->wildcarded) > $offset) {