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

View File

@ -2,20 +2,21 @@
namespace Cerbero\JsonParser\Decoders; 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. * Decode the given JSON.
@ -26,8 +27,8 @@ class ArrayDecoder implements Decoder
public function decode(string $json): DecodedValue public function decode(string $json): DecodedValue
{ {
try { try {
$value = json_decode($json, $this->decodesToArray, flags: JSON_THROW_ON_ERROR); $value = $this->decodeJson($json);
} catch (JsonException $e) { } catch (Throwable $e) {
return DecodedValue::failed($e, $json); return DecodedValue::failed($e, $json);
} }

View File

@ -2,7 +2,7 @@
namespace Cerbero\JsonParser\Decoders; namespace Cerbero\JsonParser\Decoders;
use JsonException; use Throwable;
/** /**
* The decoded value. * The decoded value.
@ -20,7 +20,7 @@ final class DecodedValue
public mixed $value = null, public mixed $value = null,
public ?string $error = null, public ?string $error = null,
public ?int $code = null, public ?int $code = null,
public ?JsonException $exception = null, public ?Throwable $exception = null,
public ?string $json = null, public ?string $json = null,
) { ) {
} }
@ -39,11 +39,11 @@ final class DecodedValue
/** /**
* Retrieve a value failed to be decoded * Retrieve a value failed to be decoded
* *
* @param JsonException $e * @param Throwable $e
* @param string $json * @param string $json
* @return static * @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); 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; namespace Cerbero\JsonParser;
use Cerbero\JsonParser\Decoders\Decoder; use Cerbero\JsonParser\Decoders\Decoder;
use Cerbero\JsonParser\Decoders\ObjectDecoder; use Cerbero\JsonParser\Decoders\SimdjsonDecoder;
use Cerbero\JsonParser\Pointers\Pointer; use Cerbero\JsonParser\Pointers\Pointer;
use Cerbero\JsonParser\Sources\AnySource; use Cerbero\JsonParser\Sources\AnySource;
use Closure; 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 * @return static
*/ */
public function toObjects(): static public function simdjson(bool $decodesToArray = true): static
{ {
return $this->decoder(new ObjectDecoder()); return $this->decoder(new SimdjsonDecoder($decodesToArray));
} }
/** /**