Implement the simdjson decoder

This commit is contained in:
Andrea Marco Sartori 2023-01-19 00:01:20 +10:00
parent 340768e247
commit 47b2e4cfaf
7 changed files with 80 additions and 35 deletions

View File

@ -2,7 +2,7 @@
namespace Cerbero\JsonParser;
use Cerbero\JsonParser\Decoders\ArrayDecoder;
use Cerbero\JsonParser\Decoders\JsonDecoder;
use Cerbero\JsonParser\Decoders\DecodedValue;
use Cerbero\JsonParser\Decoders\Decoder;
use Cerbero\JsonParser\Pointers\Pointer;
@ -48,7 +48,7 @@ final class Config
*/
public function __construct()
{
$this->decoder = new ArrayDecoder();
$this->decoder = new JsonDecoder();
$this->onError = fn (DecodedValue $decoded) => throw $decoded->exception;
}
}

View File

@ -2,20 +2,21 @@
namespace Cerbero\JsonParser\Decoders;
use JsonException;
use Throwable;
/**
* The decoder to turn a JSON into an associative array.
* The abstract implementation of a JSON decoder.
*
*/
class ArrayDecoder implements Decoder
abstract class AbstractDecoder implements Decoder
{
/**
* Whether to decode the JSON into an associative array.
* Retrieve the decoded value of the given JSON
*
* @var bool
* @param string $json
* @return mixed
*/
protected bool $decodesToArray = true;
abstract protected function decodeJson(string $json): mixed;
/**
* Decode the given JSON.
@ -26,8 +27,8 @@ class ArrayDecoder implements Decoder
public function decode(string $json): DecodedValue
{
try {
$value = json_decode($json, $this->decodesToArray, flags: JSON_THROW_ON_ERROR);
} catch (JsonException $e) {
$value = $this->decodeJson($json);
} catch (Throwable $e) {
return DecodedValue::failed($e, $json);
}

View File

@ -2,7 +2,7 @@
namespace Cerbero\JsonParser\Decoders;
use JsonException;
use Throwable;
/**
* The decoded value.
@ -20,7 +20,7 @@ final class DecodedValue
public mixed $value = null,
public ?string $error = null,
public ?int $code = null,
public ?JsonException $exception = null,
public ?Throwable $exception = null,
public ?string $json = null,
) {
}
@ -39,11 +39,11 @@ final class DecodedValue
/**
* Retrieve a value failed to be decoded
*
* @param JsonException $e
* @param Throwable $e
* @param string $json
* @return static
*/
public static function failed(JsonException $e, string $json): static
public static function failed(Throwable $e, string $json): static
{
return new static(false, null, $e->getMessage(), $e->getCode(), $e, $json);
}

View File

@ -0,0 +1,30 @@
<?php
namespace Cerbero\JsonParser\Decoders;
/**
* The decoder using the default JSON decoder.
*
*/
class JsonDecoder extends AbstractDecoder
{
/**
* Instantiate the class.
*
* @param bool $decodesToArray
*/
public function __construct(protected bool $decodesToArray = true)
{
}
/**
* Retrieve the decoded value of the given JSON
*
* @param string $json
* @return mixed
*/
protected function decodeJson(string $json): mixed
{
return json_decode($json, $this->decodesToArray, flags: JSON_THROW_ON_ERROR);
}
}

View File

@ -1,17 +0,0 @@
<?php
namespace Cerbero\JsonParser\Decoders;
/**
* The decoder to turn a JSON into an object.
*
*/
class ObjectDecoder extends ArrayDecoder
{
/**
* Whether to decode the JSON into an associative array.
*
* @var bool
*/
protected bool $decodesToArray = false;
}

View File

@ -0,0 +1,30 @@
<?php
namespace Cerbero\JsonParser\Decoders;
/**
* The simdjson decoder.
*
*/
class SimdjsonDecoder extends AbstractDecoder
{
/**
* Instantiate the class.
*
* @param bool $decodesToArray
*/
public function __construct(protected bool $decodesToArray = true)
{
}
/**
* Retrieve the decoded value of the given JSON
*
* @param string $json
* @return mixed
*/
protected function decodeJson(string $json): mixed
{
return simdjson_decode($json, $this->decodesToArray);
}
}

View File

@ -3,7 +3,7 @@
namespace Cerbero\JsonParser;
use Cerbero\JsonParser\Decoders\Decoder;
use Cerbero\JsonParser\Decoders\ObjectDecoder;
use Cerbero\JsonParser\Decoders\SimdjsonDecoder;
use Cerbero\JsonParser\Pointers\Pointer;
use Cerbero\JsonParser\Sources\AnySource;
use Closure;
@ -54,13 +54,14 @@ final class JsonParser implements IteratorAggregate
}
/**
* Set the JSON decoder to turn a JSON into objects
* Set the simdjson decoder
*
* @param bool $decodesToArray
* @return static
*/
public function toObjects(): static
public function simdjson(bool $decodesToArray = true): static
{
return $this->decoder(new ObjectDecoder());
return $this->decoder(new SimdjsonDecoder($decodesToArray));
}
/**