Initial Commit

This commit is contained in:
David Stone
2024-11-30 18:24:12 -07:00
commit e8f7955c1c
5432 changed files with 1397750 additions and 0 deletions

View File

@ -0,0 +1,42 @@
<?php
namespace WP_Ultimo\Dependencies\Amp\Serialization;
final class CompressingSerializer implements Serializer
{
private const FLAG_COMPRESSED = 1;
private const COMPRESSION_THRESHOLD = 256;
/** @var Serializer */
private $serializer;
public function __construct(Serializer $serializer)
{
$this->serializer = $serializer;
}
public function serialize($data) : string
{
$serializedData = $this->serializer->serialize($data);
$flags = 0;
if (\strlen($serializedData) > self::COMPRESSION_THRESHOLD) {
$serializedData = @\gzdeflate($serializedData, 1);
if ($serializedData === \false) {
$error = \error_get_last();
throw new SerializationException('Could not compress data: ' . ($error['message'] ?? 'unknown error'));
}
$flags |= self::FLAG_COMPRESSED;
}
return \chr($flags & 0xff) . $serializedData;
}
public function unserialize(string $data)
{
$firstByte = \ord($data[0]);
$data = \substr($data, 1);
if ($firstByte & self::FLAG_COMPRESSED) {
$data = @\gzinflate($data);
if ($data === \false) {
$error = \error_get_last();
throw new SerializationException('Could not decompress data: ' . ($error['message'] ?? 'unknown error'));
}
}
return $this->serializer->unserialize($data);
}
}

View File

@ -0,0 +1,71 @@
<?php
namespace WP_Ultimo\Dependencies\Amp\Serialization;
final class JsonSerializer implements Serializer
{
// Equal to JSON_THROW_ON_ERROR, only available in PHP 7.3+.
private const THROW_ON_ERROR = 4194304;
/** @var bool */
private $associative;
/** @var int */
private $encodeOptions;
/** @var int */
private $decodeOptions;
/** @var int */
private $depth;
/**
* Creates a JSON serializer that decodes objects to associative arrays.
*
* @param int $encodeOptions @see \json_encode() options parameter.
* @param int $decodeOptions @see \json_decode() options parameter.
* @param int $depth Maximum recursion depth.
*
* @return self
*/
public static function withAssociativeArrays(int $encodeOptions = 0, int $decodeOptions = 0, int $depth = 512) : self
{
return new self(\true, $encodeOptions, $decodeOptions, $depth);
}
/**
* Creates a JSON serializer that decodes objects to instances of stdClass.
*
* @param int $encodeOptions @see \json_encode() options parameter.
* @param int $decodeOptions @see \json_decode() options parameter.
* @param int $depth Maximum recursion depth.
*
* @return self
*/
public static function withObjects(int $encodeOptions = 0, int $decodeOptions = 0, int $depth = 512) : self
{
return new self(\false, $encodeOptions, $decodeOptions, $depth);
}
private function __construct(bool $associative, int $encodeOptions = 0, int $decodeOptions = 0, int $depth = 512)
{
$this->associative = $associative;
$this->depth = $depth;
// We don't want to throw on errors, we manually check for errors using json_last_error().
$this->encodeOptions = $encodeOptions & ~self::THROW_ON_ERROR;
$this->decodeOptions = $decodeOptions & ~self::THROW_ON_ERROR;
}
public function serialize($data) : string
{
$result = \json_encode($data, $this->encodeOptions, $this->depth);
switch ($code = \json_last_error()) {
case \JSON_ERROR_NONE:
return $result;
default:
throw new SerializationException(\json_last_error_msg(), $code);
}
}
public function unserialize(string $data)
{
$result = \json_decode($data, $this->associative, $this->depth, $this->decodeOptions);
switch ($code = \json_last_error()) {
case \JSON_ERROR_NONE:
return $result;
default:
throw new SerializationException(\json_last_error_msg(), $code);
}
}
}

View File

@ -0,0 +1,36 @@
<?php
namespace WP_Ultimo\Dependencies\Amp\Serialization;
final class NativeSerializer implements Serializer
{
/** @var string[]|null */
private $allowedClasses;
/**
* @param string[]|null $allowedClasses List of allowed class names to be unserialized. Null for any class.
*/
public function __construct(?array $allowedClasses = null)
{
$this->allowedClasses = $allowedClasses;
}
public function serialize($data) : string
{
try {
return \serialize($data);
} catch (\Throwable $exception) {
throw new SerializationException(\sprintf('The given data could not be serialized: %s', $exception->getMessage()), 0, $exception);
}
}
public function unserialize(string $data)
{
try {
$result = \unserialize($data, ['allowed_classes' => $this->allowedClasses ?? \true]);
if ($result === \false && $data !== \serialize(\false)) {
throw new SerializationException('Invalid data provided to unserialize: ' . encodeUnprintableChars($data));
}
} catch (\Throwable $exception) {
throw new SerializationException('Exception thrown when unserializing data', 0, $exception);
}
return $result;
}
}

View File

@ -0,0 +1,18 @@
<?php
namespace WP_Ultimo\Dependencies\Amp\Serialization;
final class PassthroughSerializer implements Serializer
{
public function serialize($data) : string
{
if (!\is_string($data)) {
throw new SerializationException('Serializer implementation only allows strings');
}
return $data;
}
public function unserialize(string $data) : string
{
return $data;
}
}

View File

@ -0,0 +1,7 @@
<?php
namespace WP_Ultimo\Dependencies\Amp\Serialization;
class SerializationException extends \Exception
{
}

View File

@ -0,0 +1,23 @@
<?php
namespace WP_Ultimo\Dependencies\Amp\Serialization;
interface Serializer
{
/**
* @param mixed $data
*
* @return string
*
* @throws SerializationException
*/
public function serialize($data) : string;
/**
* @param string $data
*
* @return mixed The unserialized data.
*
* @throws SerializationException
*/
public function unserialize(string $data);
}

View File

@ -0,0 +1,15 @@
<?php
namespace WP_Ultimo\Dependencies\Amp\Serialization;
/**
* @param string $data Binary data.
*
* @return string Unprintable characters encoded as \x##.
*/
function encodeUnprintableChars(string $data) : string
{
return \preg_replace_callback("/[^ -~]/", function (array $matches) : string {
return "\\x" . \dechex(\ord($matches[0]));
}, $data);
}