[
  {
    "path": ".gitattributes",
    "content": "/Tests export-ignore\n/phpunit.xml.dist export-ignore\n/.git* export-ignore\n"
  },
  {
    "path": ".github/PULL_REQUEST_TEMPLATE.md",
    "content": "Please do not submit any Pull Requests here. They will be closed.\n---\n\nPlease submit your PR here instead:\nhttps://github.com/symfony/symfony\n\nThis repository is what we call a \"subtree split\": a read-only subset of that main repository.\nWe're looking forward to your PR there!\n"
  },
  {
    "path": ".github/workflows/close-pull-request.yml",
    "content": "name: Close Pull Request\n\non:\n  pull_request_target:\n    types: [opened]\n\njobs:\n  run:\n    runs-on: ubuntu-latest\n    steps:\n    - uses: superbrothers/close-pull-request@v3\n      with:\n        comment: |\n          Thanks for your Pull Request! We love contributions.\n\n          However, you should instead open your PR on the main repository:\n          https://github.com/symfony/symfony\n\n          This repository is what we call a \"subtree split\": a read-only subset of that main repository.\n          We're looking forward to your PR there!\n"
  },
  {
    "path": ".gitignore",
    "content": "composer.lock\nphpunit.xml\nvendor/\n"
  },
  {
    "path": "CHANGELOG.md",
    "content": "CHANGELOG\n=========\n\n7.4\n---\n\n * Add support for adding more default casters to `AbstractCloner::addDefaultCasters()`\n * Select HtmlDumper only if `Accept` header contains \"html\"\n\n7.3\n---\n\n * Add casters for `Dba\\Connection`, `SQLite3Result`, `OpenSSLAsymmetricKey` and `OpenSSLCertificateSigningRequest`\n * Deprecate `ResourceCaster::castCurl()`, `ResourceCaster::castGd()` and `ResourceCaster::castOpensslX509()`\n * Mark all casters as `@internal`\n\n7.2\n---\n\n * Add support for `FORCE_COLOR` environment variable\n * Add support for virtual properties\n\n7.1\n---\n\n * Add support for new DOM extension classes in `DOMCaster`\n\n7.0\n---\n\n * Add argument `$label` to `VarDumper::dump()`\n * Require explicit argument when calling `VarDumper::setHandler()`\n * Remove display of backtrace in `Twig_Template`, only `Twig\\Template` is supported\n\n6.4\n---\n\n * Dump uninitialized properties\n\n6.3\n---\n\n * Add caster for `WeakMap`\n * Add support of named arguments to `dd()` and `dump()` to display the argument name\n * Add support for `Relay\\Relay`\n * Add display of invisible characters\n\n6.2\n---\n\n * Add support for `FFI\\CData` and `FFI\\CType`\n * Deprecate calling `VarDumper::setHandler()` without arguments\n\n5.4\n---\n\n * Add ability to style integer and double values independently\n * Add casters for Symfony's UUIDs and ULIDs\n * Add support for `Fiber`\n\n5.2.0\n-----\n\n * added support for PHPUnit `--colors` option\n * added `VAR_DUMPER_FORMAT=server` env var value support\n * prevent replacing the handler when the `VAR_DUMPER_FORMAT` env var is set\n\n5.1.0\n-----\n\n * added `RdKafka` support\n\n4.4.0\n-----\n\n * added `VarDumperTestTrait::setUpVarDumper()` and `VarDumperTestTrait::tearDownVarDumper()`\n   to configure casters & flags to use in tests\n * added `ImagineCaster` and infrastructure to dump images\n * added the stamps of a message after it is dispatched in `TraceableMessageBus` and `MessengerDataCollector` collected data\n * added `UuidCaster`\n * made all casters final\n * added support for the `NO_COLOR` env var (https://no-color.org/)\n\n4.3.0\n-----\n\n * added `DsCaster` to support dumping the contents of data structures from the Ds extension\n\n4.2.0\n-----\n\n * support selecting the format to use by setting the environment variable `VAR_DUMPER_FORMAT` to `html` or `cli`\n\n4.1.0\n-----\n\n * added a `ServerDumper` to send serialized Data clones to a server\n * added a `ServerDumpCommand` and `DumpServer` to run a server collecting\n   and displaying dumps on a single place with multiple formats support\n * added `CliDescriptor` and `HtmlDescriptor` descriptors for `server:dump` CLI and HTML formats support\n\n4.0.0\n-----\n\n * support for passing `\\ReflectionClass` instances to the `Caster::castObject()`\n   method has been dropped, pass class names as strings instead\n * the `Data::getRawData()` method has been removed\n * the `VarDumperTestTrait::assertDumpEquals()` method expects a 3rd `$filter = 0`\n   argument and moves `$message = ''` argument at 4th position.\n * the `VarDumperTestTrait::assertDumpMatchesFormat()` method expects a 3rd `$filter = 0`\n   argument and moves `$message = ''` argument at 4th position.\n\n3.4.0\n-----\n\n * added `AbstractCloner::setMinDepth()` function to ensure minimum tree depth\n * deprecated `MongoCaster`\n\n2.7.0\n-----\n\n * deprecated `Cloner\\Data::getLimitedClone()`. Use `withMaxDepth`, `withMaxItemsPerDepth` or `withRefHandles` instead.\n"
  },
  {
    "path": "Caster/AddressInfoCaster.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Caster;\n\nuse Symfony\\Component\\VarDumper\\Cloner\\Stub;\n\n/**\n * @author Nicolas Grekas <p@tchwork.com>\n *\n * @internal\n */\nfinal class AddressInfoCaster\n{\n    private const MAPS = [\n        'ai_flags' => [\n            1 => 'AI_PASSIVE',\n            2 => 'AI_CANONNAME',\n            4 => 'AI_NUMERICHOST',\n            8 => 'AI_V4MAPPED',\n            16 => 'AI_ALL',\n            32 => 'AI_ADDRCONFIG',\n            64 => 'AI_IDN',\n            128 => 'AI_CANONIDN',\n            1024 => 'AI_NUMERICSERV',\n        ],\n        'ai_family' => [\n            1 => 'AF_UNIX',\n            2 => 'AF_INET',\n            10 => 'AF_INET6',\n            44 => 'AF_DIVERT',\n        ],\n        'ai_socktype' => [\n            1 => 'SOCK_STREAM',\n            2 => 'SOCK_DGRAM',\n            3 => 'SOCK_RAW',\n            4 => 'SOCK_RDM',\n            5 => 'SOCK_SEQPACKET',\n        ],\n        'ai_protocol' => [\n            1 => 'SOL_SOCKET',\n            6 => 'SOL_TCP',\n            17 => 'SOL_UDP',\n            136 => 'SOL_UDPLITE',\n        ],\n    ];\n\n    public static function castAddressInfo(\\AddressInfo $h, array $a, Stub $stub, bool $isNested): array\n    {\n        static $resolvedMaps;\n\n        if (!$resolvedMaps) {\n            foreach (self::MAPS as $k => $map) {\n                foreach ($map as $v => $name) {\n                    if (\\defined($name)) {\n                        $resolvedMaps[$k][\\constant($name)] = $name;\n                    } elseif (!isset($resolvedMaps[$k][$v])) {\n                        $resolvedMaps[$k][$v] = $name;\n                    }\n                }\n            }\n        }\n\n        foreach (socket_addrinfo_explain($h) as $k => $v) {\n            $a[Caster::PREFIX_VIRTUAL.$k] = match (true) {\n                'ai_flags' === $k => ConstStub::fromBitfield($v, $resolvedMaps[$k]),\n                isset($resolvedMaps[$k][$v]) => new ConstStub($resolvedMaps[$k][$v], $v),\n                default => $v,\n            };\n        }\n\n        return $a;\n    }\n}\n"
  },
  {
    "path": "Caster/AmqpCaster.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Caster;\n\nuse Symfony\\Component\\VarDumper\\Cloner\\Stub;\n\n/**\n * Casts Amqp related classes to array representation.\n *\n * @author Grégoire Pineau <lyrixx@lyrixx.info>\n *\n * @final\n *\n * @internal\n */\nclass AmqpCaster\n{\n    private const FLAGS = [\n        \\AMQP_DURABLE => 'AMQP_DURABLE',\n        \\AMQP_PASSIVE => 'AMQP_PASSIVE',\n        \\AMQP_EXCLUSIVE => 'AMQP_EXCLUSIVE',\n        \\AMQP_AUTODELETE => 'AMQP_AUTODELETE',\n        \\AMQP_INTERNAL => 'AMQP_INTERNAL',\n        \\AMQP_NOLOCAL => 'AMQP_NOLOCAL',\n        \\AMQP_AUTOACK => 'AMQP_AUTOACK',\n        \\AMQP_IFEMPTY => 'AMQP_IFEMPTY',\n        \\AMQP_IFUNUSED => 'AMQP_IFUNUSED',\n        \\AMQP_MANDATORY => 'AMQP_MANDATORY',\n        \\AMQP_IMMEDIATE => 'AMQP_IMMEDIATE',\n        \\AMQP_MULTIPLE => 'AMQP_MULTIPLE',\n        \\AMQP_NOWAIT => 'AMQP_NOWAIT',\n        \\AMQP_REQUEUE => 'AMQP_REQUEUE',\n    ];\n\n    private const EXCHANGE_TYPES = [\n        \\AMQP_EX_TYPE_DIRECT => 'AMQP_EX_TYPE_DIRECT',\n        \\AMQP_EX_TYPE_FANOUT => 'AMQP_EX_TYPE_FANOUT',\n        \\AMQP_EX_TYPE_TOPIC => 'AMQP_EX_TYPE_TOPIC',\n        \\AMQP_EX_TYPE_HEADERS => 'AMQP_EX_TYPE_HEADERS',\n    ];\n\n    public static function castConnection(\\AMQPConnection $c, array $a, Stub $stub, bool $isNested): array\n    {\n        $prefix = Caster::PREFIX_VIRTUAL;\n\n        $a += [\n            $prefix.'is_connected' => $c->isConnected(),\n        ];\n\n        // Recent version of the extension already expose private properties\n        if (isset($a[\"\\x00AMQPConnection\\x00login\"])) {\n            return $a;\n        }\n\n        // BC layer in the amqp lib\n        if (method_exists($c, 'getReadTimeout')) {\n            $timeout = $c->getReadTimeout();\n        } else {\n            $timeout = $c->getTimeout();\n        }\n\n        $a += [\n            $prefix.'is_connected' => $c->isConnected(),\n            $prefix.'login' => $c->getLogin(),\n            $prefix.'password' => $c->getPassword(),\n            $prefix.'host' => $c->getHost(),\n            $prefix.'vhost' => $c->getVhost(),\n            $prefix.'port' => $c->getPort(),\n            $prefix.'read_timeout' => $timeout,\n        ];\n\n        return $a;\n    }\n\n    public static function castChannel(\\AMQPChannel $c, array $a, Stub $stub, bool $isNested): array\n    {\n        $prefix = Caster::PREFIX_VIRTUAL;\n\n        $a += [\n            $prefix.'is_connected' => $c->isConnected(),\n            $prefix.'channel_id' => $c->getChannelId(),\n        ];\n\n        // Recent version of the extension already expose private properties\n        if (isset($a[\"\\x00AMQPChannel\\x00connection\"])) {\n            return $a;\n        }\n\n        $a += [\n            $prefix.'connection' => $c->getConnection(),\n            $prefix.'prefetch_size' => $c->getPrefetchSize(),\n            $prefix.'prefetch_count' => $c->getPrefetchCount(),\n        ];\n\n        return $a;\n    }\n\n    public static function castQueue(\\AMQPQueue $c, array $a, Stub $stub, bool $isNested): array\n    {\n        $prefix = Caster::PREFIX_VIRTUAL;\n\n        $a += [\n            $prefix.'flags' => self::extractFlags($c->getFlags()),\n        ];\n\n        // Recent version of the extension already expose private properties\n        if (isset($a[\"\\x00AMQPQueue\\x00name\"])) {\n            return $a;\n        }\n\n        $a += [\n            $prefix.'connection' => $c->getConnection(),\n            $prefix.'channel' => $c->getChannel(),\n            $prefix.'name' => $c->getName(),\n            $prefix.'arguments' => $c->getArguments(),\n        ];\n\n        return $a;\n    }\n\n    public static function castExchange(\\AMQPExchange $c, array $a, Stub $stub, bool $isNested): array\n    {\n        $prefix = Caster::PREFIX_VIRTUAL;\n\n        $a += [\n            $prefix.'flags' => self::extractFlags($c->getFlags()),\n        ];\n\n        $type = isset(self::EXCHANGE_TYPES[$c->getType()]) ? new ConstStub(self::EXCHANGE_TYPES[$c->getType()], $c->getType()) : $c->getType();\n\n        // Recent version of the extension already expose private properties\n        if (isset($a[\"\\x00AMQPExchange\\x00name\"])) {\n            $a[\"\\x00AMQPExchange\\x00type\"] = $type;\n\n            return $a;\n        }\n\n        $a += [\n            $prefix.'connection' => $c->getConnection(),\n            $prefix.'channel' => $c->getChannel(),\n            $prefix.'name' => $c->getName(),\n            $prefix.'type' => $type,\n            $prefix.'arguments' => $c->getArguments(),\n        ];\n\n        return $a;\n    }\n\n    public static function castEnvelope(\\AMQPEnvelope $c, array $a, Stub $stub, bool $isNested, int $filter = 0): array\n    {\n        $prefix = Caster::PREFIX_VIRTUAL;\n\n        $deliveryMode = new ConstStub($c->getDeliveryMode().(2 === $c->getDeliveryMode() ? ' (persistent)' : ' (non-persistent)'), $c->getDeliveryMode());\n\n        // Recent version of the extension already expose private properties\n        if (isset($a[\"\\x00AMQPEnvelope\\x00body\"])) {\n            $a[\"\\0AMQPEnvelope\\0delivery_mode\"] = $deliveryMode;\n\n            return $a;\n        }\n\n        if (!($filter & Caster::EXCLUDE_VERBOSE)) {\n            $a += [$prefix.'body' => $c->getBody()];\n        }\n\n        $a += [\n            $prefix.'delivery_tag' => $c->getDeliveryTag(),\n            $prefix.'is_redelivery' => $c->isRedelivery(),\n            $prefix.'exchange_name' => $c->getExchangeName(),\n            $prefix.'routing_key' => $c->getRoutingKey(),\n            $prefix.'content_type' => $c->getContentType(),\n            $prefix.'content_encoding' => $c->getContentEncoding(),\n            $prefix.'headers' => $c->getHeaders(),\n            $prefix.'delivery_mode' => $deliveryMode,\n            $prefix.'priority' => $c->getPriority(),\n            $prefix.'correlation_id' => $c->getCorrelationId(),\n            $prefix.'reply_to' => $c->getReplyTo(),\n            $prefix.'expiration' => $c->getExpiration(),\n            $prefix.'message_id' => $c->getMessageId(),\n            $prefix.'timestamp' => $c->getTimeStamp(),\n            $prefix.'type' => $c->getType(),\n            $prefix.'user_id' => $c->getUserId(),\n            $prefix.'app_id' => $c->getAppId(),\n        ];\n\n        return $a;\n    }\n\n    private static function extractFlags(int $flags): ConstStub\n    {\n        $flagsArray = [];\n\n        foreach (self::FLAGS as $value => $name) {\n            if ($flags & $value) {\n                $flagsArray[] = $name;\n            }\n        }\n\n        if (!$flagsArray) {\n            $flagsArray = ['AMQP_NOPARAM'];\n        }\n\n        return new ConstStub(implode('|', $flagsArray), $flags);\n    }\n}\n"
  },
  {
    "path": "Caster/ArgsStub.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Caster;\n\nuse Symfony\\Component\\VarDumper\\Cloner\\Stub;\n\n/**\n * Represents a list of function arguments.\n *\n * @author Nicolas Grekas <p@tchwork.com>\n */\nclass ArgsStub extends EnumStub\n{\n    private static array $parameters = [];\n\n    public function __construct(array $args, string $function, ?string $class)\n    {\n        [$variadic, $params] = self::getParameters($function, $class);\n\n        $values = [];\n        foreach ($args as $k => $v) {\n            $values[$k] = !\\is_scalar($v) && !$v instanceof Stub ? new CutStub($v) : $v;\n        }\n        if (null === $params) {\n            parent::__construct($values, false);\n\n            return;\n        }\n        if (\\count($values) < \\count($params)) {\n            $params = \\array_slice($params, 0, \\count($values));\n        } elseif (\\count($values) > \\count($params)) {\n            $values[] = new EnumStub(array_splice($values, \\count($params)), false);\n            $params[] = $variadic;\n        }\n        if (['...'] === $params) {\n            parent::__construct($values[0]->value, false);\n        } else {\n            parent::__construct(array_combine($params, $values));\n        }\n    }\n\n    private static function getParameters(string $function, ?string $class): array\n    {\n        if (isset(self::$parameters[$k = $class.'::'.$function])) {\n            return self::$parameters[$k];\n        }\n\n        try {\n            $r = null !== $class ? new \\ReflectionMethod($class, $function) : new \\ReflectionFunction($function);\n        } catch (\\ReflectionException) {\n            return [null, null];\n        }\n\n        $variadic = '...';\n        $params = [];\n        foreach ($r->getParameters() as $v) {\n            $k = '$'.$v->name;\n            if ($v->isPassedByReference()) {\n                $k = '&'.$k;\n            }\n            if ($v->isVariadic()) {\n                $variadic .= $k;\n            } else {\n                $params[] = $k;\n            }\n        }\n\n        return self::$parameters[$k] = [$variadic, $params];\n    }\n}\n"
  },
  {
    "path": "Caster/Caster.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Caster;\n\nuse Symfony\\Component\\VarDumper\\Cloner\\Stub;\n\n/**\n * Helper for filtering out properties in casters.\n *\n * @author Nicolas Grekas <p@tchwork.com>\n *\n * @final\n */\nclass Caster\n{\n    public const EXCLUDE_VERBOSE = 1;\n    public const EXCLUDE_VIRTUAL = 2;\n    public const EXCLUDE_DYNAMIC = 4;\n    public const EXCLUDE_PUBLIC = 8;\n    public const EXCLUDE_PROTECTED = 16;\n    public const EXCLUDE_PRIVATE = 32;\n    public const EXCLUDE_NULL = 64;\n    public const EXCLUDE_EMPTY = 128;\n    public const EXCLUDE_NOT_IMPORTANT = 256;\n    public const EXCLUDE_STRICT = 512;\n    public const EXCLUDE_UNINITIALIZED = 1024;\n\n    public const PREFIX_VIRTUAL = \"\\0~\\0\";\n    public const PREFIX_DYNAMIC = \"\\0+\\0\";\n    public const PREFIX_PROTECTED = \"\\0*\\0\";\n    // usage: sprintf(Caster::PATTERN_PRIVATE, $class, $property)\n    public const PATTERN_PRIVATE = \"\\0%s\\0%s\";\n\n    private static array $classProperties = [];\n\n    /**\n     * Casts objects to arrays and adds the dynamic property prefix.\n     *\n     * @param bool $hasDebugInfo Whether the __debugInfo method exists on $obj or not\n     *\n     * @internal\n     */\n    public static function castObject(object $obj, string $class, bool $hasDebugInfo = false, ?string $debugClass = null): array\n    {\n        if ($hasDebugInfo) {\n            try {\n                $debugInfo = $obj->__debugInfo();\n            } catch (\\Throwable) {\n                // ignore failing __debugInfo()\n                $hasDebugInfo = false;\n            }\n        }\n\n        $a = $obj instanceof \\Closure ? [] : (array) $obj;\n\n        if ($obj instanceof \\__PHP_Incomplete_Class) {\n            return $a;\n        }\n\n        $classProperties = self::$classProperties[$class] ??= self::getClassProperties(new \\ReflectionClass($class));\n        $a = array_replace($classProperties, $a);\n\n        if ($a) {\n            $debugClass ??= get_debug_type($obj);\n\n            $i = 0;\n            $prefixedKeys = [];\n            foreach ($a as $k => $v) {\n                if (\"\\0\" !== ($k[0] ?? '')) {\n                    if (!isset($classProperties[$k])) {\n                        $prefixedKeys[$i] = self::PREFIX_DYNAMIC.$k;\n                    }\n                } elseif ($debugClass !== $class && 1 === strpos($k, $class)) {\n                    $prefixedKeys[$i] = \"\\0\".$debugClass.strrchr($k, \"\\0\");\n                }\n                ++$i;\n            }\n            if ($prefixedKeys) {\n                $keys = array_keys($a);\n                foreach ($prefixedKeys as $i => $k) {\n                    $keys[$i] = $k;\n                }\n                $a = array_combine($keys, $a);\n            }\n        }\n\n        if ($hasDebugInfo && \\is_array($debugInfo)) {\n            foreach ($debugInfo as $k => $v) {\n                if (!isset($k[0]) || \"\\0\" !== $k[0]) {\n                    if (\\array_key_exists(self::PREFIX_DYNAMIC.$k, $a)) {\n                        continue;\n                    }\n                    $k = self::PREFIX_VIRTUAL.$k;\n                }\n\n                unset($a[$k]);\n                $a[$k] = $v;\n            }\n        }\n\n        return $a;\n    }\n\n    /**\n     * Filters out the specified properties.\n     *\n     * By default, a single match in the $filter bit field filters properties out, following an \"or\" logic.\n     * When EXCLUDE_STRICT is set, an \"and\" logic is applied: all bits must match for a property to be removed.\n     *\n     * @param array    $a                The array containing the properties to filter\n     * @param int      $filter           A bit field of Caster::EXCLUDE_* constants specifying which properties to filter out\n     * @param string[] $listedProperties List of properties to exclude when Caster::EXCLUDE_VERBOSE is set, and to preserve when Caster::EXCLUDE_NOT_IMPORTANT is set\n     * @param int|null &$count           Set to the number of removed properties\n     */\n    public static function filter(array $a, int $filter, array $listedProperties = [], ?int &$count = 0): array\n    {\n        $count = 0;\n\n        foreach ($a as $k => $v) {\n            $type = self::EXCLUDE_STRICT & $filter;\n\n            if (null === $v) {\n                $type |= self::EXCLUDE_NULL & $filter;\n                $type |= self::EXCLUDE_EMPTY & $filter;\n            } elseif (false === $v || '' === $v || '0' === $v || 0 === $v || 0.0 === $v || [] === $v) {\n                $type |= self::EXCLUDE_EMPTY & $filter;\n            } elseif ($v instanceof UninitializedStub) {\n                $type |= self::EXCLUDE_UNINITIALIZED & $filter;\n            }\n            if ((self::EXCLUDE_NOT_IMPORTANT & $filter) && !\\in_array($k, $listedProperties, true)) {\n                $type |= self::EXCLUDE_NOT_IMPORTANT;\n            }\n            if ((self::EXCLUDE_VERBOSE & $filter) && \\in_array($k, $listedProperties, true)) {\n                $type |= self::EXCLUDE_VERBOSE;\n            }\n\n            if (!isset($k[1]) || \"\\0\" !== $k[0]) {\n                $type |= self::EXCLUDE_PUBLIC & $filter;\n            } elseif ('~' === $k[1]) {\n                $type |= self::EXCLUDE_VIRTUAL & $filter;\n            } elseif ('+' === $k[1]) {\n                $type |= self::EXCLUDE_DYNAMIC & $filter;\n            } elseif ('*' === $k[1]) {\n                $type |= self::EXCLUDE_PROTECTED & $filter;\n            } else {\n                $type |= self::EXCLUDE_PRIVATE & $filter;\n            }\n\n            if ((self::EXCLUDE_STRICT & $filter) ? $type === $filter : $type) {\n                unset($a[$k]);\n                ++$count;\n            }\n        }\n\n        return $a;\n    }\n\n    /**\n     * @internal\n     */\n    public static function castPhpIncompleteClass(\\__PHP_Incomplete_Class $c, array $a, Stub $stub, bool $isNested): array\n    {\n        if (isset($a['__PHP_Incomplete_Class_Name'])) {\n            $stub->class .= '('.$a['__PHP_Incomplete_Class_Name'].')';\n            unset($a['__PHP_Incomplete_Class_Name']);\n        }\n\n        return $a;\n    }\n\n    private static function getClassProperties(\\ReflectionClass $class): array\n    {\n        $classProperties = [];\n        $className = $class->name;\n\n        if ($parent = $class->getParentClass()) {\n            $classProperties += self::$classProperties[$parent->name] ??= self::getClassProperties($parent);\n        }\n\n        foreach ($class->getProperties() as $p) {\n            if ($p->isStatic()) {\n                continue;\n            }\n\n            $classProperties[match (true) {\n                $p->isPublic() => $p->name,\n                $p->isProtected() => self::PREFIX_PROTECTED.$p->name,\n                default => \"\\0\".$className.\"\\0\".$p->name,\n            }] = $p->isVirtual() ? new VirtualStub($p) : new UninitializedStub($p);\n        }\n\n        return $classProperties;\n    }\n}\n"
  },
  {
    "path": "Caster/ClassStub.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Caster;\n\nuse Symfony\\Component\\VarDumper\\Cloner\\Stub;\n\n/**\n * Represents a PHP class identifier.\n *\n * @author Nicolas Grekas <p@tchwork.com>\n */\nclass ClassStub extends ConstStub\n{\n    /**\n     * @param string   $identifier A PHP identifier, e.g. a class, method, interface, etc. name\n     * @param callable $callable   The callable targeted by the identifier when it is ambiguous or not a real PHP identifier\n     */\n    public function __construct(string $identifier, callable|array|string|null $callable = null)\n    {\n        $this->value = $identifier;\n\n        try {\n            if (null !== $callable) {\n                if ($callable instanceof \\Closure) {\n                    $r = new \\ReflectionFunction($callable);\n                } elseif (\\is_object($callable)) {\n                    $r = [$callable, '__invoke'];\n                } elseif (\\is_array($callable)) {\n                    $r = $callable;\n                } elseif (false !== $i = strpos($callable, '::')) {\n                    $r = [substr($callable, 0, $i), substr($callable, 2 + $i)];\n                } else {\n                    $r = new \\ReflectionFunction($callable);\n                }\n            } elseif (0 < $i = strpos($identifier, '::') ?: strpos($identifier, '->')) {\n                $r = [substr($identifier, 0, $i), substr($identifier, 2 + $i)];\n            } else {\n                $r = new \\ReflectionClass($identifier);\n            }\n\n            if (\\is_array($r)) {\n                try {\n                    $r = new \\ReflectionMethod($r[0], $r[1]);\n                } catch (\\ReflectionException) {\n                    $r = new \\ReflectionClass($r[0]);\n                }\n            }\n\n            if (str_contains($identifier, \"@anonymous\\0\")) {\n                $this->value = $identifier = preg_replace_callback('/[a-zA-Z_\\x7f-\\xff][\\\\\\\\a-zA-Z0-9_\\x7f-\\xff]*+@anonymous\\x00.*?\\.php(?:0x?|:[0-9]++\\$)?[0-9a-fA-F]++/', static fn ($m) => class_exists($m[0], false) ? (get_parent_class($m[0]) ?: key(class_implements($m[0])) ?: 'class').'@anonymous' : $m[0], $identifier);\n            }\n\n            if (null !== $callable && $r instanceof \\ReflectionFunctionAbstract) {\n                $s = ReflectionCaster::castFunctionAbstract($r, [], new Stub(), true, Caster::EXCLUDE_VERBOSE);\n                $s = ReflectionCaster::getSignature($s);\n\n                if (str_ends_with($identifier, '()')) {\n                    $this->value = substr_replace($identifier, $s, -2);\n                } else {\n                    $this->value .= $s;\n                }\n            }\n        } catch (\\ReflectionException) {\n            return;\n        } finally {\n            if (0 < $i = strrpos($this->value, '\\\\')) {\n                $this->attr['ellipsis'] = \\strlen($this->value) - $i;\n                $this->attr['ellipsis-type'] = 'class';\n                $this->attr['ellipsis-tail'] = 1;\n            }\n        }\n\n        if ($f = $r->getFileName()) {\n            $this->attr['file'] = $f;\n            $this->attr['line'] = $r->getStartLine();\n        }\n    }\n\n    public static function wrapCallable(mixed $callable): mixed\n    {\n        if (\\is_object($callable) || !\\is_callable($callable)) {\n            return $callable;\n        }\n\n        if (!\\is_array($callable)) {\n            $callable = new static($callable, $callable);\n        } elseif (\\is_string($callable[0])) {\n            $callable[0] = new static($callable[0], $callable);\n        } else {\n            $callable[1] = new static($callable[1], $callable);\n        }\n\n        return $callable;\n    }\n}\n"
  },
  {
    "path": "Caster/ConstStub.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Caster;\n\nuse Symfony\\Component\\VarDumper\\Cloner\\Stub;\n\n/**\n * Represents a PHP constant and its value.\n *\n * @author Nicolas Grekas <p@tchwork.com>\n */\nclass ConstStub extends Stub\n{\n    public function __construct(string $name, string|int|float|null $value = null)\n    {\n        $this->class = $name;\n        $this->value = 1 < \\func_num_args() ? $value : $name;\n    }\n\n    public function __toString(): string\n    {\n        return (string) $this->value;\n    }\n\n    /**\n     * @param array<int, string> $values\n     */\n    public static function fromBitfield(int $value, array $values): self\n    {\n        $names = [];\n        foreach ($values as $v => $name) {\n            if ($value & $v) {\n                $names[] = $name;\n            }\n        }\n\n        if (!$names) {\n            $names[] = $values[0] ?? 0;\n        }\n\n        return new self(implode(' | ', $names), $value);\n    }\n}\n"
  },
  {
    "path": "Caster/CurlCaster.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Caster;\n\nuse Symfony\\Component\\VarDumper\\Cloner\\Stub;\n\n/**\n * @author Nicolas Grekas <p@tchwork.com>\n *\n * @internal\n */\nfinal class CurlCaster\n{\n    public static function castCurl(\\CurlHandle $h, array $a, Stub $stub, bool $isNested): array\n    {\n        foreach (curl_getinfo($h) as $key => $val) {\n            $a[Caster::PREFIX_VIRTUAL.$key] = $val;\n        }\n\n        return $a;\n    }\n}\n"
  },
  {
    "path": "Caster/CutArrayStub.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Caster;\n\n/**\n * Represents a cut array.\n *\n * @author Nicolas Grekas <p@tchwork.com>\n */\nclass CutArrayStub extends CutStub\n{\n    public array $preservedSubset;\n\n    public function __construct(array $value, array $preservedKeys)\n    {\n        parent::__construct($value);\n\n        $this->preservedSubset = array_intersect_key($value, array_flip($preservedKeys));\n        $this->cut -= \\count($this->preservedSubset);\n    }\n}\n"
  },
  {
    "path": "Caster/CutStub.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Caster;\n\nuse Symfony\\Component\\VarDumper\\Cloner\\Stub;\n\n/**\n * Represents the main properties of a PHP variable, pre-casted by a caster.\n *\n * @author Nicolas Grekas <p@tchwork.com>\n */\nclass CutStub extends Stub\n{\n    public function __construct(mixed $value)\n    {\n        $this->value = $value;\n\n        switch (\\gettype($value)) {\n            case 'object':\n                $this->type = self::TYPE_OBJECT;\n                $this->class = get_debug_type($value);\n\n                if ($value instanceof \\Closure) {\n                    ReflectionCaster::castClosure($value, [], $this, true, Caster::EXCLUDE_VERBOSE);\n                }\n\n                $this->cut = -1;\n                break;\n\n            case 'array':\n                $this->type = self::TYPE_ARRAY;\n                $this->class = self::ARRAY_ASSOC;\n                $this->cut = $this->value = \\count($value);\n                break;\n\n            case 'resource':\n            case 'unknown type':\n            case 'resource (closed)':\n                $this->type = self::TYPE_RESOURCE;\n                $this->handle = (int) $value;\n                if ('Unknown' === $this->class = @get_resource_type($value)) {\n                    $this->class = 'Closed';\n                }\n                $this->cut = -1;\n                break;\n\n            case 'string':\n                $this->type = self::TYPE_STRING;\n                $this->class = preg_match('//u', $value) ? self::STRING_UTF8 : self::STRING_BINARY;\n                $this->cut = self::STRING_BINARY === $this->class ? \\strlen($value) : mb_strlen($value, 'UTF-8');\n                $this->value = '';\n                break;\n        }\n    }\n}\n"
  },
  {
    "path": "Caster/DOMCaster.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Caster;\n\nuse Symfony\\Component\\VarDumper\\Cloner\\Stub;\n\n/**\n * Casts DOM related classes to array representation.\n *\n * @author Nicolas Grekas <p@tchwork.com>\n *\n * @final\n *\n * @internal\n */\nclass DOMCaster\n{\n    private const ERROR_CODES = [\n        0 => 'DOM_PHP_ERR',\n        \\DOM_INDEX_SIZE_ERR => 'DOM_INDEX_SIZE_ERR',\n        \\DOMSTRING_SIZE_ERR => 'DOMSTRING_SIZE_ERR',\n        \\DOM_HIERARCHY_REQUEST_ERR => 'DOM_HIERARCHY_REQUEST_ERR',\n        \\DOM_WRONG_DOCUMENT_ERR => 'DOM_WRONG_DOCUMENT_ERR',\n        \\DOM_INVALID_CHARACTER_ERR => 'DOM_INVALID_CHARACTER_ERR',\n        \\DOM_NO_DATA_ALLOWED_ERR => 'DOM_NO_DATA_ALLOWED_ERR',\n        \\DOM_NO_MODIFICATION_ALLOWED_ERR => 'DOM_NO_MODIFICATION_ALLOWED_ERR',\n        \\DOM_NOT_FOUND_ERR => 'DOM_NOT_FOUND_ERR',\n        \\DOM_NOT_SUPPORTED_ERR => 'DOM_NOT_SUPPORTED_ERR',\n        \\DOM_INUSE_ATTRIBUTE_ERR => 'DOM_INUSE_ATTRIBUTE_ERR',\n        \\DOM_INVALID_STATE_ERR => 'DOM_INVALID_STATE_ERR',\n        \\DOM_SYNTAX_ERR => 'DOM_SYNTAX_ERR',\n        \\DOM_INVALID_MODIFICATION_ERR => 'DOM_INVALID_MODIFICATION_ERR',\n        \\DOM_NAMESPACE_ERR => 'DOM_NAMESPACE_ERR',\n        \\DOM_INVALID_ACCESS_ERR => 'DOM_INVALID_ACCESS_ERR',\n        \\DOM_VALIDATION_ERR => 'DOM_VALIDATION_ERR',\n    ];\n\n    private const NODE_TYPES = [\n        \\XML_ELEMENT_NODE => 'XML_ELEMENT_NODE',\n        \\XML_ATTRIBUTE_NODE => 'XML_ATTRIBUTE_NODE',\n        \\XML_TEXT_NODE => 'XML_TEXT_NODE',\n        \\XML_CDATA_SECTION_NODE => 'XML_CDATA_SECTION_NODE',\n        \\XML_ENTITY_REF_NODE => 'XML_ENTITY_REF_NODE',\n        \\XML_ENTITY_NODE => 'XML_ENTITY_NODE',\n        \\XML_PI_NODE => 'XML_PI_NODE',\n        \\XML_COMMENT_NODE => 'XML_COMMENT_NODE',\n        \\XML_DOCUMENT_NODE => 'XML_DOCUMENT_NODE',\n        \\XML_DOCUMENT_TYPE_NODE => 'XML_DOCUMENT_TYPE_NODE',\n        \\XML_DOCUMENT_FRAG_NODE => 'XML_DOCUMENT_FRAG_NODE',\n        \\XML_NOTATION_NODE => 'XML_NOTATION_NODE',\n        \\XML_HTML_DOCUMENT_NODE => 'XML_HTML_DOCUMENT_NODE',\n        \\XML_DTD_NODE => 'XML_DTD_NODE',\n        \\XML_ELEMENT_DECL_NODE => 'XML_ELEMENT_DECL_NODE',\n        \\XML_ATTRIBUTE_DECL_NODE => 'XML_ATTRIBUTE_DECL_NODE',\n        \\XML_ENTITY_DECL_NODE => 'XML_ENTITY_DECL_NODE',\n        \\XML_NAMESPACE_DECL_NODE => 'XML_NAMESPACE_DECL_NODE',\n    ];\n\n    public static function castException(\\DOMException|\\Dom\\Exception $e, array $a, Stub $stub, bool $isNested): array\n    {\n        $k = Caster::PREFIX_PROTECTED.'code';\n        if (isset($a[$k], self::ERROR_CODES[$a[$k]])) {\n            $a[$k] = new ConstStub(self::ERROR_CODES[$a[$k]], $a[$k]);\n        }\n\n        return $a;\n    }\n\n    public static function castLength($dom, array $a, Stub $stub, bool $isNested): array\n    {\n        return $a;\n    }\n\n    public static function castImplementation(\\DOMImplementation|\\Dom\\Implementation $dom, array $a, Stub $stub, bool $isNested): array\n    {\n        $a += [\n            Caster::PREFIX_VIRTUAL.'Core' => '1.0',\n            Caster::PREFIX_VIRTUAL.'XML' => '2.0',\n        ];\n\n        return $a;\n    }\n\n    public static function castNode(\\DOMNode|\\Dom\\Node $dom, array $a, Stub $stub, bool $isNested): array\n    {\n        return self::castDom($dom, $a, $stub, $isNested);\n    }\n\n    public static function castNameSpaceNode(\\DOMNameSpaceNode $dom, array $a, Stub $stub, bool $isNested): array\n    {\n        return self::castDom($dom, $a, $stub, $isNested);\n    }\n\n    public static function castDocument(\\DOMDocument $dom, array $a, Stub $stub, bool $isNested, int $filter = 0): array\n    {\n        if (!($filter & Caster::EXCLUDE_VERBOSE)) {\n            $formatOutput = $dom->formatOutput;\n            $dom->formatOutput = true;\n            $a += [Caster::PREFIX_VIRTUAL.'xml' => $dom->saveXML()];\n            $dom->formatOutput = $formatOutput;\n        }\n\n        return $a;\n    }\n\n    public static function castXMLDocument(\\Dom\\XMLDocument $dom, array $a, Stub $stub, bool $isNested, int $filter = 0): array\n    {\n        if (!($filter & Caster::EXCLUDE_VERBOSE)) {\n            $formatOutput = $dom->formatOutput;\n            $dom->formatOutput = true;\n            $a += [Caster::PREFIX_VIRTUAL.'xml' => $dom->saveXML()];\n            $dom->formatOutput = $formatOutput;\n        }\n\n        return $a;\n    }\n\n    public static function castHTMLDocument(\\Dom\\HTMLDocument $dom, array $a, Stub $stub, bool $isNested, int $filter = 0): array\n    {\n        if (!($filter & Caster::EXCLUDE_VERBOSE)) {\n            $a += [Caster::PREFIX_VIRTUAL.'html' => $dom->saveHTML()];\n        }\n\n        return $a;\n    }\n\n    public static function castCharacterData(\\DOMCharacterData|\\Dom\\CharacterData $dom, array $a, Stub $stub, bool $isNested): array\n    {\n        return $a;\n    }\n\n    public static function castAttr(\\DOMAttr|\\Dom\\Attr $dom, array $a, Stub $stub, bool $isNested): array\n    {\n        return $a;\n    }\n\n    public static function castElement(\\DOMElement|\\Dom\\Element $dom, array $a, Stub $stub, bool $isNested): array\n    {\n        return $a;\n    }\n\n    public static function castText(\\DOMText|\\Dom\\Text $dom, array $a, Stub $stub, bool $isNested): array\n    {\n        return $a;\n    }\n\n    public static function castDocumentType(\\DOMDocumentType|\\Dom\\DocumentType $dom, array $a, Stub $stub, bool $isNested): array\n    {\n        return $a;\n    }\n\n    public static function castNotation(\\DOMNotation|\\Dom\\Notation $dom, array $a, Stub $stub, bool $isNested): array\n    {\n        return $a;\n    }\n\n    public static function castEntity(\\DOMEntity|\\Dom\\Entity $dom, array $a, Stub $stub, bool $isNested): array\n    {\n        return $a;\n    }\n\n    public static function castProcessingInstruction(\\DOMProcessingInstruction|\\Dom\\ProcessingInstruction $dom, array $a, Stub $stub, bool $isNested): array\n    {\n        return $a;\n    }\n\n    public static function castXPath(\\DOMXPath|\\Dom\\XPath $dom, array $a, Stub $stub, bool $isNested): array\n    {\n        return self::castDom($dom, $a, $stub, $isNested);\n    }\n\n    public static function castDom($dom, array $a, Stub $stub, bool $isNested, int $filter = 0): array\n    {\n        foreach ($a as $k => $v) {\n            if ('encoding' === $k && $dom instanceof \\DOMEntity\n                || \\in_array($k, ['actualEncoding', 'config', 'standalone', 'version'], true)\n            ) {\n                continue; // deprecated properties\n            }\n\n            $v = $dom->$k;\n\n            $a[$k] = match (true) {\n                $v instanceof \\DOMNode || $v instanceof \\Dom\\Node => new CutStub($v),\n                'nodeType' === $k => new ConstStub(self::NODE_TYPES[$v], $v),\n                'baseURI' === $k && $v,\n                'documentURI' === $k && $v => new LinkStub($v),\n                default => $v,\n            };\n        }\n\n        if ($dom instanceof \\IteratorAggregate) {\n            foreach ($dom as $k => $v) {\n                $a[Caster::PREFIX_VIRTUAL.$k] = $v;\n            }\n        }\n\n        return $a;\n    }\n}\n"
  },
  {
    "path": "Caster/DateCaster.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Caster;\n\nuse Symfony\\Component\\VarDumper\\Cloner\\Stub;\n\n/**\n * Casts DateTimeInterface related classes to array representation.\n *\n * @author Dany Maillard <danymaillard93b@gmail.com>\n *\n * @final\n *\n * @internal\n */\nclass DateCaster\n{\n    private const PERIOD_LIMIT = 3;\n\n    public static function castDateTime(\\DateTimeInterface $d, array $a, Stub $stub, bool $isNested, int $filter): array\n    {\n        $prefix = Caster::PREFIX_VIRTUAL;\n        $location = $d->getTimezone() ? $d->getTimezone()->getLocation() : null;\n        $fromNow = (new \\DateTimeImmutable())->diff($d);\n\n        $title = $d->format('l, F j, Y')\n            .\"\\n\".self::formatInterval($fromNow).' from now'\n            .($location ? ($d->format('I') ? \"\\nDST On\" : \"\\nDST Off\") : '')\n        ;\n\n        unset(\n            $a[Caster::PREFIX_DYNAMIC.'date'],\n            $a[Caster::PREFIX_DYNAMIC.'timezone'],\n            $a[Caster::PREFIX_DYNAMIC.'timezone_type']\n        );\n        $a[$prefix.'date'] = new ConstStub(self::formatDateTime($d, $location ? ' e (P)' : ' P'), $title);\n\n        $stub->class .= $d->format(' @U');\n\n        return $a;\n    }\n\n    public static function castInterval(\\DateInterval $interval, array $a, Stub $stub, bool $isNested, int $filter): array\n    {\n        $now = new \\DateTimeImmutable('@0', new \\DateTimeZone('UTC'));\n        $numberOfSeconds = $now->add($interval)->getTimestamp() - $now->getTimestamp();\n        $title = number_format($numberOfSeconds, 0, '.', ' ').'s';\n\n        $i = [Caster::PREFIX_VIRTUAL.'interval' => new ConstStub(self::formatInterval($interval), $title)];\n\n        return $filter & Caster::EXCLUDE_VERBOSE ? $i : $i + $a;\n    }\n\n    private static function formatInterval(\\DateInterval $i): string\n    {\n        $format = '%R ';\n\n        if (0 === $i->y && 0 === $i->m && ($i->h >= 24 || $i->i >= 60 || $i->s >= 60)) {\n            $d = new \\DateTimeImmutable('@0', new \\DateTimeZone('UTC'));\n            $i = $d->diff($d->add($i)); // recalculate carry over points\n            $format .= 0 < $i->days ? '%ad ' : '';\n        } else {\n            $format .= ($i->y ? '%yy ' : '').($i->m ? '%mm ' : '').($i->d ? '%dd ' : '');\n        }\n\n        $format .= $i->h || $i->i || $i->s || $i->f ? '%H:%I:'.self::formatSeconds($i->s, substr($i->f, 2)) : '';\n        $format = '%R ' === $format ? '0s' : $format;\n\n        return $i->format(rtrim($format));\n    }\n\n    public static function castTimeZone(\\DateTimeZone $timeZone, array $a, Stub $stub, bool $isNested, int $filter): array\n    {\n        $location = $timeZone->getLocation();\n        $formatted = (new \\DateTimeImmutable('now', $timeZone))->format($location ? 'e (P)' : 'P');\n        $title = $location && \\extension_loaded('intl') ? \\Locale::getDisplayRegion('-'.$location['country_code']) : '';\n\n        $z = [Caster::PREFIX_VIRTUAL.'timezone' => new ConstStub($formatted, $title)];\n\n        return $filter & Caster::EXCLUDE_VERBOSE ? $z : $z + $a;\n    }\n\n    public static function castPeriod(\\DatePeriod $p, array $a, Stub $stub, bool $isNested, int $filter): array\n    {\n        $dates = [];\n        foreach (clone $p as $i => $d) {\n            if (self::PERIOD_LIMIT === $i) {\n                $now = new \\DateTimeImmutable('now', new \\DateTimeZone('UTC'));\n                $dates[] = \\sprintf('%s more', ($end = $p->getEndDate())\n                    ? ceil(($end->format('U.u') - $d->format('U.u')) / ((int) $now->add($p->getDateInterval())->format('U.u') - (int) $now->format('U.u')))\n                    : $p->recurrences - $i\n                );\n                break;\n            }\n            $dates[] = \\sprintf('%s) %s', $i + 1, self::formatDateTime($d));\n        }\n\n        $period = \\sprintf(\n            'every %s, from %s%s %s',\n            self::formatInterval($p->getDateInterval()),\n            $p->include_start_date ? '[' : ']',\n            self::formatDateTime($p->getStartDate()),\n            ($end = $p->getEndDate()) ? 'to '.self::formatDateTime($end).($p->include_end_date ? ']' : '[') : 'recurring '.$p->recurrences.' time/s'\n        );\n\n        $p = [Caster::PREFIX_VIRTUAL.'period' => new ConstStub($period, implode(\"\\n\", $dates))];\n\n        return $filter & Caster::EXCLUDE_VERBOSE ? $p : $p + $a;\n    }\n\n    private static function formatDateTime(\\DateTimeInterface $d, string $extra = ''): string\n    {\n        return $d->format('Y-m-d H:i:'.self::formatSeconds($d->format('s'), $d->format('u')).$extra);\n    }\n\n    private static function formatSeconds(string $s, string $us): string\n    {\n        return \\sprintf('%02d.%s', $s, 0 === ($len = \\strlen($t = rtrim($us, '0'))) ? '0' : ($len <= 3 ? str_pad($t, 3, '0') : $us));\n    }\n}\n"
  },
  {
    "path": "Caster/DoctrineCaster.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Caster;\n\nuse Doctrine\\Common\\Proxy\\Proxy as CommonProxy;\nuse Doctrine\\ORM\\PersistentCollection;\nuse Doctrine\\ORM\\Proxy\\Proxy as OrmProxy;\nuse Symfony\\Component\\VarDumper\\Cloner\\Stub;\n\n/**\n * Casts Doctrine related classes to array representation.\n *\n * @author Nicolas Grekas <p@tchwork.com>\n *\n * @final\n *\n * @internal\n */\nclass DoctrineCaster\n{\n    public static function castCommonProxy(CommonProxy $proxy, array $a, Stub $stub, bool $isNested): array\n    {\n        foreach (['__cloner__', '__initializer__'] as $k) {\n            if (\\array_key_exists($k, $a)) {\n                unset($a[$k]);\n                ++$stub->cut;\n            }\n        }\n\n        return $a;\n    }\n\n    public static function castOrmProxy(OrmProxy $proxy, array $a, Stub $stub, bool $isNested): array\n    {\n        foreach (['_entityPersister', '_identifier'] as $k) {\n            if (\\array_key_exists($k = \"\\0Doctrine\\\\ORM\\\\Proxy\\\\Proxy\\0\".$k, $a)) {\n                unset($a[$k]);\n                ++$stub->cut;\n            }\n        }\n\n        return $a;\n    }\n\n    public static function castPersistentCollection(PersistentCollection $coll, array $a, Stub $stub, bool $isNested): array\n    {\n        foreach (['snapshot', 'association', 'typeClass'] as $k) {\n            if (\\array_key_exists($k = \"\\0Doctrine\\\\ORM\\\\PersistentCollection\\0\".$k, $a)) {\n                $a[$k] = new CutStub($a[$k]);\n            }\n        }\n\n        return $a;\n    }\n}\n"
  },
  {
    "path": "Caster/DsCaster.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Caster;\n\nuse Ds\\Collection;\nuse Ds\\Map;\nuse Ds\\Pair;\nuse Symfony\\Component\\VarDumper\\Cloner\\Stub;\n\n/**\n * Casts Ds extension classes to array representation.\n *\n * @author Jáchym Toušek <enumag@gmail.com>\n *\n * @final\n */\nclass DsCaster\n{\n    public static function castCollection(Collection $c, array $a, Stub $stub, bool $isNested): array\n    {\n        $a[Caster::PREFIX_VIRTUAL.'count'] = $c->count();\n        $a[Caster::PREFIX_VIRTUAL.'capacity'] = $c->capacity();\n\n        if (!$c instanceof Map) {\n            $a += $c->toArray();\n        }\n\n        return $a;\n    }\n\n    public static function castMap(Map $c, array $a, Stub $stub, bool $isNested): array\n    {\n        foreach ($c as $k => $v) {\n            $a[] = new DsPairStub($k, $v);\n        }\n\n        return $a;\n    }\n\n    public static function castPair(Pair $c, array $a, Stub $stub, bool $isNested): array\n    {\n        foreach ($c->toArray() as $k => $v) {\n            $a[Caster::PREFIX_VIRTUAL.$k] = $v;\n        }\n\n        return $a;\n    }\n\n    public static function castPairStub(DsPairStub $c, array $a, Stub $stub, bool $isNested): array\n    {\n        if ($isNested) {\n            $stub->class = Pair::class;\n            $stub->value = null;\n            $stub->handle = 0;\n\n            $a = $c->value;\n        }\n\n        return $a;\n    }\n}\n"
  },
  {
    "path": "Caster/DsPairStub.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Caster;\n\nuse Symfony\\Component\\VarDumper\\Cloner\\Stub;\n\n/**\n * @author Nicolas Grekas <p@tchwork.com>\n */\nclass DsPairStub extends Stub\n{\n    public function __construct(mixed $key, mixed $value)\n    {\n        $this->value = [\n            Caster::PREFIX_VIRTUAL.'key' => $key,\n            Caster::PREFIX_VIRTUAL.'value' => $value,\n        ];\n    }\n}\n"
  },
  {
    "path": "Caster/EnumStub.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Caster;\n\nuse Symfony\\Component\\VarDumper\\Cloner\\Stub;\n\n/**\n * Represents an enumeration of values.\n *\n * @author Nicolas Grekas <p@tchwork.com>\n */\nclass EnumStub extends Stub\n{\n    public function __construct(\n        array $values,\n        public bool $dumpKeys = true,\n    ) {\n        $this->value = $values;\n    }\n}\n"
  },
  {
    "path": "Caster/ExceptionCaster.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Caster;\n\nuse Symfony\\Component\\ErrorHandler\\Exception\\FlattenException;\nuse Symfony\\Component\\ErrorHandler\\Exception\\SilencedErrorContext;\nuse Symfony\\Component\\VarDumper\\Cloner\\Stub;\nuse Symfony\\Component\\VarDumper\\Exception\\ThrowingCasterException;\n\n/**\n * Casts common Exception classes to array representation.\n *\n * @author Nicolas Grekas <p@tchwork.com>\n *\n * @final\n *\n * @internal\n */\nclass ExceptionCaster\n{\n    public static int $srcContext = 1;\n    public static bool $traceArgs = true;\n    public static array $errorTypes = [\n        \\E_DEPRECATED => 'E_DEPRECATED',\n        \\E_USER_DEPRECATED => 'E_USER_DEPRECATED',\n        \\E_RECOVERABLE_ERROR => 'E_RECOVERABLE_ERROR',\n        \\E_ERROR => 'E_ERROR',\n        \\E_WARNING => 'E_WARNING',\n        \\E_PARSE => 'E_PARSE',\n        \\E_NOTICE => 'E_NOTICE',\n        \\E_CORE_ERROR => 'E_CORE_ERROR',\n        \\E_CORE_WARNING => 'E_CORE_WARNING',\n        \\E_COMPILE_ERROR => 'E_COMPILE_ERROR',\n        \\E_COMPILE_WARNING => 'E_COMPILE_WARNING',\n        \\E_USER_ERROR => 'E_USER_ERROR',\n        \\E_USER_WARNING => 'E_USER_WARNING',\n        \\E_USER_NOTICE => 'E_USER_NOTICE',\n        2048 => 'E_STRICT',\n    ];\n\n    private static array $framesCache = [];\n\n    public static function castError(\\Error $e, array $a, Stub $stub, bool $isNested, int $filter = 0): array\n    {\n        return self::filterExceptionArray($stub->class, $a, \"\\0Error\\0\", $filter);\n    }\n\n    public static function castException(\\Exception $e, array $a, Stub $stub, bool $isNested, int $filter = 0): array\n    {\n        return self::filterExceptionArray($stub->class, $a, \"\\0Exception\\0\", $filter);\n    }\n\n    public static function castErrorException(\\ErrorException $e, array $a, Stub $stub, bool $isNested): array\n    {\n        if (isset($a[$s = Caster::PREFIX_PROTECTED.'severity'], self::$errorTypes[$a[$s]])) {\n            $a[$s] = new ConstStub(self::$errorTypes[$a[$s]], $a[$s]);\n        }\n\n        return $a;\n    }\n\n    public static function castThrowingCasterException(ThrowingCasterException $e, array $a, Stub $stub, bool $isNested): array\n    {\n        $trace = Caster::PREFIX_VIRTUAL.'trace';\n        $prefix = Caster::PREFIX_PROTECTED;\n        $xPrefix = \"\\0Exception\\0\";\n\n        if (isset($a[$xPrefix.'previous'], $a[$trace]) && $a[$xPrefix.'previous'] instanceof \\Exception) {\n            $b = (array) $a[$xPrefix.'previous'];\n            $class = get_debug_type($a[$xPrefix.'previous']);\n            self::traceUnshift($b[$xPrefix.'trace'], $class, $b[$prefix.'file'], $b[$prefix.'line']);\n            $a[$trace] = new TraceStub($b[$xPrefix.'trace'], false, 0, -\\count($a[$trace]->value));\n        }\n\n        unset($a[$xPrefix.'previous'], $a[$prefix.'code'], $a[$prefix.'file'], $a[$prefix.'line']);\n\n        return $a;\n    }\n\n    public static function castSilencedErrorContext(SilencedErrorContext $e, array $a, Stub $stub, bool $isNested): array\n    {\n        $sPrefix = \"\\0\".SilencedErrorContext::class.\"\\0\";\n\n        if (!isset($a[$s = $sPrefix.'severity'])) {\n            return $a;\n        }\n\n        if (isset(self::$errorTypes[$a[$s]])) {\n            $a[$s] = new ConstStub(self::$errorTypes[$a[$s]], $a[$s]);\n        }\n\n        $trace = [[\n            'file' => $a[$sPrefix.'file'],\n            'line' => $a[$sPrefix.'line'],\n        ]];\n\n        if (isset($a[$sPrefix.'trace'])) {\n            $trace = array_merge($trace, $a[$sPrefix.'trace']);\n        }\n\n        unset($a[$sPrefix.'file'], $a[$sPrefix.'line'], $a[$sPrefix.'trace']);\n        $a[Caster::PREFIX_VIRTUAL.'trace'] = new TraceStub($trace, self::$traceArgs);\n\n        return $a;\n    }\n\n    public static function castTraceStub(TraceStub $trace, array $a, Stub $stub, bool $isNested): array\n    {\n        if (!$isNested) {\n            return $a;\n        }\n        $stub->class = '';\n        $stub->handle = 0;\n        $frames = $trace->value;\n        $prefix = Caster::PREFIX_VIRTUAL;\n\n        $a = [];\n        $j = \\count($frames);\n        if (0 > $i = $trace->sliceOffset) {\n            $i = max(0, $j + $i);\n        }\n        if (!isset($trace->value[$i])) {\n            return [];\n        }\n        $lastCall = isset($frames[$i]['function']) ? (isset($frames[$i]['class']) ? $frames[0]['class'].$frames[$i]['type'] : '').$frames[$i]['function'].'()' : '';\n        $frames[] = ['function' => ''];\n        $collapse = false;\n\n        for ($j += $trace->numberingOffset - $i++; isset($frames[$i]); ++$i, --$j) {\n            $f = $frames[$i];\n            $call = isset($f['function']) ? (isset($f['class']) ? $f['class'].$f['type'] : '').$f['function'] : '???';\n\n            $frame = new FrameStub(\n                [\n                    'object' => $f['object'] ?? null,\n                    'class' => $f['class'] ?? null,\n                    'type' => $f['type'] ?? null,\n                    'function' => $f['function'] ?? null,\n                ] + $frames[$i - 1],\n                false,\n                true\n            );\n            $f = self::castFrameStub($frame, [], $frame, true);\n            if (isset($f[$prefix.'src'])) {\n                foreach ($f[$prefix.'src']->value as $label => $frame) {\n                    if (str_starts_with($label, \"\\0~collapse=0\")) {\n                        if ($collapse) {\n                            $label = substr_replace($label, '1', 11, 1);\n                        } else {\n                            $collapse = true;\n                        }\n                    }\n                    $label = substr_replace($label, \"title=Stack level $j.&\", 2, 0);\n                }\n                $f = $frames[$i - 1];\n                if ($trace->keepArgs && !empty($f['args']) && $frame instanceof EnumStub) {\n                    $frame->value['arguments'] = new ArgsStub($f['args'], $f['function'] ?? null, $f['class'] ?? null);\n                }\n            } elseif ('???' !== $lastCall) {\n                $label = new ClassStub($lastCall);\n                if (isset($label->attr['ellipsis'])) {\n                    $label->attr['ellipsis'] += 2;\n                    $label = substr_replace($prefix, \"ellipsis-type=class&ellipsis={$label->attr['ellipsis']}&ellipsis-tail=1&title=Stack level $j.\", 2, 0).$label->value.'()';\n                } else {\n                    $label = substr_replace($prefix, \"title=Stack level $j.\", 2, 0).$label->value.'()';\n                }\n            } else {\n                $label = substr_replace($prefix, \"title=Stack level $j.\", 2, 0).$lastCall;\n            }\n            $a[substr_replace($label, \\sprintf('separator=%s&', $frame instanceof EnumStub ? ' ' : ':'), 2, 0)] = $frame;\n\n            $lastCall = $call;\n        }\n        if (null !== $trace->sliceLength) {\n            $a = \\array_slice($a, 0, $trace->sliceLength, true);\n        }\n\n        return $a;\n    }\n\n    public static function castFrameStub(FrameStub $frame, array $a, Stub $stub, bool $isNested): array\n    {\n        if (!$isNested) {\n            return $a;\n        }\n        $f = $frame->value;\n        $prefix = Caster::PREFIX_VIRTUAL;\n\n        if (isset($f['file'], $f['line'])) {\n            $cacheKey = $f;\n            unset($cacheKey['object'], $cacheKey['args']);\n            $cacheKey[] = self::$srcContext;\n            $cacheKey = implode('-', $cacheKey);\n\n            if (isset(self::$framesCache[$cacheKey])) {\n                $a[$prefix.'src'] = self::$framesCache[$cacheKey];\n            } else {\n                if (preg_match('/\\((\\d+)\\)(?:\\([\\da-f]{32}\\))? : (?:eval\\(\\)\\'d code|runtime-created function)$/', $f['file'], $match)) {\n                    $f['file'] = substr($f['file'], 0, -\\strlen($match[0]));\n                    $f['line'] = (int) $match[1];\n                }\n                $src = $f['line'];\n                $srcKey = $f['file'];\n                $ellipsis = new LinkStub($srcKey, 0);\n                $srcAttr = 'collapse='.(int) $ellipsis->inVendor;\n                $ellipsisTail = $ellipsis->attr['ellipsis-tail'] ?? 0;\n                $ellipsis = $ellipsis->attr['ellipsis'] ?? 0;\n\n                if (is_file($f['file']) && 0 <= self::$srcContext) {\n                    if (!empty($f['class']) && is_subclass_of($f['class'], 'Twig\\Template')) {\n                        $template = null;\n                        if (isset($f['object'])) {\n                            $template = $f['object'];\n                        } elseif ((new \\ReflectionClass($f['class']))->isInstantiable()) {\n                            $template = unserialize(\\sprintf('O:%d:\"%s\":0:{}', \\strlen($f['class']), $f['class']));\n                        }\n                        if (null !== $template) {\n                            $ellipsis = 0;\n                            $templateSrc = method_exists($template, 'getSourceContext') ? $template->getSourceContext()->getCode() : (method_exists($template, 'getSource') ? $template->getSource() : '');\n                            $templateInfo = $template->getDebugInfo();\n                            if (isset($templateInfo[$f['line']])) {\n                                if (!method_exists($template, 'getSourceContext') || !is_file($templatePath = $template->getSourceContext()->getPath())) {\n                                    $templatePath = null;\n                                }\n                                if ($templateSrc) {\n                                    $src = self::extractSource($templateSrc, $templateInfo[$f['line']], self::$srcContext, 'twig', $templatePath, $f);\n                                    $srcKey = ($templatePath ?: $template->getTemplateName()).':'.$templateInfo[$f['line']];\n                                }\n                            }\n                        }\n                    }\n                    if ($srcKey == $f['file']) {\n                        $src = self::extractSource(file_get_contents($f['file']), $f['line'], self::$srcContext, 'php', $f['file'], $f);\n                        $srcKey .= ':'.$f['line'];\n                        if ($ellipsis) {\n                            $ellipsis += 1 + \\strlen($f['line']);\n                        }\n                    }\n                    $srcAttr .= \\sprintf('&separator= &file=%s&line=%d', rawurlencode($f['file']), $f['line']);\n                } else {\n                    $srcAttr .= '&separator=:';\n                }\n                $srcAttr .= $ellipsis ? '&ellipsis-type=path&ellipsis='.$ellipsis.'&ellipsis-tail='.$ellipsisTail : '';\n                self::$framesCache[$cacheKey] = $a[$prefix.'src'] = new EnumStub([\"\\0~$srcAttr\\0$srcKey\" => $src]);\n            }\n        }\n\n        unset($a[$prefix.'args'], $a[$prefix.'line'], $a[$prefix.'file']);\n        if ($frame->inTraceStub) {\n            unset($a[$prefix.'class'], $a[$prefix.'type'], $a[$prefix.'function']);\n        }\n        foreach ($a as $k => $v) {\n            if (!$v) {\n                unset($a[$k]);\n            }\n        }\n        if ($frame->keepArgs && !empty($f['args'])) {\n            $a[$prefix.'arguments'] = new ArgsStub($f['args'], $f['function'], $f['class']);\n        }\n\n        return $a;\n    }\n\n    public static function castFlattenException(FlattenException $e, array $a, Stub $stub, bool $isNested): array\n    {\n        if ($isNested) {\n            $k = \\sprintf(Caster::PATTERN_PRIVATE, FlattenException::class, 'traceAsString');\n            $a[$k] = new CutStub($a[$k]);\n        }\n\n        return $a;\n    }\n\n    private static function filterExceptionArray(string $xClass, array $a, string $xPrefix, int $filter): array\n    {\n        if (isset($a[$xPrefix.'trace'])) {\n            $trace = $a[$xPrefix.'trace'];\n            unset($a[$xPrefix.'trace']); // Ensures the trace is always last\n        } else {\n            $trace = [];\n        }\n\n        if (!($filter & Caster::EXCLUDE_VERBOSE) && $trace) {\n            if (isset($a[Caster::PREFIX_PROTECTED.'file'], $a[Caster::PREFIX_PROTECTED.'line'])) {\n                self::traceUnshift($trace, $xClass, $a[Caster::PREFIX_PROTECTED.'file'], $a[Caster::PREFIX_PROTECTED.'line']);\n            }\n            $a[Caster::PREFIX_VIRTUAL.'trace'] = new TraceStub($trace, self::$traceArgs);\n        }\n        if (empty($a[$xPrefix.'previous'])) {\n            unset($a[$xPrefix.'previous']);\n        }\n        unset($a[$xPrefix.'string'], $a[Caster::PREFIX_DYNAMIC.'xdebug_message']);\n\n        if (isset($a[Caster::PREFIX_PROTECTED.'message']) && str_contains($a[Caster::PREFIX_PROTECTED.'message'], \"@anonymous\\0\")) {\n            $a[Caster::PREFIX_PROTECTED.'message'] = preg_replace_callback('/[a-zA-Z_\\x7f-\\xff][\\\\\\\\a-zA-Z0-9_\\x7f-\\xff]*+@anonymous\\x00.*?\\.php(?:0x?|:[0-9]++\\$)?[0-9a-fA-F]++/', static fn ($m) => class_exists($m[0], false) ? (get_parent_class($m[0]) ?: key(class_implements($m[0])) ?: 'class').'@anonymous' : $m[0], $a[Caster::PREFIX_PROTECTED.'message']);\n        }\n\n        if (isset($a[Caster::PREFIX_PROTECTED.'file'], $a[Caster::PREFIX_PROTECTED.'line'])) {\n            $a[Caster::PREFIX_PROTECTED.'file'] = new LinkStub($a[Caster::PREFIX_PROTECTED.'file'], $a[Caster::PREFIX_PROTECTED.'line']);\n        }\n\n        return $a;\n    }\n\n    private static function traceUnshift(array &$trace, ?string $class, string $file, int $line): void\n    {\n        if (isset($trace[0]['file'], $trace[0]['line']) && $trace[0]['file'] === $file && $trace[0]['line'] === $line) {\n            return;\n        }\n        array_unshift($trace, [\n            'function' => $class ? 'new '.$class : null,\n            'file' => $file,\n            'line' => $line,\n        ]);\n    }\n\n    private static function extractSource(string $srcLines, int $line, int $srcContext, string $lang, ?string $file, array $frame): EnumStub\n    {\n        $srcLines = explode(\"\\n\", $srcLines);\n        $src = [];\n\n        for ($i = $line - 1 - $srcContext; $i <= $line - 1 + $srcContext; ++$i) {\n            $src[] = ($srcLines[$i] ?? '').\"\\n\";\n        }\n\n        if ($frame['function'] ?? false) {\n            $stub = new CutStub(new \\stdClass());\n            $stub->class = (isset($frame['class']) ? $frame['class'].$frame['type'] : '').$frame['function'];\n            $stub->type = Stub::TYPE_OBJECT;\n            $stub->attr['cut_hash'] = true;\n            $stub->attr['file'] = $frame['file'];\n            $stub->attr['line'] = $frame['line'];\n\n            try {\n                $caller = isset($frame['class']) ? new \\ReflectionMethod($frame['class'], $frame['function']) : new \\ReflectionFunction($frame['function']);\n                $stub->class .= ReflectionCaster::getSignature(ReflectionCaster::castFunctionAbstract($caller, [], $stub, true, Caster::EXCLUDE_VERBOSE));\n\n                if ($f = $caller->getFileName()) {\n                    $stub->attr['file'] = $f;\n                    $stub->attr['line'] = $caller->getStartLine();\n                }\n            } catch (\\ReflectionException) {\n                // ignore fake class/function\n            }\n\n            $srcLines = [\"\\0~separator=\\0\" => $stub];\n        } else {\n            $stub = null;\n            $srcLines = [];\n        }\n\n        $ltrim = 0;\n        do {\n            $pad = null;\n            for ($i = $srcContext << 1; $i >= 0; --$i) {\n                if (isset($src[$i][$ltrim]) && \"\\r\" !== ($c = $src[$i][$ltrim]) && \"\\n\" !== $c) {\n                    $pad ??= $c;\n                    if ((' ' !== $c && \"\\t\" !== $c) || $pad !== $c) {\n                        break;\n                    }\n                }\n            }\n            ++$ltrim;\n        } while (0 > $i && null !== $pad);\n\n        --$ltrim;\n\n        foreach ($src as $i => $c) {\n            if ($ltrim) {\n                $c = isset($c[$ltrim]) && \"\\r\" !== $c[$ltrim] ? substr($c, $ltrim) : ltrim($c, \" \\t\");\n            }\n            $c = substr($c, 0, -1);\n            if ($i !== $srcContext) {\n                $c = new ConstStub('default', $c);\n            } else {\n                $c = new ConstStub($c, $stub ? 'in '.$stub->class : '');\n                if (null !== $file) {\n                    $c->attr['file'] = $file;\n                    $c->attr['line'] = $line;\n                }\n            }\n            $c->attr['lang'] = $lang;\n            $srcLines[\\sprintf(\"\\0~separator=› &%d\\0\", $i + $line - $srcContext)] = $c;\n        }\n\n        return new EnumStub($srcLines);\n    }\n}\n"
  },
  {
    "path": "Caster/FFICaster.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Caster;\n\nuse FFI\\CData;\nuse FFI\\CType;\nuse Symfony\\Component\\VarDumper\\Cloner\\Stub;\n\n/**\n * Casts FFI extension classes to array representation.\n *\n * @author Nesmeyanov Kirill <nesk@xakep.ru>\n */\nfinal class FFICaster\n{\n    /**\n     * In case of \"char*\" contains a string, the length of which depends on\n     * some other parameter, then during the generation of the string it is\n     * possible to go beyond the allowable memory area.\n     *\n     * This restriction serves to ensure that processing does not take\n     * up the entire allowable PHP memory limit.\n     */\n    private const MAX_STRING_LENGTH = 255;\n\n    public static function castCTypeOrCData(CData|CType $data, array $args, Stub $stub): array\n    {\n        if ($data instanceof CType) {\n            $type = $data;\n            $data = null;\n        } else {\n            $type = \\FFI::typeof($data);\n        }\n\n        $stub->class = \\sprintf('%s<%s> size %d align %d', ($data ?? $type)::class, $type->getName(), $type->getSize(), $type->getAlignment());\n\n        return match ($type->getKind()) {\n            CType::TYPE_FLOAT,\n            CType::TYPE_DOUBLE,\n            \\defined('\\FFI\\CType::TYPE_LONGDOUBLE') ? CType::TYPE_LONGDOUBLE : -1,\n            CType::TYPE_UINT8,\n            CType::TYPE_SINT8,\n            CType::TYPE_UINT16,\n            CType::TYPE_SINT16,\n            CType::TYPE_UINT32,\n            CType::TYPE_SINT32,\n            CType::TYPE_UINT64,\n            CType::TYPE_SINT64,\n            CType::TYPE_BOOL,\n            CType::TYPE_CHAR,\n            CType::TYPE_ENUM => null !== $data ? [Caster::PREFIX_VIRTUAL.'cdata' => $data->cdata] : [],\n            CType::TYPE_POINTER => self::castFFIPointer($stub, $type, $data),\n            CType::TYPE_STRUCT => self::castFFIStructLike($type, $data),\n            CType::TYPE_FUNC => self::castFFIFunction($stub, $type),\n            default => $args,\n        };\n    }\n\n    private static function castFFIFunction(Stub $stub, CType $type): array\n    {\n        $arguments = [];\n\n        for ($i = 0, $count = $type->getFuncParameterCount(); $i < $count; ++$i) {\n            $param = $type->getFuncParameterType($i);\n\n            $arguments[] = $param->getName();\n        }\n\n        $abi = match ($type->getFuncABI()) {\n            CType::ABI_DEFAULT,\n            CType::ABI_CDECL => '[cdecl]',\n            CType::ABI_FASTCALL => '[fastcall]',\n            CType::ABI_THISCALL => '[thiscall]',\n            CType::ABI_STDCALL => '[stdcall]',\n            CType::ABI_PASCAL => '[pascal]',\n            CType::ABI_REGISTER => '[register]',\n            CType::ABI_MS => '[ms]',\n            CType::ABI_SYSV => '[sysv]',\n            CType::ABI_VECTORCALL => '[vectorcall]',\n            default => '[unknown abi]',\n        };\n\n        $returnType = $type->getFuncReturnType();\n\n        $stub->class = $abi.' callable('.implode(', ', $arguments).'): '\n            .$returnType->getName();\n\n        return [Caster::PREFIX_VIRTUAL.'returnType' => $returnType];\n    }\n\n    private static function castFFIPointer(Stub $stub, CType $type, ?CData $data = null): array\n    {\n        $ptr = $type->getPointerType();\n\n        if (null === $data) {\n            return [Caster::PREFIX_VIRTUAL.'0' => $ptr];\n        }\n\n        return match ($ptr->getKind()) {\n            CType::TYPE_CHAR => [Caster::PREFIX_VIRTUAL.'cdata' => self::castFFIStringValue($data)],\n            CType::TYPE_FUNC => self::castFFIFunction($stub, $ptr),\n            default => [Caster::PREFIX_VIRTUAL.'cdata' => $data[0]],\n        };\n    }\n\n    private static function castFFIStringValue(CData $data): string|CutStub\n    {\n        $result = [];\n        $ffi = \\FFI::cdef(<<<C\n                size_t zend_get_page_size(void);\n            C);\n\n        $pageSize = $ffi->zend_get_page_size();\n\n        // get cdata address\n        $start = $ffi->cast('uintptr_t', $ffi->cast('char*', $data))->cdata;\n        // accessing memory in the same page as $start is safe\n        $max = min(self::MAX_STRING_LENGTH, ($start | ($pageSize - 1)) - $start);\n\n        for ($i = 0; $i < $max; ++$i) {\n            $result[$i] = $data[$i];\n\n            if (\"\\0\" === $data[$i]) {\n                return implode('', $result);\n            }\n        }\n\n        $string = implode('', $result);\n        $stub = new CutStub($string);\n        $stub->cut = -1;\n        $stub->value = $string;\n\n        return $stub;\n    }\n\n    private static function castFFIStructLike(CType $type, ?CData $data = null): array\n    {\n        $isUnion = ($type->getAttributes() & CType::ATTR_UNION) === CType::ATTR_UNION;\n\n        $result = [];\n\n        foreach ($type->getStructFieldNames() as $name) {\n            $field = $type->getStructFieldType($name);\n\n            // Retrieving the value of a field from a union containing\n            // a pointer is not a safe operation, because may contain\n            // incorrect data.\n            $isUnsafe = $isUnion && CType::TYPE_POINTER === $field->getKind();\n\n            if ($isUnsafe) {\n                $result[Caster::PREFIX_VIRTUAL.$name.'?'] = $field;\n            } elseif (null === $data) {\n                $result[Caster::PREFIX_VIRTUAL.$name] = $field;\n            } else {\n                $fieldName = $data->{$name} instanceof CData ? '' : $field->getName().' ';\n                $result[Caster::PREFIX_VIRTUAL.$fieldName.$name] = $data->{$name};\n            }\n        }\n\n        return $result;\n    }\n}\n"
  },
  {
    "path": "Caster/FiberCaster.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Caster;\n\nuse Symfony\\Component\\VarDumper\\Cloner\\Stub;\n\n/**\n * Casts Fiber related classes to array representation.\n *\n * @author Grégoire Pineau <lyrixx@lyrixx.info>\n */\nfinal class FiberCaster\n{\n    public static function castFiber(\\Fiber $fiber, array $a, Stub $stub, bool $isNested, int $filter = 0): array\n    {\n        $prefix = Caster::PREFIX_VIRTUAL;\n\n        if ($fiber->isTerminated()) {\n            $status = 'terminated';\n        } elseif ($fiber->isRunning()) {\n            $status = 'running';\n        } elseif ($fiber->isSuspended()) {\n            $status = 'suspended';\n        } elseif ($fiber->isStarted()) {\n            $status = 'started';\n        } else {\n            $status = 'not started';\n        }\n\n        $a[$prefix.'status'] = $status;\n\n        return $a;\n    }\n}\n"
  },
  {
    "path": "Caster/FrameStub.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Caster;\n\n/**\n * Represents a single backtrace frame as returned by debug_backtrace() or Exception->getTrace().\n *\n * @author Nicolas Grekas <p@tchwork.com>\n */\nclass FrameStub extends EnumStub\n{\n    public function __construct(\n        array $frame,\n        public bool $keepArgs = true,\n        public bool $inTraceStub = false,\n    ) {\n        parent::__construct($frame);\n    }\n}\n"
  },
  {
    "path": "Caster/GdCaster.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Caster;\n\nuse Symfony\\Component\\VarDumper\\Cloner\\Stub;\n\n/**\n * @author Nicolas Grekas <p@tchwork.com>\n *\n * @internal\n */\nfinal class GdCaster\n{\n    public static function castGd(\\GdImage $gd, array $a, Stub $stub, bool $isNested): array\n    {\n        $a[Caster::PREFIX_VIRTUAL.'size'] = imagesx($gd).'x'.imagesy($gd);\n        $a[Caster::PREFIX_VIRTUAL.'trueColor'] = imageistruecolor($gd);\n\n        return $a;\n    }\n}\n"
  },
  {
    "path": "Caster/GmpCaster.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Caster;\n\nuse Symfony\\Component\\VarDumper\\Cloner\\Stub;\n\n/**\n * Casts GMP objects to array representation.\n *\n * @author Hamza Amrouche <hamza.simperfit@gmail.com>\n * @author Nicolas Grekas <p@tchwork.com>\n *\n * @final\n *\n * @internal\n */\nclass GmpCaster\n{\n    public static function castGmp(\\GMP $gmp, array $a, Stub $stub, bool $isNested, int $filter): array\n    {\n        $a[Caster::PREFIX_VIRTUAL.'value'] = new ConstStub(gmp_strval($gmp), gmp_strval($gmp));\n\n        return $a;\n    }\n}\n"
  },
  {
    "path": "Caster/ImagineCaster.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Caster;\n\nuse Imagine\\Image\\ImageInterface;\nuse Symfony\\Component\\VarDumper\\Cloner\\Stub;\n\n/**\n * @author Grégoire Pineau <lyrixx@lyrixx.info>\n *\n * @internal\n */\nfinal class ImagineCaster\n{\n    public static function castImage(ImageInterface $c, array $a, Stub $stub, bool $isNested): array\n    {\n        $imgData = $c->get('png');\n        if (\\strlen($imgData) > 1 * 1000 * 1000) {\n            $a += [\n                Caster::PREFIX_VIRTUAL.'image' => new ConstStub($c->getSize()),\n            ];\n        } else {\n            $a += [\n                Caster::PREFIX_VIRTUAL.'image' => new ImgStub($imgData, 'image/png', $c->getSize()),\n            ];\n        }\n\n        return $a;\n    }\n}\n"
  },
  {
    "path": "Caster/ImgStub.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Caster;\n\n/**\n * @author Grégoire Pineau <lyrixx@lyrixx.info>\n */\nclass ImgStub extends ConstStub\n{\n    public function __construct(string $data, string $contentType, string $size = '')\n    {\n        $this->value = '';\n        $this->attr['img-data'] = $data;\n        $this->attr['img-size'] = $size;\n        $this->attr['content-type'] = $contentType;\n    }\n}\n"
  },
  {
    "path": "Caster/IntlCaster.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Caster;\n\nuse Symfony\\Component\\VarDumper\\Cloner\\Stub;\n\n/**\n * @author Nicolas Grekas <p@tchwork.com>\n * @author Jan Schädlich <jan.schaedlich@sensiolabs.de>\n *\n * @final\n *\n * @internal\n */\nclass IntlCaster\n{\n    public static function castMessageFormatter(\\MessageFormatter $c, array $a, Stub $stub, bool $isNested): array\n    {\n        $a += [\n            Caster::PREFIX_VIRTUAL.'locale' => $c->getLocale(),\n            Caster::PREFIX_VIRTUAL.'pattern' => $c->getPattern(),\n        ];\n\n        return self::castError($c, $a);\n    }\n\n    public static function castNumberFormatter(\\NumberFormatter $c, array $a, Stub $stub, bool $isNested, int $filter = 0): array\n    {\n        $a += [\n            Caster::PREFIX_VIRTUAL.'locale' => $c->getLocale(),\n            Caster::PREFIX_VIRTUAL.'pattern' => $c->getPattern(),\n        ];\n\n        if ($filter & Caster::EXCLUDE_VERBOSE) {\n            $stub->cut += 3;\n\n            return self::castError($c, $a);\n        }\n\n        $a += [\n            Caster::PREFIX_VIRTUAL.'attributes' => new EnumStub(\n                [\n                    'PARSE_INT_ONLY' => $c->getAttribute(\\NumberFormatter::PARSE_INT_ONLY),\n                    'GROUPING_USED' => $c->getAttribute(\\NumberFormatter::GROUPING_USED),\n                    'DECIMAL_ALWAYS_SHOWN' => $c->getAttribute(\\NumberFormatter::DECIMAL_ALWAYS_SHOWN),\n                    'MAX_INTEGER_DIGITS' => $c->getAttribute(\\NumberFormatter::MAX_INTEGER_DIGITS),\n                    'MIN_INTEGER_DIGITS' => $c->getAttribute(\\NumberFormatter::MIN_INTEGER_DIGITS),\n                    'INTEGER_DIGITS' => $c->getAttribute(\\NumberFormatter::INTEGER_DIGITS),\n                    'MAX_FRACTION_DIGITS' => $c->getAttribute(\\NumberFormatter::MAX_FRACTION_DIGITS),\n                    'MIN_FRACTION_DIGITS' => $c->getAttribute(\\NumberFormatter::MIN_FRACTION_DIGITS),\n                    'FRACTION_DIGITS' => $c->getAttribute(\\NumberFormatter::FRACTION_DIGITS),\n                    'MULTIPLIER' => $c->getAttribute(\\NumberFormatter::MULTIPLIER),\n                    'GROUPING_SIZE' => $c->getAttribute(\\NumberFormatter::GROUPING_SIZE),\n                    'ROUNDING_MODE' => $c->getAttribute(\\NumberFormatter::ROUNDING_MODE),\n                    'ROUNDING_INCREMENT' => $c->getAttribute(\\NumberFormatter::ROUNDING_INCREMENT),\n                    'FORMAT_WIDTH' => $c->getAttribute(\\NumberFormatter::FORMAT_WIDTH),\n                    'PADDING_POSITION' => $c->getAttribute(\\NumberFormatter::PADDING_POSITION),\n                    'SECONDARY_GROUPING_SIZE' => $c->getAttribute(\\NumberFormatter::SECONDARY_GROUPING_SIZE),\n                    'SIGNIFICANT_DIGITS_USED' => $c->getAttribute(\\NumberFormatter::SIGNIFICANT_DIGITS_USED),\n                    'MIN_SIGNIFICANT_DIGITS' => $c->getAttribute(\\NumberFormatter::MIN_SIGNIFICANT_DIGITS),\n                    'MAX_SIGNIFICANT_DIGITS' => $c->getAttribute(\\NumberFormatter::MAX_SIGNIFICANT_DIGITS),\n                    'LENIENT_PARSE' => $c->getAttribute(\\NumberFormatter::LENIENT_PARSE),\n                ]\n            ),\n            Caster::PREFIX_VIRTUAL.'text_attributes' => new EnumStub(\n                [\n                    'POSITIVE_PREFIX' => $c->getTextAttribute(\\NumberFormatter::POSITIVE_PREFIX),\n                    'POSITIVE_SUFFIX' => $c->getTextAttribute(\\NumberFormatter::POSITIVE_SUFFIX),\n                    'NEGATIVE_PREFIX' => $c->getTextAttribute(\\NumberFormatter::NEGATIVE_PREFIX),\n                    'NEGATIVE_SUFFIX' => $c->getTextAttribute(\\NumberFormatter::NEGATIVE_SUFFIX),\n                    'PADDING_CHARACTER' => $c->getTextAttribute(\\NumberFormatter::PADDING_CHARACTER),\n                    'CURRENCY_CODE' => $c->getTextAttribute(\\NumberFormatter::CURRENCY_CODE),\n                    'DEFAULT_RULESET' => $c->getTextAttribute(\\NumberFormatter::DEFAULT_RULESET),\n                    'PUBLIC_RULESETS' => $c->getTextAttribute(\\NumberFormatter::PUBLIC_RULESETS),\n                ]\n            ),\n            Caster::PREFIX_VIRTUAL.'symbols' => new EnumStub(\n                [\n                    'DECIMAL_SEPARATOR_SYMBOL' => $c->getSymbol(\\NumberFormatter::DECIMAL_SEPARATOR_SYMBOL),\n                    'GROUPING_SEPARATOR_SYMBOL' => $c->getSymbol(\\NumberFormatter::GROUPING_SEPARATOR_SYMBOL),\n                    'PATTERN_SEPARATOR_SYMBOL' => $c->getSymbol(\\NumberFormatter::PATTERN_SEPARATOR_SYMBOL),\n                    'PERCENT_SYMBOL' => $c->getSymbol(\\NumberFormatter::PERCENT_SYMBOL),\n                    'ZERO_DIGIT_SYMBOL' => $c->getSymbol(\\NumberFormatter::ZERO_DIGIT_SYMBOL),\n                    'DIGIT_SYMBOL' => $c->getSymbol(\\NumberFormatter::DIGIT_SYMBOL),\n                    'MINUS_SIGN_SYMBOL' => $c->getSymbol(\\NumberFormatter::MINUS_SIGN_SYMBOL),\n                    'PLUS_SIGN_SYMBOL' => $c->getSymbol(\\NumberFormatter::PLUS_SIGN_SYMBOL),\n                    'CURRENCY_SYMBOL' => $c->getSymbol(\\NumberFormatter::CURRENCY_SYMBOL),\n                    'INTL_CURRENCY_SYMBOL' => $c->getSymbol(\\NumberFormatter::INTL_CURRENCY_SYMBOL),\n                    'MONETARY_SEPARATOR_SYMBOL' => $c->getSymbol(\\NumberFormatter::MONETARY_SEPARATOR_SYMBOL),\n                    'EXPONENTIAL_SYMBOL' => $c->getSymbol(\\NumberFormatter::EXPONENTIAL_SYMBOL),\n                    'PERMILL_SYMBOL' => $c->getSymbol(\\NumberFormatter::PERMILL_SYMBOL),\n                    'PAD_ESCAPE_SYMBOL' => $c->getSymbol(\\NumberFormatter::PAD_ESCAPE_SYMBOL),\n                    'INFINITY_SYMBOL' => $c->getSymbol(\\NumberFormatter::INFINITY_SYMBOL),\n                    'NAN_SYMBOL' => $c->getSymbol(\\NumberFormatter::NAN_SYMBOL),\n                    'SIGNIFICANT_DIGIT_SYMBOL' => $c->getSymbol(\\NumberFormatter::SIGNIFICANT_DIGIT_SYMBOL),\n                    'MONETARY_GROUPING_SEPARATOR_SYMBOL' => $c->getSymbol(\\NumberFormatter::MONETARY_GROUPING_SEPARATOR_SYMBOL),\n                ]\n            ),\n        ];\n\n        return self::castError($c, $a);\n    }\n\n    public static function castIntlTimeZone(\\IntlTimeZone $c, array $a, Stub $stub, bool $isNested): array\n    {\n        $a += [\n            Caster::PREFIX_VIRTUAL.'display_name' => $c->getDisplayName(),\n            Caster::PREFIX_VIRTUAL.'id' => $c->getID(),\n            Caster::PREFIX_VIRTUAL.'raw_offset' => $c->getRawOffset(),\n        ];\n\n        if ($c->useDaylightTime()) {\n            $a += [\n                Caster::PREFIX_VIRTUAL.'dst_savings' => $c->getDSTSavings(),\n            ];\n        }\n\n        return self::castError($c, $a);\n    }\n\n    public static function castIntlCalendar(\\IntlCalendar $c, array $a, Stub $stub, bool $isNested, int $filter = 0): array\n    {\n        $a += [\n            Caster::PREFIX_VIRTUAL.'type' => $c->getType(),\n            Caster::PREFIX_VIRTUAL.'first_day_of_week' => $c->getFirstDayOfWeek(),\n            Caster::PREFIX_VIRTUAL.'minimal_days_in_first_week' => $c->getMinimalDaysInFirstWeek(),\n            Caster::PREFIX_VIRTUAL.'repeated_wall_time_option' => $c->getRepeatedWallTimeOption(),\n            Caster::PREFIX_VIRTUAL.'skipped_wall_time_option' => $c->getSkippedWallTimeOption(),\n            Caster::PREFIX_VIRTUAL.'time' => $c->getTime(),\n            Caster::PREFIX_VIRTUAL.'in_daylight_time' => $c->inDaylightTime(),\n            Caster::PREFIX_VIRTUAL.'is_lenient' => $c->isLenient(),\n            Caster::PREFIX_VIRTUAL.'time_zone' => ($filter & Caster::EXCLUDE_VERBOSE) ? new CutStub($c->getTimeZone()) : $c->getTimeZone(),\n        ];\n\n        return self::castError($c, $a);\n    }\n\n    public static function castIntlDateFormatter(\\IntlDateFormatter $c, array $a, Stub $stub, bool $isNested, int $filter = 0): array\n    {\n        $a += [\n            Caster::PREFIX_VIRTUAL.'locale' => $c->getLocale(),\n            Caster::PREFIX_VIRTUAL.'pattern' => $c->getPattern(),\n            Caster::PREFIX_VIRTUAL.'calendar' => $c->getCalendar(),\n            Caster::PREFIX_VIRTUAL.'time_zone_id' => $c->getTimeZoneId(),\n            Caster::PREFIX_VIRTUAL.'time_type' => $c->getTimeType(),\n            Caster::PREFIX_VIRTUAL.'date_type' => $c->getDateType(),\n            Caster::PREFIX_VIRTUAL.'calendar_object' => ($filter & Caster::EXCLUDE_VERBOSE) ? new CutStub($c->getCalendarObject()) : $c->getCalendarObject(),\n            Caster::PREFIX_VIRTUAL.'time_zone' => ($filter & Caster::EXCLUDE_VERBOSE) ? new CutStub($c->getTimeZone()) : $c->getTimeZone(),\n        ];\n\n        return self::castError($c, $a);\n    }\n\n    private static function castError(object $c, array $a): array\n    {\n        if ($errorCode = $c->getErrorCode()) {\n            $a += [\n                Caster::PREFIX_VIRTUAL.'error_code' => $errorCode,\n                Caster::PREFIX_VIRTUAL.'error_message' => $c->getErrorMessage(),\n            ];\n        }\n\n        return $a;\n    }\n}\n"
  },
  {
    "path": "Caster/LinkStub.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Caster;\n\n/**\n * Represents a file or a URL.\n *\n * @author Nicolas Grekas <p@tchwork.com>\n */\nclass LinkStub extends ConstStub\n{\n    public bool $inVendor = false;\n\n    private static array $vendorRoots;\n    private static array $composerRoots = [];\n\n    public function __construct(string $label, int $line = 0, ?string $href = null)\n    {\n        $this->value = $label;\n\n        if (!\\is_string($href ??= $label)) {\n            return;\n        }\n        if (str_starts_with($href, 'file://')) {\n            if ($href === $label) {\n                $label = substr($label, 7);\n            }\n            $href = substr($href, 7);\n        } elseif (str_contains($href, '://')) {\n            $this->attr['href'] = $href;\n\n            return;\n        }\n        if (!is_file($href)) {\n            return;\n        }\n        if ($line) {\n            $this->attr['line'] = $line;\n        }\n        if ($label !== $this->attr['file'] = realpath($href) ?: $href) {\n            return;\n        }\n        if ($composerRoot = $this->getComposerRoot($href, $this->inVendor)) {\n            $this->attr['ellipsis'] = \\strlen($href) - \\strlen($composerRoot) + 1;\n            $this->attr['ellipsis-type'] = 'path';\n            $this->attr['ellipsis-tail'] = 1 + ($this->inVendor ? 2 + \\strlen(implode('', \\array_slice(explode(\\DIRECTORY_SEPARATOR, substr($href, 1 - $this->attr['ellipsis'])), 0, 2))) : 0);\n        } elseif (3 < \\count($ellipsis = explode(\\DIRECTORY_SEPARATOR, $href))) {\n            $this->attr['ellipsis'] = 2 + \\strlen(implode('', \\array_slice($ellipsis, -2)));\n            $this->attr['ellipsis-type'] = 'path';\n            $this->attr['ellipsis-tail'] = 1;\n        }\n    }\n\n    private function getComposerRoot(string $file, bool &$inVendor): string|false\n    {\n        if (!isset(self::$vendorRoots)) {\n            self::$vendorRoots = [];\n\n            foreach (get_declared_classes() as $class) {\n                if ('C' === $class[0] && str_starts_with($class, 'ComposerAutoloaderInit')) {\n                    $r = new \\ReflectionClass($class);\n                    $v = \\dirname($r->getFileName(), 2);\n                    if (is_file($v.'/composer/installed.json')) {\n                        self::$vendorRoots[] = $v.\\DIRECTORY_SEPARATOR;\n                    }\n                }\n            }\n        }\n        $inVendor = false;\n\n        if (isset(self::$composerRoots[$dir = \\dirname($file)])) {\n            return self::$composerRoots[$dir];\n        }\n\n        foreach (self::$vendorRoots as $root) {\n            if ($inVendor = str_starts_with($file, $root)) {\n                return $root;\n            }\n        }\n\n        $parent = $dir;\n        while (!@is_file($parent.'/composer.json')) {\n            if (!@file_exists($parent)) {\n                // open_basedir restriction in effect\n                break;\n            }\n            if ($parent === \\dirname($parent)) {\n                return self::$composerRoots[$dir] = false;\n            }\n\n            $parent = \\dirname($parent);\n        }\n\n        return self::$composerRoots[$dir] = $parent.\\DIRECTORY_SEPARATOR;\n    }\n}\n"
  },
  {
    "path": "Caster/MemcachedCaster.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Caster;\n\nuse Symfony\\Component\\VarDumper\\Cloner\\Stub;\n\n/**\n * @author Jan Schädlich <jan.schaedlich@sensiolabs.de>\n *\n * @final\n *\n * @internal\n */\nclass MemcachedCaster\n{\n    private static array $optionConstants;\n    private static array $defaultOptions;\n\n    public static function castMemcached(\\Memcached $c, array $a, Stub $stub, bool $isNested): array\n    {\n        $a += [\n            Caster::PREFIX_VIRTUAL.'servers' => $c->getServerList(),\n            Caster::PREFIX_VIRTUAL.'options' => new EnumStub(\n                self::getNonDefaultOptions($c)\n            ),\n        ];\n\n        return $a;\n    }\n\n    private static function getNonDefaultOptions(\\Memcached $c): array\n    {\n        self::$defaultOptions ??= self::discoverDefaultOptions();\n        self::$optionConstants ??= self::getOptionConstants();\n\n        $nonDefaultOptions = [];\n        foreach (self::$optionConstants as $constantKey => $value) {\n            if (self::$defaultOptions[$constantKey] !== $option = $c->getOption($value)) {\n                $nonDefaultOptions[$constantKey] = $option;\n            }\n        }\n\n        return $nonDefaultOptions;\n    }\n\n    private static function discoverDefaultOptions(): array\n    {\n        $defaultMemcached = new \\Memcached();\n        $defaultMemcached->addServer('127.0.0.1', 11211);\n\n        $defaultOptions = [];\n        self::$optionConstants ??= self::getOptionConstants();\n\n        foreach (self::$optionConstants as $constantKey => $value) {\n            $defaultOptions[$constantKey] = $defaultMemcached->getOption($value);\n        }\n\n        return $defaultOptions;\n    }\n\n    private static function getOptionConstants(): array\n    {\n        $reflectedMemcached = new \\ReflectionClass(\\Memcached::class);\n\n        $optionConstants = [];\n        foreach ($reflectedMemcached->getConstants() as $constantKey => $value) {\n            if (str_starts_with($constantKey, 'OPT_')) {\n                $optionConstants[$constantKey] = $value;\n            }\n        }\n\n        return $optionConstants;\n    }\n}\n"
  },
  {
    "path": "Caster/MysqliCaster.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Caster;\n\nuse Symfony\\Component\\VarDumper\\Cloner\\Stub;\n\n/**\n * @author Nicolas Grekas <p@tchwork.com>\n *\n * @internal\n */\nfinal class MysqliCaster\n{\n    public static function castMysqliDriver(\\mysqli_driver $c, array $a, Stub $stub, bool $isNested): array\n    {\n        foreach ($a as $k => $v) {\n            if (isset($c->$k)) {\n                $a[$k] = $c->$k;\n            }\n        }\n\n        return $a;\n    }\n}\n"
  },
  {
    "path": "Caster/OpenSSLCaster.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Caster;\n\nuse Symfony\\Component\\VarDumper\\Cloner\\Stub;\n\n/**\n * @author Nicolas Grekas <p@tchwork.com>\n * @author Alexandre Daubois <alex.daubois@gmail.com>\n *\n * @internal\n */\nfinal class OpenSSLCaster\n{\n    public static function castOpensslX509(\\OpenSSLCertificate $h, array $a, Stub $stub, bool $isNested): array\n    {\n        $stub->cut = -1;\n        $info = openssl_x509_parse($h, false);\n\n        $pin = openssl_pkey_get_public($h);\n        $pin = openssl_pkey_get_details($pin)['key'];\n        $pin = \\array_slice(explode(\"\\n\", $pin), 1, -2);\n        $pin = base64_decode(implode('', $pin));\n        $pin = base64_encode(hash('sha256', $pin, true));\n\n        $a += [\n            Caster::PREFIX_VIRTUAL.'subject' => new EnumStub(array_intersect_key($info['subject'], ['organizationName' => true, 'commonName' => true])),\n            Caster::PREFIX_VIRTUAL.'issuer' => new EnumStub(array_intersect_key($info['issuer'], ['organizationName' => true, 'commonName' => true])),\n            Caster::PREFIX_VIRTUAL.'expiry' => new ConstStub(date(\\DateTimeInterface::ISO8601, $info['validTo_time_t']), $info['validTo_time_t']),\n            Caster::PREFIX_VIRTUAL.'fingerprint' => new EnumStub([\n                'md5' => new ConstStub(wordwrap(strtoupper(openssl_x509_fingerprint($h, 'md5')), 2, ':', true)),\n                'sha1' => new ConstStub(wordwrap(strtoupper(openssl_x509_fingerprint($h, 'sha1')), 2, ':', true)),\n                'sha256' => new ConstStub(wordwrap(strtoupper(openssl_x509_fingerprint($h, 'sha256')), 2, ':', true)),\n                'pin-sha256' => new ConstStub($pin),\n            ]),\n        ];\n\n        return $a;\n    }\n\n    public static function castOpensslAsymmetricKey(\\OpenSSLAsymmetricKey $key, array $a, Stub $stub, bool $isNested): array\n    {\n        foreach (openssl_pkey_get_details($key) as $k => $v) {\n            $a[Caster::PREFIX_VIRTUAL.$k] = $v;\n        }\n\n        unset($a[Caster::PREFIX_VIRTUAL.'rsa']); // binary data\n\n        return $a;\n    }\n\n    public static function castOpensslCsr(\\OpenSSLCertificateSigningRequest $csr, array $a, Stub $stub, bool $isNested): array\n    {\n        foreach (openssl_csr_get_subject($csr, false) as $k => $v) {\n            $a[Caster::PREFIX_VIRTUAL.$k] = $v;\n        }\n\n        return $a;\n    }\n}\n"
  },
  {
    "path": "Caster/PdoCaster.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Caster;\n\nuse Symfony\\Component\\VarDumper\\Cloner\\Stub;\n\n/**\n * Casts PDO related classes to array representation.\n *\n * @author Nicolas Grekas <p@tchwork.com>\n *\n * @final\n *\n * @internal\n */\nclass PdoCaster\n{\n    private const PDO_ATTRIBUTES = [\n        'CASE' => [\n            \\PDO::CASE_LOWER => 'LOWER',\n            \\PDO::CASE_NATURAL => 'NATURAL',\n            \\PDO::CASE_UPPER => 'UPPER',\n        ],\n        'ERRMODE' => [\n            \\PDO::ERRMODE_SILENT => 'SILENT',\n            \\PDO::ERRMODE_WARNING => 'WARNING',\n            \\PDO::ERRMODE_EXCEPTION => 'EXCEPTION',\n        ],\n        'TIMEOUT',\n        'PREFETCH',\n        'AUTOCOMMIT',\n        'PERSISTENT',\n        'DRIVER_NAME',\n        'SERVER_INFO',\n        'ORACLE_NULLS' => [\n            \\PDO::NULL_NATURAL => 'NATURAL',\n            \\PDO::NULL_EMPTY_STRING => 'EMPTY_STRING',\n            \\PDO::NULL_TO_STRING => 'TO_STRING',\n        ],\n        'CLIENT_VERSION',\n        'SERVER_VERSION',\n        'STATEMENT_CLASS',\n        'EMULATE_PREPARES',\n        'CONNECTION_STATUS',\n        'STRINGIFY_FETCHES',\n        'DEFAULT_FETCH_MODE' => [\n            \\PDO::FETCH_ASSOC => 'ASSOC',\n            \\PDO::FETCH_BOTH => 'BOTH',\n            \\PDO::FETCH_LAZY => 'LAZY',\n            \\PDO::FETCH_NUM => 'NUM',\n            \\PDO::FETCH_OBJ => 'OBJ',\n        ],\n    ];\n\n    public static function castPdo(\\PDO $c, array $a, Stub $stub, bool $isNested): array\n    {\n        $attr = [];\n        $errmode = $c->getAttribute(\\PDO::ATTR_ERRMODE);\n        $c->setAttribute(\\PDO::ATTR_ERRMODE, \\PDO::ERRMODE_EXCEPTION);\n\n        foreach (self::PDO_ATTRIBUTES as $k => $v) {\n            if (!isset($k[0])) {\n                $k = $v;\n                $v = [];\n            }\n\n            try {\n                $attr[$k] = 'ERRMODE' === $k ? $errmode : $c->getAttribute(\\constant('PDO::ATTR_'.$k));\n                if ($v && isset($v[$attr[$k]])) {\n                    $attr[$k] = new ConstStub($v[$attr[$k]], $attr[$k]);\n                }\n            } catch (\\Exception) {\n            }\n        }\n        if (isset($attr[$k = 'STATEMENT_CLASS'][1])) {\n            if ($attr[$k][1]) {\n                $attr[$k][1] = new ArgsStub($attr[$k][1], '__construct', $attr[$k][0]);\n            }\n            $attr[$k][0] = new ClassStub($attr[$k][0]);\n        }\n\n        $prefix = Caster::PREFIX_VIRTUAL;\n        $a += [\n            $prefix.'inTransaction' => method_exists($c, 'inTransaction'),\n            $prefix.'errorInfo' => $c->errorInfo(),\n            $prefix.'attributes' => new EnumStub($attr),\n        ];\n\n        if ($a[$prefix.'inTransaction']) {\n            $a[$prefix.'inTransaction'] = $c->inTransaction();\n        } else {\n            unset($a[$prefix.'inTransaction']);\n        }\n\n        if (!isset($a[$prefix.'errorInfo'][1], $a[$prefix.'errorInfo'][2])) {\n            unset($a[$prefix.'errorInfo']);\n        }\n\n        $c->setAttribute(\\PDO::ATTR_ERRMODE, $errmode);\n\n        return $a;\n    }\n\n    public static function castPdoStatement(\\PDOStatement $c, array $a, Stub $stub, bool $isNested): array\n    {\n        $prefix = Caster::PREFIX_VIRTUAL;\n        $a[$prefix.'errorInfo'] = $c->errorInfo();\n\n        if (!isset($a[$prefix.'errorInfo'][1], $a[$prefix.'errorInfo'][2])) {\n            unset($a[$prefix.'errorInfo']);\n        }\n\n        return $a;\n    }\n}\n"
  },
  {
    "path": "Caster/PgSqlCaster.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Caster;\n\nuse Symfony\\Component\\VarDumper\\Cloner\\Stub;\n\n/**\n * Casts pgsql resources to array representation.\n *\n * @author Nicolas Grekas <p@tchwork.com>\n *\n * @final\n *\n * @internal\n */\nclass PgSqlCaster\n{\n    private const PARAM_CODES = [\n        'server_encoding',\n        'client_encoding',\n        'is_superuser',\n        'session_authorization',\n        'DateStyle',\n        'TimeZone',\n        'IntervalStyle',\n        'integer_datetimes',\n        'application_name',\n        'standard_conforming_strings',\n    ];\n\n    private const TRANSACTION_STATUS = [\n        \\PGSQL_TRANSACTION_IDLE => 'PGSQL_TRANSACTION_IDLE',\n        \\PGSQL_TRANSACTION_ACTIVE => 'PGSQL_TRANSACTION_ACTIVE',\n        \\PGSQL_TRANSACTION_INTRANS => 'PGSQL_TRANSACTION_INTRANS',\n        \\PGSQL_TRANSACTION_INERROR => 'PGSQL_TRANSACTION_INERROR',\n        \\PGSQL_TRANSACTION_UNKNOWN => 'PGSQL_TRANSACTION_UNKNOWN',\n    ];\n\n    private const RESULT_STATUS = [\n        \\PGSQL_EMPTY_QUERY => 'PGSQL_EMPTY_QUERY',\n        \\PGSQL_COMMAND_OK => 'PGSQL_COMMAND_OK',\n        \\PGSQL_TUPLES_OK => 'PGSQL_TUPLES_OK',\n        \\PGSQL_COPY_OUT => 'PGSQL_COPY_OUT',\n        \\PGSQL_COPY_IN => 'PGSQL_COPY_IN',\n        \\PGSQL_BAD_RESPONSE => 'PGSQL_BAD_RESPONSE',\n        \\PGSQL_NONFATAL_ERROR => 'PGSQL_NONFATAL_ERROR',\n        \\PGSQL_FATAL_ERROR => 'PGSQL_FATAL_ERROR',\n    ];\n\n    private const DIAG_CODES = [\n        'severity' => \\PGSQL_DIAG_SEVERITY,\n        'sqlstate' => \\PGSQL_DIAG_SQLSTATE,\n        'message' => \\PGSQL_DIAG_MESSAGE_PRIMARY,\n        'detail' => \\PGSQL_DIAG_MESSAGE_DETAIL,\n        'hint' => \\PGSQL_DIAG_MESSAGE_HINT,\n        'statement position' => \\PGSQL_DIAG_STATEMENT_POSITION,\n        'internal position' => \\PGSQL_DIAG_INTERNAL_POSITION,\n        'internal query' => \\PGSQL_DIAG_INTERNAL_QUERY,\n        'context' => \\PGSQL_DIAG_CONTEXT,\n        'file' => \\PGSQL_DIAG_SOURCE_FILE,\n        'line' => \\PGSQL_DIAG_SOURCE_LINE,\n        'function' => \\PGSQL_DIAG_SOURCE_FUNCTION,\n    ];\n\n    public static function castLargeObject($lo, array $a, Stub $stub, bool $isNested): array\n    {\n        $a['seek position'] = pg_lo_tell($lo);\n\n        return $a;\n    }\n\n    public static function castLink($link, array $a, Stub $stub, bool $isNested): array\n    {\n        $a['status'] = pg_connection_status($link);\n        $a['status'] = new ConstStub(\\PGSQL_CONNECTION_OK === $a['status'] ? 'PGSQL_CONNECTION_OK' : 'PGSQL_CONNECTION_BAD', $a['status']);\n        $a['busy'] = pg_connection_busy($link);\n\n        $a['transaction'] = pg_transaction_status($link);\n        if (isset(self::TRANSACTION_STATUS[$a['transaction']])) {\n            $a['transaction'] = new ConstStub(self::TRANSACTION_STATUS[$a['transaction']], $a['transaction']);\n        }\n\n        $a['pid'] = pg_get_pid($link);\n        $a['last error'] = pg_last_error($link);\n        $a['last notice'] = pg_last_notice($link);\n        $a['host'] = pg_host($link);\n        $a['port'] = pg_port($link);\n        $a['dbname'] = pg_dbname($link);\n        $a['options'] = pg_options($link);\n        $a['version'] = pg_version($link);\n\n        foreach (self::PARAM_CODES as $v) {\n            if (false !== $s = pg_parameter_status($link, $v)) {\n                $a['param'][$v] = $s;\n            }\n        }\n\n        $a['param']['client_encoding'] = pg_client_encoding($link);\n        $a['param'] = new EnumStub($a['param']);\n\n        return $a;\n    }\n\n    public static function castResult($result, array $a, Stub $stub, bool $isNested): array\n    {\n        $a['num rows'] = pg_num_rows($result);\n        $a['status'] = pg_result_status($result);\n        if (isset(self::RESULT_STATUS[$a['status']])) {\n            $a['status'] = new ConstStub(self::RESULT_STATUS[$a['status']], $a['status']);\n        }\n        $a['command-completion tag'] = pg_result_status($result, \\PGSQL_STATUS_STRING);\n\n        if (-1 === $a['num rows']) {\n            foreach (self::DIAG_CODES as $k => $v) {\n                $a['error'][$k] = pg_result_error_field($result, $v);\n            }\n        }\n\n        $a['affected rows'] = pg_affected_rows($result);\n        $a['last OID'] = pg_last_oid($result);\n\n        $fields = pg_num_fields($result);\n\n        for ($i = 0; $i < $fields; ++$i) {\n            $field = [\n                'name' => pg_field_name($result, $i),\n                'table' => \\sprintf('%s (OID: %s)', pg_field_table($result, $i), pg_field_table($result, $i, true)),\n                'type' => \\sprintf('%s (OID: %s)', pg_field_type($result, $i), pg_field_type_oid($result, $i)),\n                'nullable' => (bool) pg_field_is_null($result, null, $i),\n                'storage' => pg_field_size($result, $i).' bytes',\n                'display' => pg_field_prtlen($result, null, $i).' chars',\n            ];\n            if (' (OID: )' === $field['table']) {\n                $field['table'] = null;\n            }\n            if ('-1 bytes' === $field['storage']) {\n                $field['storage'] = 'variable size';\n            } elseif ('1 bytes' === $field['storage']) {\n                $field['storage'] = '1 byte';\n            }\n            if ('1 chars' === $field['display']) {\n                $field['display'] = '1 char';\n            }\n            $a['fields'][] = new EnumStub($field);\n        }\n\n        return $a;\n    }\n}\n"
  },
  {
    "path": "Caster/ProxyManagerCaster.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Caster;\n\nuse ProxyManager\\Proxy\\ProxyInterface;\nuse Symfony\\Component\\VarDumper\\Cloner\\Stub;\n\n/**\n * @author Nicolas Grekas <p@tchwork.com>\n *\n * @final\n *\n * @internal\n */\nclass ProxyManagerCaster\n{\n    public static function castProxy(ProxyInterface $c, array $a, Stub $stub, bool $isNested): array\n    {\n        if ($parent = get_parent_class($c)) {\n            $stub->class .= ' - '.$parent;\n        }\n        $stub->class .= '@proxy';\n\n        return $a;\n    }\n}\n"
  },
  {
    "path": "Caster/RdKafkaCaster.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Caster;\n\nuse RdKafka\\Conf;\nuse RdKafka\\Exception as RdKafkaException;\nuse RdKafka\\KafkaConsumer;\nuse RdKafka\\Message;\nuse RdKafka\\Metadata\\Broker as BrokerMetadata;\nuse RdKafka\\Metadata\\Collection as CollectionMetadata;\nuse RdKafka\\Metadata\\Partition as PartitionMetadata;\nuse RdKafka\\Metadata\\Topic as TopicMetadata;\nuse RdKafka\\Topic;\nuse RdKafka\\TopicConf;\nuse RdKafka\\TopicPartition;\nuse Symfony\\Component\\VarDumper\\Cloner\\Stub;\n\n/**\n * Casts RdKafka related classes to array representation.\n *\n * @author Romain Neutron <imprec@gmail.com>\n *\n * @internal\n */\nclass RdKafkaCaster\n{\n    public static function castKafkaConsumer(KafkaConsumer $c, array $a, Stub $stub, bool $isNested): array\n    {\n        $prefix = Caster::PREFIX_VIRTUAL;\n\n        try {\n            $assignment = $c->getAssignment();\n        } catch (RdKafkaException) {\n            $assignment = [];\n        }\n\n        $a += [\n            $prefix.'subscription' => $c->getSubscription(),\n            $prefix.'assignment' => $assignment,\n        ];\n\n        $a += self::extractMetadata($c);\n\n        return $a;\n    }\n\n    public static function castTopic(Topic $c, array $a, Stub $stub, bool $isNested): array\n    {\n        $prefix = Caster::PREFIX_VIRTUAL;\n\n        $a += [\n            $prefix.'name' => $c->getName(),\n        ];\n\n        return $a;\n    }\n\n    public static function castTopicPartition(TopicPartition $c, array $a): array\n    {\n        $prefix = Caster::PREFIX_VIRTUAL;\n\n        $a += [\n            $prefix.'offset' => $c->getOffset(),\n            $prefix.'partition' => $c->getPartition(),\n            $prefix.'topic' => $c->getTopic(),\n        ];\n\n        return $a;\n    }\n\n    public static function castMessage(Message $c, array $a, Stub $stub, bool $isNested): array\n    {\n        $prefix = Caster::PREFIX_VIRTUAL;\n\n        $a += [\n            $prefix.'errstr' => $c->errstr(),\n        ];\n\n        return $a;\n    }\n\n    public static function castConf(Conf $c, array $a, Stub $stub, bool $isNested): array\n    {\n        $prefix = Caster::PREFIX_VIRTUAL;\n\n        foreach ($c->dump() as $key => $value) {\n            $a[$prefix.$key] = $value;\n        }\n\n        return $a;\n    }\n\n    public static function castTopicConf(TopicConf $c, array $a, Stub $stub, bool $isNested): array\n    {\n        $prefix = Caster::PREFIX_VIRTUAL;\n\n        foreach ($c->dump() as $key => $value) {\n            $a[$prefix.$key] = $value;\n        }\n\n        return $a;\n    }\n\n    public static function castRdKafka(\\RdKafka $c, array $a, Stub $stub, bool $isNested): array\n    {\n        $prefix = Caster::PREFIX_VIRTUAL;\n\n        $a += [\n            $prefix.'out_q_len' => $c->getOutQLen(),\n        ];\n\n        $a += self::extractMetadata($c);\n\n        return $a;\n    }\n\n    public static function castCollectionMetadata(CollectionMetadata $c, array $a, Stub $stub, bool $isNested): array\n    {\n        $a += iterator_to_array($c);\n\n        return $a;\n    }\n\n    public static function castTopicMetadata(TopicMetadata $c, array $a, Stub $stub, bool $isNested): array\n    {\n        $prefix = Caster::PREFIX_VIRTUAL;\n\n        $a += [\n            $prefix.'name' => $c->getTopic(),\n            $prefix.'partitions' => $c->getPartitions(),\n        ];\n\n        return $a;\n    }\n\n    public static function castPartitionMetadata(PartitionMetadata $c, array $a, Stub $stub, bool $isNested): array\n    {\n        $prefix = Caster::PREFIX_VIRTUAL;\n\n        $a += [\n            $prefix.'id' => $c->getId(),\n            $prefix.'err' => $c->getErr(),\n            $prefix.'leader' => $c->getLeader(),\n        ];\n\n        return $a;\n    }\n\n    public static function castBrokerMetadata(BrokerMetadata $c, array $a, Stub $stub, bool $isNested): array\n    {\n        $prefix = Caster::PREFIX_VIRTUAL;\n\n        $a += [\n            $prefix.'id' => $c->getId(),\n            $prefix.'host' => $c->getHost(),\n            $prefix.'port' => $c->getPort(),\n        ];\n\n        return $a;\n    }\n\n    private static function extractMetadata(KafkaConsumer|\\RdKafka $c): array\n    {\n        $prefix = Caster::PREFIX_VIRTUAL;\n\n        try {\n            $m = $c->getMetadata(true, null, 500);\n        } catch (RdKafkaException) {\n            return [];\n        }\n\n        return [\n            $prefix.'orig_broker_id' => $m->getOrigBrokerId(),\n            $prefix.'orig_broker_name' => $m->getOrigBrokerName(),\n            $prefix.'brokers' => $m->getBrokers(),\n            $prefix.'topics' => $m->getTopics(),\n        ];\n    }\n}\n"
  },
  {
    "path": "Caster/RedisCaster.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Caster;\n\nuse Relay\\Relay;\nuse Symfony\\Component\\VarDumper\\Cloner\\Stub;\n\n/**\n * Casts Redis class from ext-redis to array representation.\n *\n * @author Nicolas Grekas <p@tchwork.com>\n *\n * @final\n *\n * @internal\n */\nclass RedisCaster\n{\n    private const SERIALIZERS = [\n        0 => 'NONE', // Redis::SERIALIZER_NONE\n        1 => 'PHP', // Redis::SERIALIZER_PHP\n        2 => 'IGBINARY', // Optional Redis::SERIALIZER_IGBINARY\n    ];\n\n    private const MODES = [\n        0 => 'ATOMIC', // Redis::ATOMIC\n        1 => 'MULTI', // Redis::MULTI\n        2 => 'PIPELINE', // Redis::PIPELINE\n    ];\n\n    private const COMPRESSION_MODES = [\n        0 => 'NONE', // Redis::COMPRESSION_NONE\n        1 => 'LZF',  // Redis::COMPRESSION_LZF\n    ];\n\n    private const FAILOVER_OPTIONS = [\n        \\RedisCluster::FAILOVER_NONE => 'NONE',\n        \\RedisCluster::FAILOVER_ERROR => 'ERROR',\n        \\RedisCluster::FAILOVER_DISTRIBUTE => 'DISTRIBUTE',\n        \\RedisCluster::FAILOVER_DISTRIBUTE_SLAVES => 'DISTRIBUTE_SLAVES',\n    ];\n\n    public static function castRedis(\\Redis|Relay $c, array $a, Stub $stub, bool $isNested): array\n    {\n        $prefix = Caster::PREFIX_VIRTUAL;\n\n        if (!$connected = $c->isConnected()) {\n            return $a + [\n                $prefix.'isConnected' => $connected,\n            ];\n        }\n\n        $mode = $c->getMode();\n\n        return $a + [\n            $prefix.'isConnected' => $connected,\n            $prefix.'host' => $c->getHost(),\n            $prefix.'port' => $c->getPort(),\n            $prefix.'auth' => $c->getAuth(),\n            $prefix.'mode' => isset(self::MODES[$mode]) ? new ConstStub(self::MODES[$mode], $mode) : $mode,\n            $prefix.'dbNum' => $c->getDbNum(),\n            $prefix.'timeout' => $c->getTimeout(),\n            $prefix.'lastError' => $c->getLastError(),\n            $prefix.'persistentId' => $c->getPersistentID(),\n            $prefix.'options' => self::getRedisOptions($c),\n        ];\n    }\n\n    public static function castRedisArray(\\RedisArray $c, array $a, Stub $stub, bool $isNested): array\n    {\n        $prefix = Caster::PREFIX_VIRTUAL;\n\n        return $a + [\n            $prefix.'hosts' => $c->_hosts(),\n            $prefix.'function' => ClassStub::wrapCallable($c->_function()),\n            $prefix.'lastError' => $c->getLastError(),\n            $prefix.'options' => self::getRedisOptions($c),\n        ];\n    }\n\n    public static function castRedisCluster(\\RedisCluster $c, array $a, Stub $stub, bool $isNested): array\n    {\n        $prefix = Caster::PREFIX_VIRTUAL;\n        $failover = $c->getOption(\\RedisCluster::OPT_SLAVE_FAILOVER);\n\n        $a += [\n            $prefix.'_masters' => $c->_masters(),\n            $prefix.'_redir' => $c->_redir(),\n            $prefix.'mode' => new ConstStub($c->getMode() ? 'MULTI' : 'ATOMIC', $c->getMode()),\n            $prefix.'lastError' => $c->getLastError(),\n            $prefix.'options' => self::getRedisOptions($c, [\n                'SLAVE_FAILOVER' => isset(self::FAILOVER_OPTIONS[$failover]) ? new ConstStub(self::FAILOVER_OPTIONS[$failover], $failover) : $failover,\n            ]),\n        ];\n\n        return $a;\n    }\n\n    private static function getRedisOptions(\\Redis|Relay|\\RedisArray|\\RedisCluster $redis, array $options = []): EnumStub\n    {\n        $serializer = $redis->getOption(\\defined('Redis::OPT_SERIALIZER') ? \\Redis::OPT_SERIALIZER : 1);\n        if (\\is_array($serializer)) {\n            foreach ($serializer as &$v) {\n                if (isset(self::SERIALIZERS[$v])) {\n                    $v = new ConstStub(self::SERIALIZERS[$v], $v);\n                }\n            }\n        } elseif (isset(self::SERIALIZERS[$serializer])) {\n            $serializer = new ConstStub(self::SERIALIZERS[$serializer], $serializer);\n        }\n\n        $compression = \\defined('Redis::OPT_COMPRESSION') ? $redis->getOption(\\Redis::OPT_COMPRESSION) : 0;\n        if (\\is_array($compression)) {\n            foreach ($compression as &$v) {\n                if (isset(self::COMPRESSION_MODES[$v])) {\n                    $v = new ConstStub(self::COMPRESSION_MODES[$v], $v);\n                }\n            }\n        } elseif (isset(self::COMPRESSION_MODES[$compression])) {\n            $compression = new ConstStub(self::COMPRESSION_MODES[$compression], $compression);\n        }\n\n        $retry = \\defined('Redis::OPT_SCAN') ? $redis->getOption(\\Redis::OPT_SCAN) : 0;\n        if (\\is_array($retry)) {\n            foreach ($retry as &$v) {\n                $v = new ConstStub($v ? 'RETRY' : 'NORETRY', $v);\n            }\n        } else {\n            $retry = new ConstStub($retry ? 'RETRY' : 'NORETRY', $retry);\n        }\n\n        $options += [\n            'TCP_KEEPALIVE' => \\defined('Redis::OPT_TCP_KEEPALIVE') ? $redis->getOption(\\Redis::OPT_TCP_KEEPALIVE) : Relay::OPT_TCP_KEEPALIVE,\n            'READ_TIMEOUT' => $redis->getOption(\\defined('Redis::OPT_READ_TIMEOUT') ? \\Redis::OPT_READ_TIMEOUT : Relay::OPT_READ_TIMEOUT),\n            'COMPRESSION' => $compression,\n            'SERIALIZER' => $serializer,\n            'PREFIX' => $redis->getOption(\\defined('Redis::OPT_PREFIX') ? \\Redis::OPT_PREFIX : Relay::OPT_PREFIX),\n            'SCAN' => $retry,\n        ];\n\n        return new EnumStub($options);\n    }\n}\n"
  },
  {
    "path": "Caster/ReflectionCaster.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Caster;\n\nuse Symfony\\Component\\VarDumper\\Cloner\\Stub;\n\n/**\n * Casts Reflector related classes to array representation.\n *\n * @author Nicolas Grekas <p@tchwork.com>\n *\n * @final\n *\n * @internal\n */\nclass ReflectionCaster\n{\n    public const UNSET_CLOSURE_FILE_INFO = ['Closure' => __CLASS__.'::unsetClosureFileInfo'];\n\n    private const EXTRA_MAP = [\n        'docComment' => 'getDocComment',\n        'extension' => 'getExtensionName',\n        'isDisabled' => 'isDisabled',\n        'isDeprecated' => 'isDeprecated',\n        'isInternal' => 'isInternal',\n        'isUserDefined' => 'isUserDefined',\n        'isGenerator' => 'isGenerator',\n        'isVariadic' => 'isVariadic',\n    ];\n\n    public static function castClosure(\\Closure $c, array $a, Stub $stub, bool $isNested, int $filter = 0): array\n    {\n        $prefix = Caster::PREFIX_VIRTUAL;\n        $c = new \\ReflectionFunction($c);\n\n        $a = static::castFunctionAbstract($c, $a, $stub, $isNested, $filter);\n\n        if (!$c->isAnonymous()) {\n            $stub->class = isset($a[$prefix.'class']) ? $a[$prefix.'class']->value.'::'.$c->name : $c->name;\n            unset($a[$prefix.'class']);\n        }\n        unset($a[$prefix.'extra']);\n\n        $stub->class .= self::getSignature($a);\n\n        if ($f = $c->getFileName()) {\n            $stub->attr['file'] = $f;\n            $stub->attr['line'] = $c->getStartLine();\n        }\n\n        unset($a[$prefix.'parameters']);\n\n        if ($filter & Caster::EXCLUDE_VERBOSE) {\n            $stub->cut += ($c->getFileName() ? 2 : 0) + \\count($a);\n\n            return [];\n        }\n\n        if ($f) {\n            $a[$prefix.'file'] = new LinkStub($f, $c->getStartLine());\n            $a[$prefix.'line'] = $c->getStartLine().' to '.$c->getEndLine();\n        }\n\n        return $a;\n    }\n\n    public static function unsetClosureFileInfo(\\Closure $c, array $a): array\n    {\n        unset($a[Caster::PREFIX_VIRTUAL.'file'], $a[Caster::PREFIX_VIRTUAL.'line']);\n\n        return $a;\n    }\n\n    public static function castGenerator(\\Generator $c, array $a, Stub $stub, bool $isNested): array\n    {\n        // Cannot create ReflectionGenerator based on a terminated Generator\n        try {\n            $reflectionGenerator = new \\ReflectionGenerator($c);\n\n            return self::castReflectionGenerator($reflectionGenerator, $a, $stub, $isNested);\n        } catch (\\Exception) {\n            $a[Caster::PREFIX_VIRTUAL.'closed'] = true;\n\n            return $a;\n        }\n    }\n\n    public static function castType(\\ReflectionType $c, array $a, Stub $stub, bool $isNested): array\n    {\n        $prefix = Caster::PREFIX_VIRTUAL;\n\n        if ($c instanceof \\ReflectionNamedType) {\n            $a += [\n                $prefix.'name' => $c->getName(),\n                $prefix.'allowsNull' => $c->allowsNull(),\n                $prefix.'isBuiltin' => $c->isBuiltin(),\n            ];\n        } elseif ($c instanceof \\ReflectionUnionType || $c instanceof \\ReflectionIntersectionType) {\n            $a[$prefix.'allowsNull'] = $c->allowsNull();\n            self::addMap($a, $c, [\n                'types' => 'getTypes',\n            ]);\n        } else {\n            $a[$prefix.'allowsNull'] = $c->allowsNull();\n        }\n\n        return $a;\n    }\n\n    public static function castAttribute(\\ReflectionAttribute $c, array $a, Stub $stub, bool $isNested): array\n    {\n        $map = [\n            'arguments' => 'getArguments',\n        ];\n\n        self::addMap($a, $c, $map);\n\n        return $a;\n    }\n\n    public static function castReflectionGenerator(\\ReflectionGenerator $c, array $a, Stub $stub, bool $isNested): array\n    {\n        $prefix = Caster::PREFIX_VIRTUAL;\n\n        if ($c->getThis()) {\n            $a[$prefix.'this'] = new CutStub($c->getThis());\n        }\n        $function = $c->getFunction();\n        $frame = [\n            'class' => $function->class ?? null,\n            'type' => isset($function->class) ? ($function->isStatic() ? '::' : '->') : null,\n            'function' => $function->name,\n            'file' => $c->getExecutingFile(),\n            'line' => $c->getExecutingLine(),\n        ];\n        if ($trace = $c->getTrace(\\DEBUG_BACKTRACE_IGNORE_ARGS)) {\n            $function = new \\ReflectionGenerator($c->getExecutingGenerator());\n            array_unshift($trace, [\n                'function' => 'yield',\n                'file' => $function->getExecutingFile(),\n                'line' => $function->getExecutingLine(),\n            ]);\n            $trace[] = $frame;\n            $a[$prefix.'trace'] = new TraceStub($trace, false, 0, -1, -1);\n        } else {\n            $function = new FrameStub($frame, false, true);\n            $function = ExceptionCaster::castFrameStub($function, [], $function, true);\n            $a[$prefix.'executing'] = $function[$prefix.'src'];\n        }\n\n        $a[Caster::PREFIX_VIRTUAL.'closed'] = false;\n\n        return $a;\n    }\n\n    public static function castClass(\\ReflectionClass $c, array $a, Stub $stub, bool $isNested, int $filter = 0): array\n    {\n        $prefix = Caster::PREFIX_VIRTUAL;\n\n        if ($n = \\Reflection::getModifierNames($c->getModifiers())) {\n            $a[$prefix.'modifiers'] = implode(' ', $n);\n        }\n\n        self::addMap($a, $c, [\n            'extends' => 'getParentClass',\n            'implements' => 'getInterfaceNames',\n            'constants' => 'getReflectionConstants',\n        ]);\n\n        foreach ($c->getProperties() as $n) {\n            $a[$prefix.'properties'][$n->name] = $n;\n        }\n\n        foreach ($c->getMethods() as $n) {\n            $a[$prefix.'methods'][$n->name] = $n;\n        }\n\n        self::addAttributes($a, $c, $prefix);\n\n        if (!($filter & Caster::EXCLUDE_VERBOSE) && !$isNested) {\n            self::addExtra($a, $c);\n        }\n\n        return $a;\n    }\n\n    public static function castFunctionAbstract(\\ReflectionFunctionAbstract $c, array $a, Stub $stub, bool $isNested, int $filter = 0): array\n    {\n        $prefix = Caster::PREFIX_VIRTUAL;\n\n        self::addMap($a, $c, [\n            'returnsReference' => 'returnsReference',\n            'returnType' => 'getReturnType',\n            'class' => 'getClosureCalledClass',\n            'this' => 'getClosureThis',\n        ]);\n\n        if (isset($a[$prefix.'returnType'])) {\n            $v = $a[$prefix.'returnType'];\n            $v = $v instanceof \\ReflectionNamedType ? $v->getName() : (string) $v;\n            $a[$prefix.'returnType'] = new ClassStub($a[$prefix.'returnType'] instanceof \\ReflectionNamedType && $a[$prefix.'returnType']->allowsNull() && !\\in_array($v, ['mixed', 'null'], true) ? '?'.$v : $v, [class_exists($v, false) || interface_exists($v, false) || trait_exists($v, false) ? $v : '', '']);\n        }\n        if (isset($a[$prefix.'class'])) {\n            $a[$prefix.'class'] = new ClassStub($a[$prefix.'class']);\n        }\n        if (isset($a[$prefix.'this'])) {\n            $a[$prefix.'this'] = new CutStub($a[$prefix.'this']);\n        }\n\n        foreach ($c->getParameters() as $v) {\n            $k = '$'.$v->name;\n            if ($v->isVariadic()) {\n                $k = '...'.$k;\n            }\n            if ($v->isPassedByReference()) {\n                $k = '&'.$k;\n            }\n            $a[$prefix.'parameters'][$k] = $v;\n        }\n        if (isset($a[$prefix.'parameters'])) {\n            $a[$prefix.'parameters'] = new EnumStub($a[$prefix.'parameters']);\n        }\n\n        self::addAttributes($a, $c, $prefix);\n\n        if (!($filter & Caster::EXCLUDE_VERBOSE) && $v = $c->getStaticVariables()) {\n            foreach ($v as $k => &$v) {\n                if (\\is_object($v)) {\n                    $a[$prefix.'use']['$'.$k] = new CutStub($v);\n                } else {\n                    $a[$prefix.'use']['$'.$k] = &$v;\n                }\n            }\n            unset($v);\n            $a[$prefix.'use'] = new EnumStub($a[$prefix.'use']);\n        }\n\n        if (!($filter & Caster::EXCLUDE_VERBOSE) && !$isNested) {\n            self::addExtra($a, $c);\n        }\n\n        return $a;\n    }\n\n    public static function castClassConstant(\\ReflectionClassConstant $c, array $a, Stub $stub, bool $isNested): array\n    {\n        $a[Caster::PREFIX_VIRTUAL.'modifiers'] = implode(' ', \\Reflection::getModifierNames($c->getModifiers()));\n        $a[Caster::PREFIX_VIRTUAL.'value'] = $c->getValue();\n\n        self::addAttributes($a, $c);\n\n        return $a;\n    }\n\n    public static function castMethod(\\ReflectionMethod $c, array $a, Stub $stub, bool $isNested): array\n    {\n        $a[Caster::PREFIX_VIRTUAL.'modifiers'] = implode(' ', \\Reflection::getModifierNames($c->getModifiers()));\n\n        return $a;\n    }\n\n    public static function castParameter(\\ReflectionParameter $c, array $a, Stub $stub, bool $isNested): array\n    {\n        $prefix = Caster::PREFIX_VIRTUAL;\n\n        self::addMap($a, $c, [\n            'position' => 'getPosition',\n            'isVariadic' => 'isVariadic',\n            'byReference' => 'isPassedByReference',\n            'allowsNull' => 'allowsNull',\n        ]);\n\n        self::addAttributes($a, $c, $prefix);\n\n        if ($v = $c->getType()) {\n            $a[$prefix.'typeHint'] = $v instanceof \\ReflectionNamedType ? $v->getName() : (string) $v;\n        }\n\n        if (isset($a[$prefix.'typeHint'])) {\n            $v = $a[$prefix.'typeHint'];\n            $a[$prefix.'typeHint'] = new ClassStub($v, [class_exists($v, false) || interface_exists($v, false) || trait_exists($v, false) ? $v : '', '']);\n        } else {\n            unset($a[$prefix.'allowsNull']);\n        }\n\n        if ($c->isOptional()) {\n            try {\n                $a[$prefix.'default'] = $v = $c->getDefaultValue();\n                if ($c->isDefaultValueConstant() && !\\is_object($v)) {\n                    $a[$prefix.'default'] = new ConstStub($c->getDefaultValueConstantName(), $v);\n                }\n                if (null === $v) {\n                    unset($a[$prefix.'allowsNull']);\n                }\n            } catch (\\ReflectionException) {\n            }\n        }\n\n        return $a;\n    }\n\n    public static function castProperty(\\ReflectionProperty $c, array $a, Stub $stub, bool $isNested): array\n    {\n        $a[Caster::PREFIX_VIRTUAL.'modifiers'] = implode(' ', \\Reflection::getModifierNames($c->getModifiers()));\n\n        self::addAttributes($a, $c);\n        self::addExtra($a, $c);\n\n        return $a;\n    }\n\n    public static function castReference(\\ReflectionReference $c, array $a, Stub $stub, bool $isNested): array\n    {\n        $a[Caster::PREFIX_VIRTUAL.'id'] = $c->getId();\n\n        return $a;\n    }\n\n    public static function castExtension(\\ReflectionExtension $c, array $a, Stub $stub, bool $isNested): array\n    {\n        self::addMap($a, $c, [\n            'version' => 'getVersion',\n            'dependencies' => 'getDependencies',\n            'iniEntries' => 'getIniEntries',\n            'isPersistent' => 'isPersistent',\n            'isTemporary' => 'isTemporary',\n            'constants' => 'getConstants',\n            'functions' => 'getFunctions',\n            'classes' => 'getClasses',\n        ]);\n\n        return $a;\n    }\n\n    public static function castZendExtension(\\ReflectionZendExtension $c, array $a, Stub $stub, bool $isNested): array\n    {\n        self::addMap($a, $c, [\n            'version' => 'getVersion',\n            'author' => 'getAuthor',\n            'copyright' => 'getCopyright',\n            'url' => 'getURL',\n        ]);\n\n        return $a;\n    }\n\n    public static function getSignature(array $a): string\n    {\n        $prefix = Caster::PREFIX_VIRTUAL;\n        $signature = '';\n\n        if (isset($a[$prefix.'parameters'])) {\n            foreach ($a[$prefix.'parameters']->value as $k => $param) {\n                $signature .= ', ';\n                if ($type = $param->getType()) {\n                    if (!$type instanceof \\ReflectionNamedType) {\n                        $signature .= $type.' ';\n                    } else {\n                        if ($param->allowsNull() && !\\in_array($type->getName(), ['mixed', 'null'], true)) {\n                            $signature .= '?';\n                        }\n                        $signature .= substr(strrchr('\\\\'.$type->getName(), '\\\\'), 1).' ';\n                    }\n                }\n                $signature .= $k;\n\n                if (!$param->isDefaultValueAvailable()) {\n                    continue;\n                }\n                $v = $param->getDefaultValue();\n                $signature .= ' = ';\n\n                if ($param->isDefaultValueConstant()) {\n                    $signature .= substr(strrchr('\\\\'.$param->getDefaultValueConstantName(), '\\\\'), 1);\n                } elseif (null === $v) {\n                    $signature .= 'null';\n                } elseif (\\is_array($v)) {\n                    $signature .= $v ? '[…'.\\count($v).']' : '[]';\n                } elseif (\\is_string($v)) {\n                    $signature .= 10 > \\strlen($v) && !str_contains($v, '\\\\') ? \"'{$v}'\" : \"'…\".\\strlen($v).\"'\";\n                } elseif (\\is_bool($v)) {\n                    $signature .= $v ? 'true' : 'false';\n                } elseif (\\is_object($v)) {\n                    $signature .= 'new '.substr(strrchr('\\\\'.get_debug_type($v), '\\\\'), 1);\n                } else {\n                    $signature .= $v;\n                }\n            }\n        }\n        $signature = (empty($a[$prefix.'returnsReference']) ? '' : '&').'('.substr($signature, 2).')';\n\n        if (isset($a[$prefix.'returnType'])) {\n            $signature .= ': '.substr(strrchr('\\\\'.$a[$prefix.'returnType'], '\\\\'), 1);\n        }\n\n        return $signature;\n    }\n\n    private static function addExtra(array &$a, \\Reflector $c): void\n    {\n        $x = isset($a[Caster::PREFIX_VIRTUAL.'extra']) ? $a[Caster::PREFIX_VIRTUAL.'extra']->value : [];\n\n        if (method_exists($c, 'getFileName') && $m = $c->getFileName()) {\n            $x['file'] = new LinkStub($m, $c->getStartLine());\n            $x['line'] = $c->getStartLine().' to '.$c->getEndLine();\n        }\n\n        self::addMap($x, $c, self::EXTRA_MAP, '');\n\n        if ($x) {\n            $a[Caster::PREFIX_VIRTUAL.'extra'] = new EnumStub($x);\n        }\n    }\n\n    private static function addMap(array &$a, object $c, array $map, string $prefix = Caster::PREFIX_VIRTUAL): void\n    {\n        foreach ($map as $k => $m) {\n            if ('isDisabled' === $k) {\n                continue;\n            }\n\n            if (method_exists($c, $m) && false !== ($m = $c->$m()) && null !== $m) {\n                $a[$prefix.$k] = $m instanceof \\Reflector ? $m->name : $m;\n            }\n        }\n    }\n\n    private static function addAttributes(array &$a, \\Reflector $c, string $prefix = Caster::PREFIX_VIRTUAL): void\n    {\n        foreach ($c->getAttributes() as $n) {\n            $a[$prefix.'attributes'][] = $n;\n        }\n    }\n}\n"
  },
  {
    "path": "Caster/ResourceCaster.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Caster;\n\nuse Symfony\\Component\\VarDumper\\Cloner\\Stub;\n\n/**\n * Casts common resource types to array representation.\n *\n * @author Nicolas Grekas <p@tchwork.com>\n *\n * @final\n *\n * @internal\n */\nclass ResourceCaster\n{\n    public static function castDba(\\Dba\\Connection $dba, array $a, Stub $stub, bool $isNested): array\n    {\n        if (\\PHP_VERSION_ID < 80402) {\n            // @see https://github.com/php/php-src/issues/16990\n            return $a;\n        }\n\n        $list = dba_list();\n        $a['file'] = $list[(int) $dba];\n\n        return $a;\n    }\n\n    public static function castProcess($process, array $a, Stub $stub, bool $isNested): array\n    {\n        return proc_get_status($process);\n    }\n\n    public static function castStream($stream, array $a, Stub $stub, bool $isNested): array\n    {\n        $a = stream_get_meta_data($stream) + static::castStreamContext($stream, $a, $stub, $isNested);\n        if ($a['uri'] ?? false) {\n            $a['uri'] = new LinkStub($a['uri']);\n        }\n\n        return $a;\n    }\n\n    public static function castStreamContext($stream, array $a, Stub $stub, bool $isNested): array\n    {\n        return @stream_context_get_params($stream) ?: $a;\n    }\n}\n"
  },
  {
    "path": "Caster/ScalarStub.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Caster;\n\nuse Symfony\\Component\\VarDumper\\Cloner\\Stub;\n\n/**\n * Represents any arbitrary value.\n *\n * @author Alexandre Daubois <alex.daubois@gmail.com>\n */\nclass ScalarStub extends Stub\n{\n    public function __construct(mixed $value)\n    {\n        $this->value = $value;\n    }\n}\n"
  },
  {
    "path": "Caster/SocketCaster.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Caster;\n\nuse Symfony\\Component\\VarDumper\\Cloner\\Stub;\n\n/**\n * @author Nicolas Grekas <p@tchwork.com>\n * @author Alexandre Daubois <alex.daubois@gmail.com>\n *\n * @internal\n */\nfinal class SocketCaster\n{\n    public static function castSocket(\\Socket $socket, array $a, Stub $stub, bool $isNested): array\n    {\n        socket_getsockname($socket, $addr, $port);\n        $info = stream_get_meta_data(socket_export_stream($socket));\n\n        $uri = ($info['uri'] ?? '//');\n        if (str_starts_with($uri, 'unix://')) {\n            $uri .= $addr;\n        } else {\n            $uri .= \\sprintf(str_contains($addr, ':') ? '[%s]:%s' : '%s:%s', $addr, $port);\n        }\n\n        $a[Caster::PREFIX_VIRTUAL.'uri'] = $uri;\n\n        if (@socket_atmark($socket)) {\n            $a[Caster::PREFIX_VIRTUAL.'atmark'] = true;\n        }\n\n        $a += [\n            Caster::PREFIX_VIRTUAL.'timed_out' => $info['timed_out'],\n            Caster::PREFIX_VIRTUAL.'blocked' => $info['blocked'],\n        ];\n\n        if (!$lastError = socket_last_error($socket)) {\n            return $a;\n        }\n\n        static $errors;\n\n        if (!$errors) {\n            $errors = get_defined_constants(true)['sockets'] ?? [];\n            $errors = array_flip(array_filter($errors, static fn ($k) => str_starts_with($k, 'SOCKET_E'), \\ARRAY_FILTER_USE_KEY));\n        }\n\n        $a[Caster::PREFIX_VIRTUAL.'last_error'] = new ConstStub($errors[$lastError], socket_strerror($lastError));\n\n        return $a;\n    }\n}\n"
  },
  {
    "path": "Caster/SplCaster.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Caster;\n\nuse Symfony\\Component\\VarDumper\\Cloner\\Stub;\n\n/**\n * Casts SPL related classes to array representation.\n *\n * @author Nicolas Grekas <p@tchwork.com>\n *\n * @final\n *\n * @internal\n */\nclass SplCaster\n{\n    private const SPL_FILE_OBJECT_FLAGS = [\n        \\SplFileObject::DROP_NEW_LINE => 'DROP_NEW_LINE',\n        \\SplFileObject::READ_AHEAD => 'READ_AHEAD',\n        \\SplFileObject::SKIP_EMPTY => 'SKIP_EMPTY',\n        \\SplFileObject::READ_CSV => 'READ_CSV',\n    ];\n\n    public static function castArrayObject(\\ArrayObject $c, array $a, Stub $stub, bool $isNested): array\n    {\n        return self::castSplArray($c, $a, $stub, $isNested);\n    }\n\n    public static function castArrayIterator(\\ArrayIterator $c, array $a, Stub $stub, bool $isNested): array\n    {\n        return self::castSplArray($c, $a, $stub, $isNested);\n    }\n\n    public static function castHeap(\\Iterator $c, array $a, Stub $stub, bool $isNested): array\n    {\n        $a += [\n            Caster::PREFIX_VIRTUAL.'heap' => iterator_to_array(clone $c),\n        ];\n\n        return $a;\n    }\n\n    public static function castDoublyLinkedList(\\SplDoublyLinkedList $c, array $a, Stub $stub, bool $isNested): array\n    {\n        $prefix = Caster::PREFIX_VIRTUAL;\n        $mode = $c->getIteratorMode();\n        $c->setIteratorMode(\\SplDoublyLinkedList::IT_MODE_KEEP | $mode & ~\\SplDoublyLinkedList::IT_MODE_DELETE);\n\n        $a += [\n            $prefix.'mode' => new ConstStub((($mode & \\SplDoublyLinkedList::IT_MODE_LIFO) ? 'IT_MODE_LIFO' : 'IT_MODE_FIFO').' | '.(($mode & \\SplDoublyLinkedList::IT_MODE_DELETE) ? 'IT_MODE_DELETE' : 'IT_MODE_KEEP'), $mode),\n            $prefix.'dllist' => iterator_to_array($c),\n        ];\n        $c->setIteratorMode($mode);\n\n        return $a;\n    }\n\n    public static function castFileInfo(\\SplFileInfo $c, array $a, Stub $stub, bool $isNested): array\n    {\n        static $map = [\n            'path' => 'getPath',\n            'filename' => 'getFilename',\n            'basename' => 'getBasename',\n            'pathname' => 'getPathname',\n            'extension' => 'getExtension',\n            'realPath' => 'getRealPath',\n            'aTime' => 'getATime',\n            'mTime' => 'getMTime',\n            'cTime' => 'getCTime',\n            'inode' => 'getInode',\n            'size' => 'getSize',\n            'perms' => 'getPerms',\n            'owner' => 'getOwner',\n            'group' => 'getGroup',\n            'type' => 'getType',\n            'writable' => 'isWritable',\n            'readable' => 'isReadable',\n            'executable' => 'isExecutable',\n            'file' => 'isFile',\n            'dir' => 'isDir',\n            'link' => 'isLink',\n            'linkTarget' => 'getLinkTarget',\n        ];\n\n        $prefix = Caster::PREFIX_VIRTUAL;\n        unset($a[\"\\0SplFileInfo\\0fileName\"]);\n        unset($a[\"\\0SplFileInfo\\0pathName\"]);\n\n        try {\n            $c->isReadable();\n        } catch (\\RuntimeException $e) {\n            if ('Object not initialized' !== $e->getMessage()) {\n                throw $e;\n            }\n\n            $a[$prefix.'⚠'] = 'The parent constructor was not called: the object is in an invalid state';\n\n            return $a;\n        } catch (\\Error $e) {\n            if ('Object not initialized' !== $e->getMessage()) {\n                throw $e;\n            }\n\n            $a[$prefix.'⚠'] = 'The parent constructor was not called: the object is in an invalid state';\n\n            return $a;\n        }\n\n        foreach ($map as $key => $accessor) {\n            try {\n                $a[$prefix.$key] = $c->$accessor();\n            } catch (\\Exception) {\n            }\n        }\n\n        if ($a[$prefix.'realPath'] ?? false) {\n            $a[$prefix.'realPath'] = new LinkStub($a[$prefix.'realPath']);\n        }\n\n        if (isset($a[$prefix.'perms'])) {\n            $a[$prefix.'perms'] = new ConstStub(\\sprintf('0%o', $a[$prefix.'perms']), $a[$prefix.'perms']);\n        }\n\n        static $mapDate = ['aTime', 'mTime', 'cTime'];\n        foreach ($mapDate as $key) {\n            if (isset($a[$prefix.$key])) {\n                $a[$prefix.$key] = new ConstStub(date('Y-m-d H:i:s', $a[$prefix.$key]), $a[$prefix.$key]);\n            }\n        }\n\n        return $a;\n    }\n\n    public static function castFileObject(\\SplFileObject $c, array $a, Stub $stub, bool $isNested): array\n    {\n        static $map = [\n            'csvControl' => 'getCsvControl',\n            'flags' => 'getFlags',\n            'maxLineLen' => 'getMaxLineLen',\n            'fstat' => 'fstat',\n            'eof' => 'eof',\n            'key' => 'key',\n        ];\n\n        $prefix = Caster::PREFIX_VIRTUAL;\n\n        foreach ($map as $key => $accessor) {\n            try {\n                $a[$prefix.$key] = $c->$accessor();\n            } catch (\\Exception) {\n            }\n        }\n\n        if (isset($a[$prefix.'flags'])) {\n            $flagsArray = [];\n            foreach (self::SPL_FILE_OBJECT_FLAGS as $value => $name) {\n                if ($a[$prefix.'flags'] & $value) {\n                    $flagsArray[] = $name;\n                }\n            }\n            $a[$prefix.'flags'] = new ConstStub(implode('|', $flagsArray), $a[$prefix.'flags']);\n        }\n\n        if (isset($a[$prefix.'fstat'])) {\n            $a[$prefix.'fstat'] = new CutArrayStub($a[$prefix.'fstat'], ['dev', 'ino', 'nlink', 'rdev', 'blksize', 'blocks']);\n        }\n\n        return $a;\n    }\n\n    public static function castObjectStorage(\\SplObjectStorage $c, array $a, Stub $stub, bool $isNested): array\n    {\n        $storage = [];\n        unset($a[Caster::PREFIX_DYNAMIC.\"\\0gcdata\"]); // Don't hit https://bugs.php.net/65967\n        unset($a[\"\\0SplObjectStorage\\0storage\"]);\n\n        $clone = clone $c;\n        foreach ($clone as $obj) {\n            $storage[] = new EnumStub([\n                'object' => $obj,\n                'info' => $clone->getInfo(),\n            ]);\n        }\n\n        $a += [\n            Caster::PREFIX_VIRTUAL.'storage' => $storage,\n        ];\n\n        return $a;\n    }\n\n    public static function castOuterIterator(\\OuterIterator $c, array $a, Stub $stub, bool $isNested): array\n    {\n        $a[Caster::PREFIX_VIRTUAL.'innerIterator'] = $c->getInnerIterator();\n\n        return $a;\n    }\n\n    public static function castWeakReference(\\WeakReference $c, array $a, Stub $stub, bool $isNested): array\n    {\n        $a[Caster::PREFIX_VIRTUAL.'object'] = $c->get();\n\n        return $a;\n    }\n\n    public static function castWeakMap(\\WeakMap $c, array $a, Stub $stub, bool $isNested): array\n    {\n        $map = [];\n\n        foreach (clone $c as $obj => $data) {\n            $map[] = new EnumStub([\n                'object' => $obj,\n                'data' => $data,\n            ]);\n        }\n\n        $a += [\n            Caster::PREFIX_VIRTUAL.'map' => $map,\n        ];\n\n        return $a;\n    }\n\n    private static function castSplArray(\\ArrayObject|\\ArrayIterator $c, array $a, Stub $stub, bool $isNested): array\n    {\n        $prefix = Caster::PREFIX_VIRTUAL;\n        $flags = $c->getFlags();\n\n        if (!($flags & \\ArrayObject::STD_PROP_LIST)) {\n            $c->setFlags(\\ArrayObject::STD_PROP_LIST);\n            $a = Caster::castObject($c, $c::class, method_exists($c, '__debugInfo'), $stub->class);\n            $c->setFlags($flags);\n        }\n\n        unset($a[\"\\0ArrayObject\\0storage\"], $a[\"\\0ArrayIterator\\0storage\"]);\n\n        $a += [\n            $prefix.'storage' => $c->getArrayCopy(),\n            $prefix.'flag::STD_PROP_LIST' => (bool) ($flags & \\ArrayObject::STD_PROP_LIST),\n            $prefix.'flag::ARRAY_AS_PROPS' => (bool) ($flags & \\ArrayObject::ARRAY_AS_PROPS),\n        ];\n        if ($c instanceof \\ArrayObject) {\n            $a[$prefix.'iteratorClass'] = new ClassStub($c->getIteratorClass());\n        }\n\n        return $a;\n    }\n}\n"
  },
  {
    "path": "Caster/SqliteCaster.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Caster;\n\nuse Symfony\\Component\\VarDumper\\Cloner\\Stub;\n\n/**\n * @author Alexandre Daubois <alex.daubois@gmail.com>\n *\n * @internal\n */\nfinal class SqliteCaster\n{\n    public static function castSqlite3Result(\\SQLite3Result $result, array $a, Stub $stub, bool $isNested): array\n    {\n        $numColumns = $result->numColumns();\n        for ($i = 0; $i < $numColumns; ++$i) {\n            $a[Caster::PREFIX_VIRTUAL.'columnNames'][$i] = $result->columnName($i);\n        }\n\n        return $a;\n    }\n}\n"
  },
  {
    "path": "Caster/StubCaster.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Caster;\n\nuse Symfony\\Component\\VarDumper\\Cloner\\Stub;\n\n/**\n * Casts a caster's Stub.\n *\n * @author Nicolas Grekas <p@tchwork.com>\n *\n * @final\n *\n * @internal\n */\nclass StubCaster\n{\n    public static function castStub(Stub $c, array $a, Stub $stub, bool $isNested): array\n    {\n        if ($isNested) {\n            $stub->type = $c->type;\n            $stub->class = $c->class;\n            $stub->value = $c->value;\n            $stub->handle = $c->handle;\n            $stub->cut = $c->cut;\n            $stub->attr = $c->attr;\n\n            if (Stub::TYPE_REF === $c->type && !$c->class && \\is_string($c->value) && !preg_match('//u', $c->value)) {\n                $stub->type = Stub::TYPE_STRING;\n                $stub->class = Stub::STRING_BINARY;\n            }\n\n            $a = [];\n        }\n\n        return $a;\n    }\n\n    public static function castCutArray(CutArrayStub $c, array $a, Stub $stub, bool $isNested): array\n    {\n        return $isNested ? $c->preservedSubset : $a;\n    }\n\n    public static function cutInternals($obj, array $a, Stub $stub, bool $isNested): array\n    {\n        if ($isNested) {\n            $stub->cut += \\count($a);\n\n            return [];\n        }\n\n        return $a;\n    }\n\n    public static function castEnum(EnumStub $c, array $a, Stub $stub, bool $isNested): array\n    {\n        if ($isNested) {\n            $stub->class = $c->dumpKeys ? '' : null;\n            $stub->handle = 0;\n            $stub->value = null;\n            $stub->cut = $c->cut;\n            $stub->attr = $c->attr;\n\n            $a = [];\n\n            if ($c->value) {\n                foreach (array_keys($c->value) as $k) {\n                    $keys[] = !isset($k[0]) || \"\\0\" !== $k[0] ? Caster::PREFIX_VIRTUAL.$k : $k;\n                }\n                // Preserve references with array_combine()\n                $a = array_combine($keys, $c->value);\n            }\n        }\n\n        return $a;\n    }\n\n    public static function castScalar(ScalarStub $scalarStub, array $a, Stub $stub): array\n    {\n        $stub->type = Stub::TYPE_SCALAR;\n        $stub->attr['value'] = $scalarStub->value;\n\n        return $a;\n    }\n}\n"
  },
  {
    "path": "Caster/SymfonyCaster.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Caster;\n\nuse Symfony\\Component\\HttpFoundation\\Request;\nuse Symfony\\Component\\Uid\\TimeBasedUidInterface;\nuse Symfony\\Component\\Uid\\Ulid;\nuse Symfony\\Component\\Uid\\Uuid;\nuse Symfony\\Component\\VarDumper\\Cloner\\Stub;\nuse Symfony\\Component\\VarExporter\\Internal\\LazyObjectState;\n\n/**\n * @final\n *\n * @internal\n */\nclass SymfonyCaster\n{\n    private const REQUEST_GETTERS = [\n        'pathInfo' => 'getPathInfo',\n        'requestUri' => 'getRequestUri',\n        'baseUrl' => 'getBaseUrl',\n        'basePath' => 'getBasePath',\n        'method' => 'getMethod',\n        'format' => 'getRequestFormat',\n    ];\n\n    public static function castRequest(Request $request, array $a, Stub $stub, bool $isNested): array\n    {\n        $clone = null;\n\n        foreach (self::REQUEST_GETTERS as $prop => $getter) {\n            $key = Caster::PREFIX_PROTECTED.$prop;\n            if (\\array_key_exists($key, $a) && null === $a[$key]) {\n                $clone ??= clone $request;\n                $a[Caster::PREFIX_VIRTUAL.$prop] = $clone->{$getter}();\n            }\n        }\n\n        return $a;\n    }\n\n    public static function castHttpClient($client, array $a, Stub $stub, bool $isNested): array\n    {\n        $multiKey = \\sprintf(\"\\0%s\\0multi\", $client::class);\n        if (isset($a[$multiKey]) && !$a[$multiKey] instanceof Stub) {\n            $a[$multiKey] = new CutStub($a[$multiKey]);\n        }\n\n        return $a;\n    }\n\n    public static function castHttpClientResponse($response, array $a, Stub $stub, bool $isNested): array\n    {\n        $stub->cut += \\count($a);\n        $a = [];\n\n        foreach ($response->getInfo() as $k => $v) {\n            $a[Caster::PREFIX_VIRTUAL.$k] = $v;\n        }\n\n        return $a;\n    }\n\n    public static function castLazyObjectState($state, array $a, Stub $stub, bool $isNested): array\n    {\n        if (!$isNested) {\n            return $a;\n        }\n\n        $stub->cut += \\count($a) - 1;\n\n        $instance = $a['realInstance'] ?? null;\n\n        if (isset($a['status'])) { // forward-compat with Symfony 8\n            $a = ['status' => new ConstStub(match ($a['status']) {\n                LazyObjectState::STATUS_INITIALIZED_FULL => 'INITIALIZED_FULL',\n                LazyObjectState::STATUS_INITIALIZED_PARTIAL => 'INITIALIZED_PARTIAL',\n                LazyObjectState::STATUS_UNINITIALIZED_FULL => 'UNINITIALIZED_FULL',\n                LazyObjectState::STATUS_UNINITIALIZED_PARTIAL => 'UNINITIALIZED_PARTIAL',\n            }, $a['status'])];\n        }\n\n        if ($instance) {\n            $a['realInstance'] = $instance;\n            --$stub->cut;\n        }\n\n        return $a;\n    }\n\n    public static function castUuid(Uuid $uuid, array $a, Stub $stub, bool $isNested): array\n    {\n        $a[Caster::PREFIX_VIRTUAL.'toBase58'] = $uuid->toBase58();\n        $a[Caster::PREFIX_VIRTUAL.'toBase32'] = $uuid->toBase32();\n\n        if ($uuid instanceof TimeBasedUidInterface) {\n            $a[Caster::PREFIX_VIRTUAL.'time'] = $uuid->getDateTime()->format('Y-m-d H:i:s.u \\U\\T\\C');\n        }\n\n        return $a;\n    }\n\n    public static function castUlid(Ulid $ulid, array $a, Stub $stub, bool $isNested): array\n    {\n        $a[Caster::PREFIX_VIRTUAL.'toBase58'] = $ulid->toBase58();\n        $a[Caster::PREFIX_VIRTUAL.'toRfc4122'] = $ulid->toRfc4122();\n\n        if ($ulid instanceof TimeBasedUidInterface) {\n            $a[Caster::PREFIX_VIRTUAL.'time'] = $ulid->getDateTime()->format('Y-m-d H:i:s.v \\U\\T\\C');\n        }\n\n        return $a;\n    }\n}\n"
  },
  {
    "path": "Caster/TraceStub.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Caster;\n\nuse Symfony\\Component\\VarDumper\\Cloner\\Stub;\n\n/**\n * Represents a backtrace as returned by debug_backtrace() or Exception->getTrace().\n *\n * @author Nicolas Grekas <p@tchwork.com>\n */\nclass TraceStub extends Stub\n{\n    public function __construct(\n        array $trace,\n        public bool $keepArgs = true,\n        public int $sliceOffset = 0,\n        public ?int $sliceLength = null,\n        public int $numberingOffset = 0,\n    ) {\n        $this->value = $trace;\n    }\n}\n"
  },
  {
    "path": "Caster/UninitializedStub.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Caster;\n\n/**\n * Represents an uninitialized property.\n *\n * @author Nicolas Grekas <p@tchwork.com>\n */\nclass UninitializedStub extends ConstStub\n{\n    public function __construct(\\ReflectionProperty $property)\n    {\n        parent::__construct('?'.($property->hasType() ? ' '.$property->getType() : ''), 'Uninitialized property');\n    }\n}\n"
  },
  {
    "path": "Caster/UuidCaster.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Caster;\n\nuse Ramsey\\Uuid\\UuidInterface;\nuse Symfony\\Component\\VarDumper\\Cloner\\Stub;\n\n/**\n * @author Grégoire Pineau <lyrixx@lyrixx.info>\n *\n * @internal\n */\nfinal class UuidCaster\n{\n    public static function castRamseyUuid(UuidInterface $c, array $a, Stub $stub, bool $isNested): array\n    {\n        $a += [\n            Caster::PREFIX_VIRTUAL.'uuid' => (string) $c,\n        ];\n\n        return $a;\n    }\n}\n"
  },
  {
    "path": "Caster/VirtualStub.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Caster;\n\nclass VirtualStub extends ConstStub\n{\n    public function __construct(\\ReflectionProperty $property)\n    {\n        parent::__construct('~'.($property->hasType() ? ' '.$property->getType() : ''), 'Virtual property');\n        $this->attr['virtual'] = true;\n    }\n}\n"
  },
  {
    "path": "Caster/XmlReaderCaster.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Caster;\n\nuse Symfony\\Component\\VarDumper\\Cloner\\Stub;\n\n/**\n * Casts XmlReader class to array representation.\n *\n * @author Baptiste Clavié <clavie.b@gmail.com>\n *\n * @final\n *\n * @internal\n */\nclass XmlReaderCaster\n{\n    private const NODE_TYPES = [\n        \\XMLReader::NONE => 'NONE',\n        \\XMLReader::ELEMENT => 'ELEMENT',\n        \\XMLReader::ATTRIBUTE => 'ATTRIBUTE',\n        \\XMLReader::TEXT => 'TEXT',\n        \\XMLReader::CDATA => 'CDATA',\n        \\XMLReader::ENTITY_REF => 'ENTITY_REF',\n        \\XMLReader::ENTITY => 'ENTITY',\n        \\XMLReader::PI => 'PI (Processing Instruction)',\n        \\XMLReader::COMMENT => 'COMMENT',\n        \\XMLReader::DOC => 'DOC',\n        \\XMLReader::DOC_TYPE => 'DOC_TYPE',\n        \\XMLReader::DOC_FRAGMENT => 'DOC_FRAGMENT',\n        \\XMLReader::NOTATION => 'NOTATION',\n        \\XMLReader::WHITESPACE => 'WHITESPACE',\n        \\XMLReader::SIGNIFICANT_WHITESPACE => 'SIGNIFICANT_WHITESPACE',\n        \\XMLReader::END_ELEMENT => 'END_ELEMENT',\n        \\XMLReader::END_ENTITY => 'END_ENTITY',\n        \\XMLReader::XML_DECLARATION => 'XML_DECLARATION',\n    ];\n\n    public static function castXmlReader(\\XMLReader $reader, array $a, Stub $stub, bool $isNested): array\n    {\n        try {\n            $properties = [\n                'LOADDTD' => @$reader->getParserProperty(\\XMLReader::LOADDTD),\n                'DEFAULTATTRS' => @$reader->getParserProperty(\\XMLReader::DEFAULTATTRS),\n                'VALIDATE' => @$reader->getParserProperty(\\XMLReader::VALIDATE),\n                'SUBST_ENTITIES' => @$reader->getParserProperty(\\XMLReader::SUBST_ENTITIES),\n            ];\n        } catch (\\Error) {\n            $properties = [\n                'LOADDTD' => false,\n                'DEFAULTATTRS' => false,\n                'VALIDATE' => false,\n                'SUBST_ENTITIES' => false,\n            ];\n        }\n\n        $props = Caster::PREFIX_VIRTUAL.'parserProperties';\n        $info = [\n            'localName' => $reader->localName,\n            'prefix' => $reader->prefix,\n            'nodeType' => new ConstStub(self::NODE_TYPES[$reader->nodeType], $reader->nodeType),\n            'depth' => $reader->depth,\n            'isDefault' => $reader->isDefault,\n            'isEmptyElement' => \\XMLReader::NONE === $reader->nodeType ? null : $reader->isEmptyElement,\n            'xmlLang' => $reader->xmlLang,\n            'attributeCount' => $reader->attributeCount,\n            'value' => $reader->value,\n            'namespaceURI' => $reader->namespaceURI,\n            'baseURI' => $reader->baseURI ? new LinkStub($reader->baseURI) : $reader->baseURI,\n            $props => $properties,\n        ];\n\n        if ($info[$props] = Caster::filter($info[$props], Caster::EXCLUDE_EMPTY, [], $count)) {\n            $info[$props] = new EnumStub($info[$props]);\n            $info[$props]->cut = $count;\n        }\n\n        $a = Caster::filter($a, Caster::EXCLUDE_UNINITIALIZED, [], $count);\n        $info = Caster::filter($info, Caster::EXCLUDE_EMPTY, [], $count);\n        // +2 because hasValue and hasAttributes are always filtered\n        $stub->cut += $count + 2;\n\n        return $a + $info;\n    }\n}\n"
  },
  {
    "path": "Caster/XmlResourceCaster.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Caster;\n\nuse Symfony\\Component\\VarDumper\\Cloner\\Stub;\n\n/**\n * Casts XML resources to array representation.\n *\n * @author Nicolas Grekas <p@tchwork.com>\n *\n * @final\n *\n * @internal\n */\nclass XmlResourceCaster\n{\n    private const XML_ERRORS = [\n        \\XML_ERROR_NONE => 'XML_ERROR_NONE',\n        \\XML_ERROR_NO_MEMORY => 'XML_ERROR_NO_MEMORY',\n        \\XML_ERROR_SYNTAX => 'XML_ERROR_SYNTAX',\n        \\XML_ERROR_NO_ELEMENTS => 'XML_ERROR_NO_ELEMENTS',\n        \\XML_ERROR_INVALID_TOKEN => 'XML_ERROR_INVALID_TOKEN',\n        \\XML_ERROR_UNCLOSED_TOKEN => 'XML_ERROR_UNCLOSED_TOKEN',\n        \\XML_ERROR_PARTIAL_CHAR => 'XML_ERROR_PARTIAL_CHAR',\n        \\XML_ERROR_TAG_MISMATCH => 'XML_ERROR_TAG_MISMATCH',\n        \\XML_ERROR_DUPLICATE_ATTRIBUTE => 'XML_ERROR_DUPLICATE_ATTRIBUTE',\n        \\XML_ERROR_JUNK_AFTER_DOC_ELEMENT => 'XML_ERROR_JUNK_AFTER_DOC_ELEMENT',\n        \\XML_ERROR_PARAM_ENTITY_REF => 'XML_ERROR_PARAM_ENTITY_REF',\n        \\XML_ERROR_UNDEFINED_ENTITY => 'XML_ERROR_UNDEFINED_ENTITY',\n        \\XML_ERROR_RECURSIVE_ENTITY_REF => 'XML_ERROR_RECURSIVE_ENTITY_REF',\n        \\XML_ERROR_ASYNC_ENTITY => 'XML_ERROR_ASYNC_ENTITY',\n        \\XML_ERROR_BAD_CHAR_REF => 'XML_ERROR_BAD_CHAR_REF',\n        \\XML_ERROR_BINARY_ENTITY_REF => 'XML_ERROR_BINARY_ENTITY_REF',\n        \\XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF => 'XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF',\n        \\XML_ERROR_MISPLACED_XML_PI => 'XML_ERROR_MISPLACED_XML_PI',\n        \\XML_ERROR_UNKNOWN_ENCODING => 'XML_ERROR_UNKNOWN_ENCODING',\n        \\XML_ERROR_INCORRECT_ENCODING => 'XML_ERROR_INCORRECT_ENCODING',\n        \\XML_ERROR_UNCLOSED_CDATA_SECTION => 'XML_ERROR_UNCLOSED_CDATA_SECTION',\n        \\XML_ERROR_EXTERNAL_ENTITY_HANDLING => 'XML_ERROR_EXTERNAL_ENTITY_HANDLING',\n    ];\n\n    public static function castXml($h, array $a, Stub $stub, bool $isNested): array\n    {\n        $a['current_byte_index'] = xml_get_current_byte_index($h);\n        $a['current_column_number'] = xml_get_current_column_number($h);\n        $a['current_line_number'] = xml_get_current_line_number($h);\n        $a['error_code'] = xml_get_error_code($h);\n\n        if (isset(self::XML_ERRORS[$a['error_code']])) {\n            $a['error_code'] = new ConstStub(self::XML_ERRORS[$a['error_code']], $a['error_code']);\n        }\n\n        return $a;\n    }\n}\n"
  },
  {
    "path": "Cloner/AbstractCloner.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Cloner;\n\nuse Symfony\\Component\\VarDumper\\Caster\\Caster;\nuse Symfony\\Component\\VarDumper\\Exception\\ThrowingCasterException;\n\n/**\n * AbstractCloner implements a generic caster mechanism for objects and resources.\n *\n * @author Nicolas Grekas <p@tchwork.com>\n */\nabstract class AbstractCloner implements ClonerInterface\n{\n    public static array $defaultCasters = [\n        '__PHP_Incomplete_Class' => ['Symfony\\Component\\VarDumper\\Caster\\Caster', 'castPhpIncompleteClass'],\n\n        'AddressInfo' => ['Symfony\\Component\\VarDumper\\Caster\\AddressInfoCaster', 'castAddressInfo'],\n        'Socket' => ['Symfony\\Component\\VarDumper\\Caster\\SocketCaster', 'castSocket'],\n\n        'Symfony\\Component\\VarDumper\\Caster\\CutStub' => ['Symfony\\Component\\VarDumper\\Caster\\StubCaster', 'castStub'],\n        'Symfony\\Component\\VarDumper\\Caster\\CutArrayStub' => ['Symfony\\Component\\VarDumper\\Caster\\StubCaster', 'castCutArray'],\n        'Symfony\\Component\\VarDumper\\Caster\\ConstStub' => ['Symfony\\Component\\VarDumper\\Caster\\StubCaster', 'castStub'],\n        'Symfony\\Component\\VarDumper\\Caster\\EnumStub' => ['Symfony\\Component\\VarDumper\\Caster\\StubCaster', 'castEnum'],\n        'Symfony\\Component\\VarDumper\\Caster\\ScalarStub' => ['Symfony\\Component\\VarDumper\\Caster\\StubCaster', 'castScalar'],\n\n        'Fiber' => ['Symfony\\Component\\VarDumper\\Caster\\FiberCaster', 'castFiber'],\n\n        'Closure' => ['Symfony\\Component\\VarDumper\\Caster\\ReflectionCaster', 'castClosure'],\n        'Generator' => ['Symfony\\Component\\VarDumper\\Caster\\ReflectionCaster', 'castGenerator'],\n        'ReflectionType' => ['Symfony\\Component\\VarDumper\\Caster\\ReflectionCaster', 'castType'],\n        'ReflectionAttribute' => ['Symfony\\Component\\VarDumper\\Caster\\ReflectionCaster', 'castAttribute'],\n        'ReflectionGenerator' => ['Symfony\\Component\\VarDumper\\Caster\\ReflectionCaster', 'castReflectionGenerator'],\n        'ReflectionClass' => ['Symfony\\Component\\VarDumper\\Caster\\ReflectionCaster', 'castClass'],\n        'ReflectionClassConstant' => ['Symfony\\Component\\VarDumper\\Caster\\ReflectionCaster', 'castClassConstant'],\n        'ReflectionFunctionAbstract' => ['Symfony\\Component\\VarDumper\\Caster\\ReflectionCaster', 'castFunctionAbstract'],\n        'ReflectionMethod' => ['Symfony\\Component\\VarDumper\\Caster\\ReflectionCaster', 'castMethod'],\n        'ReflectionParameter' => ['Symfony\\Component\\VarDumper\\Caster\\ReflectionCaster', 'castParameter'],\n        'ReflectionProperty' => ['Symfony\\Component\\VarDumper\\Caster\\ReflectionCaster', 'castProperty'],\n        'ReflectionReference' => ['Symfony\\Component\\VarDumper\\Caster\\ReflectionCaster', 'castReference'],\n        'ReflectionExtension' => ['Symfony\\Component\\VarDumper\\Caster\\ReflectionCaster', 'castExtension'],\n        'ReflectionZendExtension' => ['Symfony\\Component\\VarDumper\\Caster\\ReflectionCaster', 'castZendExtension'],\n\n        'Doctrine\\Common\\Persistence\\ObjectManager' => ['Symfony\\Component\\VarDumper\\Caster\\StubCaster', 'cutInternals'],\n        'Doctrine\\Common\\Proxy\\Proxy' => ['Symfony\\Component\\VarDumper\\Caster\\DoctrineCaster', 'castCommonProxy'],\n        'Doctrine\\ORM\\Proxy\\Proxy' => ['Symfony\\Component\\VarDumper\\Caster\\DoctrineCaster', 'castOrmProxy'],\n        'Doctrine\\ORM\\PersistentCollection' => ['Symfony\\Component\\VarDumper\\Caster\\DoctrineCaster', 'castPersistentCollection'],\n        'Doctrine\\Persistence\\ObjectManager' => ['Symfony\\Component\\VarDumper\\Caster\\StubCaster', 'cutInternals'],\n\n        'DOMException' => ['Symfony\\Component\\VarDumper\\Caster\\DOMCaster', 'castException'],\n        'Dom\\Exception' => ['Symfony\\Component\\VarDumper\\Caster\\DOMCaster', 'castException'],\n        'DOMStringList' => ['Symfony\\Component\\VarDumper\\Caster\\DOMCaster', 'castDom'],\n        'DOMNameList' => ['Symfony\\Component\\VarDumper\\Caster\\DOMCaster', 'castDom'],\n        'DOMImplementation' => ['Symfony\\Component\\VarDumper\\Caster\\DOMCaster', 'castImplementation'],\n        'Dom\\Implementation' => ['Symfony\\Component\\VarDumper\\Caster\\DOMCaster', 'castImplementation'],\n        'DOMImplementationList' => ['Symfony\\Component\\VarDumper\\Caster\\DOMCaster', 'castDom'],\n        'DOMNode' => ['Symfony\\Component\\VarDumper\\Caster\\DOMCaster', 'castDom'],\n        'Dom\\Node' => ['Symfony\\Component\\VarDumper\\Caster\\DOMCaster', 'castDom'],\n        'DOMNameSpaceNode' => ['Symfony\\Component\\VarDumper\\Caster\\DOMCaster', 'castDom'],\n        'DOMDocument' => ['Symfony\\Component\\VarDumper\\Caster\\DOMCaster', 'castDocument'],\n        'Dom\\XMLDocument' => ['Symfony\\Component\\VarDumper\\Caster\\DOMCaster', 'castXMLDocument'],\n        'Dom\\HTMLDocument' => ['Symfony\\Component\\VarDumper\\Caster\\DOMCaster', 'castHTMLDocument'],\n        'DOMNodeList' => ['Symfony\\Component\\VarDumper\\Caster\\DOMCaster', 'castDom'],\n        'Dom\\NodeList' => ['Symfony\\Component\\VarDumper\\Caster\\DOMCaster', 'castDom'],\n        'DOMNamedNodeMap' => ['Symfony\\Component\\VarDumper\\Caster\\DOMCaster', 'castDom'],\n        'Dom\\DTDNamedNodeMap' => ['Symfony\\Component\\VarDumper\\Caster\\DOMCaster', 'castDom'],\n        'DOMXPath' => ['Symfony\\Component\\VarDumper\\Caster\\DOMCaster', 'castDom'],\n        'Dom\\XPath' => ['Symfony\\Component\\VarDumper\\Caster\\DOMCaster', 'castDom'],\n        'Dom\\HTMLCollection' => ['Symfony\\Component\\VarDumper\\Caster\\DOMCaster', 'castDom'],\n        'Dom\\TokenList' => ['Symfony\\Component\\VarDumper\\Caster\\DOMCaster', 'castDom'],\n\n        'XMLReader' => ['Symfony\\Component\\VarDumper\\Caster\\XmlReaderCaster', 'castXmlReader'],\n\n        'ErrorException' => ['Symfony\\Component\\VarDumper\\Caster\\ExceptionCaster', 'castErrorException'],\n        'Exception' => ['Symfony\\Component\\VarDumper\\Caster\\ExceptionCaster', 'castException'],\n        'Error' => ['Symfony\\Component\\VarDumper\\Caster\\ExceptionCaster', 'castError'],\n        'Symfony\\Bridge\\Monolog\\Logger' => ['Symfony\\Component\\VarDumper\\Caster\\StubCaster', 'cutInternals'],\n        'Symfony\\Component\\DependencyInjection\\ContainerInterface' => ['Symfony\\Component\\VarDumper\\Caster\\StubCaster', 'cutInternals'],\n        'Symfony\\Component\\EventDispatcher\\EventDispatcherInterface' => ['Symfony\\Component\\VarDumper\\Caster\\StubCaster', 'cutInternals'],\n        'Symfony\\Component\\HttpClient\\AmpHttpClient' => ['Symfony\\Component\\VarDumper\\Caster\\SymfonyCaster', 'castHttpClient'],\n        'Symfony\\Component\\HttpClient\\CurlHttpClient' => ['Symfony\\Component\\VarDumper\\Caster\\SymfonyCaster', 'castHttpClient'],\n        'Symfony\\Component\\HttpClient\\NativeHttpClient' => ['Symfony\\Component\\VarDumper\\Caster\\SymfonyCaster', 'castHttpClient'],\n        'Symfony\\Component\\HttpClient\\Response\\AmpResponse' => ['Symfony\\Component\\VarDumper\\Caster\\SymfonyCaster', 'castHttpClientResponse'],\n        'Symfony\\Component\\HttpClient\\Response\\AmpResponseV4' => ['Symfony\\Component\\VarDumper\\Caster\\SymfonyCaster', 'castHttpClientResponse'],\n        'Symfony\\Component\\HttpClient\\Response\\AmpResponseV5' => ['Symfony\\Component\\VarDumper\\Caster\\SymfonyCaster', 'castHttpClientResponse'],\n        'Symfony\\Component\\HttpClient\\Response\\CurlResponse' => ['Symfony\\Component\\VarDumper\\Caster\\SymfonyCaster', 'castHttpClientResponse'],\n        'Symfony\\Component\\HttpClient\\Response\\NativeResponse' => ['Symfony\\Component\\VarDumper\\Caster\\SymfonyCaster', 'castHttpClientResponse'],\n        'Symfony\\Component\\HttpFoundation\\Request' => ['Symfony\\Component\\VarDumper\\Caster\\SymfonyCaster', 'castRequest'],\n        'Symfony\\Component\\Uid\\Ulid' => ['Symfony\\Component\\VarDumper\\Caster\\SymfonyCaster', 'castUlid'],\n        'Symfony\\Component\\Uid\\Uuid' => ['Symfony\\Component\\VarDumper\\Caster\\SymfonyCaster', 'castUuid'],\n        'Symfony\\Component\\VarExporter\\Internal\\LazyObjectState' => ['Symfony\\Component\\VarDumper\\Caster\\SymfonyCaster', 'castLazyObjectState'],\n        'Symfony\\Component\\VarDumper\\Exception\\ThrowingCasterException' => ['Symfony\\Component\\VarDumper\\Caster\\ExceptionCaster', 'castThrowingCasterException'],\n        'Symfony\\Component\\VarDumper\\Caster\\TraceStub' => ['Symfony\\Component\\VarDumper\\Caster\\ExceptionCaster', 'castTraceStub'],\n        'Symfony\\Component\\VarDumper\\Caster\\FrameStub' => ['Symfony\\Component\\VarDumper\\Caster\\ExceptionCaster', 'castFrameStub'],\n        'Symfony\\Component\\VarDumper\\Cloner\\AbstractCloner' => ['Symfony\\Component\\VarDumper\\Caster\\StubCaster', 'cutInternals'],\n        'Symfony\\Component\\ErrorHandler\\Exception\\FlattenException' => ['Symfony\\Component\\VarDumper\\Caster\\ExceptionCaster', 'castFlattenException'],\n        'Symfony\\Component\\ErrorHandler\\Exception\\SilencedErrorContext' => ['Symfony\\Component\\VarDumper\\Caster\\ExceptionCaster', 'castSilencedErrorContext'],\n\n        'Imagine\\Image\\ImageInterface' => ['Symfony\\Component\\VarDumper\\Caster\\ImagineCaster', 'castImage'],\n\n        'Ramsey\\Uuid\\UuidInterface' => ['Symfony\\Component\\VarDumper\\Caster\\UuidCaster', 'castRamseyUuid'],\n\n        'ProxyManager\\Proxy\\ProxyInterface' => ['Symfony\\Component\\VarDumper\\Caster\\ProxyManagerCaster', 'castProxy'],\n        'PHPUnit_Framework_MockObject_MockObject' => ['Symfony\\Component\\VarDumper\\Caster\\StubCaster', 'cutInternals'],\n        'PHPUnit\\Framework\\MockObject\\MockObject' => ['Symfony\\Component\\VarDumper\\Caster\\StubCaster', 'cutInternals'],\n        'PHPUnit\\Framework\\MockObject\\Stub' => ['Symfony\\Component\\VarDumper\\Caster\\StubCaster', 'cutInternals'],\n        'Prophecy\\Prophecy\\ProphecySubjectInterface' => ['Symfony\\Component\\VarDumper\\Caster\\StubCaster', 'cutInternals'],\n        'Mockery\\MockInterface' => ['Symfony\\Component\\VarDumper\\Caster\\StubCaster', 'cutInternals'],\n\n        'PDO' => ['Symfony\\Component\\VarDumper\\Caster\\PdoCaster', 'castPdo'],\n        'PDOStatement' => ['Symfony\\Component\\VarDumper\\Caster\\PdoCaster', 'castPdoStatement'],\n\n        'AMQPConnection' => ['Symfony\\Component\\VarDumper\\Caster\\AmqpCaster', 'castConnection'],\n        'AMQPChannel' => ['Symfony\\Component\\VarDumper\\Caster\\AmqpCaster', 'castChannel'],\n        'AMQPQueue' => ['Symfony\\Component\\VarDumper\\Caster\\AmqpCaster', 'castQueue'],\n        'AMQPExchange' => ['Symfony\\Component\\VarDumper\\Caster\\AmqpCaster', 'castExchange'],\n        'AMQPEnvelope' => ['Symfony\\Component\\VarDumper\\Caster\\AmqpCaster', 'castEnvelope'],\n\n        'ArrayObject' => ['Symfony\\Component\\VarDumper\\Caster\\SplCaster', 'castArrayObject'],\n        'ArrayIterator' => ['Symfony\\Component\\VarDumper\\Caster\\SplCaster', 'castArrayIterator'],\n        'SplDoublyLinkedList' => ['Symfony\\Component\\VarDumper\\Caster\\SplCaster', 'castDoublyLinkedList'],\n        'SplFileInfo' => ['Symfony\\Component\\VarDumper\\Caster\\SplCaster', 'castFileInfo'],\n        'SplFileObject' => ['Symfony\\Component\\VarDumper\\Caster\\SplCaster', 'castFileObject'],\n        'SplHeap' => ['Symfony\\Component\\VarDumper\\Caster\\SplCaster', 'castHeap'],\n        'SplObjectStorage' => ['Symfony\\Component\\VarDumper\\Caster\\SplCaster', 'castObjectStorage'],\n        'SplPriorityQueue' => ['Symfony\\Component\\VarDumper\\Caster\\SplCaster', 'castHeap'],\n        'OuterIterator' => ['Symfony\\Component\\VarDumper\\Caster\\SplCaster', 'castOuterIterator'],\n        'WeakMap' => ['Symfony\\Component\\VarDumper\\Caster\\SplCaster', 'castWeakMap'],\n        'WeakReference' => ['Symfony\\Component\\VarDumper\\Caster\\SplCaster', 'castWeakReference'],\n\n        'Redis' => ['Symfony\\Component\\VarDumper\\Caster\\RedisCaster', 'castRedis'],\n        'Relay\\Relay' => ['Symfony\\Component\\VarDumper\\Caster\\RedisCaster', 'castRedis'],\n        'RedisArray' => ['Symfony\\Component\\VarDumper\\Caster\\RedisCaster', 'castRedisArray'],\n        'RedisCluster' => ['Symfony\\Component\\VarDumper\\Caster\\RedisCaster', 'castRedisCluster'],\n\n        'DateTimeInterface' => ['Symfony\\Component\\VarDumper\\Caster\\DateCaster', 'castDateTime'],\n        'DateInterval' => ['Symfony\\Component\\VarDumper\\Caster\\DateCaster', 'castInterval'],\n        'DateTimeZone' => ['Symfony\\Component\\VarDumper\\Caster\\DateCaster', 'castTimeZone'],\n        'DatePeriod' => ['Symfony\\Component\\VarDumper\\Caster\\DateCaster', 'castPeriod'],\n\n        'GMP' => ['Symfony\\Component\\VarDumper\\Caster\\GmpCaster', 'castGmp'],\n\n        'MessageFormatter' => ['Symfony\\Component\\VarDumper\\Caster\\IntlCaster', 'castMessageFormatter'],\n        'NumberFormatter' => ['Symfony\\Component\\VarDumper\\Caster\\IntlCaster', 'castNumberFormatter'],\n        'IntlTimeZone' => ['Symfony\\Component\\VarDumper\\Caster\\IntlCaster', 'castIntlTimeZone'],\n        'IntlCalendar' => ['Symfony\\Component\\VarDumper\\Caster\\IntlCaster', 'castIntlCalendar'],\n        'IntlDateFormatter' => ['Symfony\\Component\\VarDumper\\Caster\\IntlCaster', 'castIntlDateFormatter'],\n\n        'Memcached' => ['Symfony\\Component\\VarDumper\\Caster\\MemcachedCaster', 'castMemcached'],\n\n        'Ds\\Collection' => ['Symfony\\Component\\VarDumper\\Caster\\DsCaster', 'castCollection'],\n        'Ds\\Map' => ['Symfony\\Component\\VarDumper\\Caster\\DsCaster', 'castMap'],\n        'Ds\\Pair' => ['Symfony\\Component\\VarDumper\\Caster\\DsCaster', 'castPair'],\n        'Symfony\\Component\\VarDumper\\Caster\\DsPairStub' => ['Symfony\\Component\\VarDumper\\Caster\\DsCaster', 'castPairStub'],\n\n        'mysqli_driver' => ['Symfony\\Component\\VarDumper\\Caster\\MysqliCaster', 'castMysqliDriver'],\n\n        'CurlHandle' => ['Symfony\\Component\\VarDumper\\Caster\\CurlCaster', 'castCurl'],\n\n        'Dba\\Connection' => ['Symfony\\Component\\VarDumper\\Caster\\ResourceCaster', 'castDba'],\n\n        'GdImage' => ['Symfony\\Component\\VarDumper\\Caster\\GdCaster', 'castGd'],\n\n        'SQLite3Result' => ['Symfony\\Component\\VarDumper\\Caster\\SqliteCaster', 'castSqlite3Result'],\n\n        'PgSql\\Lob' => ['Symfony\\Component\\VarDumper\\Caster\\PgSqlCaster', 'castLargeObject'],\n        'PgSql\\Connection' => ['Symfony\\Component\\VarDumper\\Caster\\PgSqlCaster', 'castLink'],\n        'PgSql\\Result' => ['Symfony\\Component\\VarDumper\\Caster\\PgSqlCaster', 'castResult'],\n\n        ':process' => ['Symfony\\Component\\VarDumper\\Caster\\ResourceCaster', 'castProcess'],\n        ':stream' => ['Symfony\\Component\\VarDumper\\Caster\\ResourceCaster', 'castStream'],\n\n        'OpenSSLAsymmetricKey' => ['Symfony\\Component\\VarDumper\\Caster\\OpenSSLCaster', 'castOpensslAsymmetricKey'],\n        'OpenSSLCertificateSigningRequest' => ['Symfony\\Component\\VarDumper\\Caster\\OpenSSLCaster', 'castOpensslCsr'],\n        'OpenSSLCertificate' => ['Symfony\\Component\\VarDumper\\Caster\\OpenSSLCaster', 'castOpensslX509'],\n\n        ':persistent stream' => ['Symfony\\Component\\VarDumper\\Caster\\ResourceCaster', 'castStream'],\n        ':stream-context' => ['Symfony\\Component\\VarDumper\\Caster\\ResourceCaster', 'castStreamContext'],\n\n        'XmlParser' => ['Symfony\\Component\\VarDumper\\Caster\\XmlResourceCaster', 'castXml'],\n\n        'RdKafka' => ['Symfony\\Component\\VarDumper\\Caster\\RdKafkaCaster', 'castRdKafka'],\n        'RdKafka\\Conf' => ['Symfony\\Component\\VarDumper\\Caster\\RdKafkaCaster', 'castConf'],\n        'RdKafka\\KafkaConsumer' => ['Symfony\\Component\\VarDumper\\Caster\\RdKafkaCaster', 'castKafkaConsumer'],\n        'RdKafka\\Metadata\\Broker' => ['Symfony\\Component\\VarDumper\\Caster\\RdKafkaCaster', 'castBrokerMetadata'],\n        'RdKafka\\Metadata\\Collection' => ['Symfony\\Component\\VarDumper\\Caster\\RdKafkaCaster', 'castCollectionMetadata'],\n        'RdKafka\\Metadata\\Partition' => ['Symfony\\Component\\VarDumper\\Caster\\RdKafkaCaster', 'castPartitionMetadata'],\n        'RdKafka\\Metadata\\Topic' => ['Symfony\\Component\\VarDumper\\Caster\\RdKafkaCaster', 'castTopicMetadata'],\n        'RdKafka\\Message' => ['Symfony\\Component\\VarDumper\\Caster\\RdKafkaCaster', 'castMessage'],\n        'RdKafka\\Topic' => ['Symfony\\Component\\VarDumper\\Caster\\RdKafkaCaster', 'castTopic'],\n        'RdKafka\\TopicPartition' => ['Symfony\\Component\\VarDumper\\Caster\\RdKafkaCaster', 'castTopicPartition'],\n        'RdKafka\\TopicConf' => ['Symfony\\Component\\VarDumper\\Caster\\RdKafkaCaster', 'castTopicConf'],\n\n        'FFI\\CData' => ['Symfony\\Component\\VarDumper\\Caster\\FFICaster', 'castCTypeOrCData'],\n        'FFI\\CType' => ['Symfony\\Component\\VarDumper\\Caster\\FFICaster', 'castCTypeOrCData'],\n    ];\n\n    protected int $maxItems = 2500;\n    protected int $maxString = -1;\n    protected int $minDepth = 1;\n\n    /**\n     * @var array<string, list<callable>>\n     */\n    private array $casters = [];\n\n    /**\n     * @var callable|null\n     */\n    private $prevErrorHandler;\n\n    private array $classInfo = [];\n    private int $filter = 0;\n\n    /**\n     * @param callable[]|null $casters A map of casters\n     *\n     * @see addCasters\n     */\n    public function __construct(?array $casters = null)\n    {\n        $this->addCasters($casters ?? static::$defaultCasters);\n    }\n\n    /**\n     * Adds casters for resources and objects.\n     *\n     * Maps resources or object types to a callback.\n     * Use types as keys and callable casters as values.\n     * Prefix types with `::`,\n     * see e.g. self::$defaultCasters.\n     *\n     * @param array<string, callable> $casters A map of casters\n     */\n    public function addCasters(array $casters): void\n    {\n        foreach ($casters as $type => $callback) {\n            $this->casters[$type][] = $callback;\n        }\n    }\n\n    /**\n     * Adds default casters for resources and objects.\n     *\n     * Maps resources or object types to a callback.\n     * Use types as keys and callable casters as values.\n     * Prefix types with `::`,\n     * see e.g. self::$defaultCasters.\n     *\n     * @param array<string, callable> $casters A map of casters\n     */\n    public static function addDefaultCasters(array $casters): void\n    {\n        self::$defaultCasters = [...self::$defaultCasters, ...$casters];\n    }\n\n    /**\n     * Sets the maximum number of items to clone past the minimum depth in nested structures.\n     */\n    public function setMaxItems(int $maxItems): void\n    {\n        $this->maxItems = $maxItems;\n    }\n\n    /**\n     * Sets the maximum cloned length for strings.\n     */\n    public function setMaxString(int $maxString): void\n    {\n        $this->maxString = $maxString;\n    }\n\n    /**\n     * Sets the minimum tree depth where we are guaranteed to clone all the items.  After this\n     * depth is reached, only setMaxItems items will be cloned.\n     */\n    public function setMinDepth(int $minDepth): void\n    {\n        $this->minDepth = $minDepth;\n    }\n\n    /**\n     * Clones a PHP variable.\n     *\n     * @param int $filter A bit field of Caster::EXCLUDE_* constants\n     */\n    public function cloneVar(mixed $var, int $filter = 0): Data\n    {\n        $this->prevErrorHandler = set_error_handler(function ($type, $msg, $file, $line, $context = []) {\n            if (\\E_RECOVERABLE_ERROR === $type || \\E_USER_ERROR === $type) {\n                // Cloner never dies\n                throw new \\ErrorException($msg, 0, $type, $file, $line);\n            }\n\n            if ($this->prevErrorHandler) {\n                return ($this->prevErrorHandler)($type, $msg, $file, $line, $context);\n            }\n\n            return false;\n        });\n        $this->filter = $filter;\n\n        if ($gc = gc_enabled()) {\n            gc_disable();\n        }\n        try {\n            return new Data($this->doClone($var));\n        } finally {\n            if ($gc) {\n                gc_enable();\n            }\n            restore_error_handler();\n            $this->prevErrorHandler = null;\n        }\n    }\n\n    /**\n     * Effectively clones the PHP variable.\n     */\n    abstract protected function doClone(mixed $var): array;\n\n    /**\n     * Casts an object to an array representation.\n     *\n     * @param bool $isNested True if the object is nested in the dumped structure\n     */\n    protected function castObject(Stub $stub, bool $isNested): array\n    {\n        $obj = $stub->value;\n        $class = $stub->class;\n\n        if (str_contains($class, \"@anonymous\\0\")) {\n            $stub->class = get_debug_type($obj);\n        }\n        if (isset($this->classInfo[$class])) {\n            [$i, $parents, $hasDebugInfo, $fileInfo] = $this->classInfo[$class];\n        } else {\n            $i = 2;\n            $parents = [$class];\n            $hasDebugInfo = method_exists($class, '__debugInfo');\n\n            foreach (class_parents($class) as $p) {\n                $parents[] = $p;\n                ++$i;\n            }\n            foreach (class_implements($class) as $p) {\n                $parents[] = $p;\n                ++$i;\n            }\n            $parents[] = '*';\n\n            $r = new \\ReflectionClass($class);\n            $fileInfo = $r->isInternal() || $r->isSubclassOf(Stub::class) ? [] : [\n                'file' => $r->getFileName(),\n                'line' => $r->getStartLine(),\n            ];\n\n            $this->classInfo[$class] = [$i, $parents, $hasDebugInfo, $fileInfo];\n        }\n\n        $stub->attr += $fileInfo;\n        $a = Caster::castObject($obj, $class, $hasDebugInfo, $stub->class);\n\n        try {\n            while ($i--) {\n                if (!empty($this->casters[$p = $parents[$i]])) {\n                    foreach ($this->casters[$p] as $callback) {\n                        $a = $callback($obj, $a, $stub, $isNested, $this->filter);\n                    }\n                }\n            }\n        } catch (\\Exception $e) {\n            $a = [(Stub::TYPE_OBJECT === $stub->type ? Caster::PREFIX_VIRTUAL : '').'⚠' => new ThrowingCasterException($e)] + $a;\n        }\n\n        return $a;\n    }\n\n    /**\n     * Casts a resource to an array representation.\n     *\n     * @param bool $isNested True if the object is nested in the dumped structure\n     */\n    protected function castResource(Stub $stub, bool $isNested): array\n    {\n        $a = [];\n        $res = $stub->value;\n        $type = $stub->class;\n\n        try {\n            if (!empty($this->casters[':'.$type])) {\n                foreach ($this->casters[':'.$type] as $callback) {\n                    $a = $callback($res, $a, $stub, $isNested, $this->filter);\n                }\n            }\n        } catch (\\Exception $e) {\n            $a = [(Stub::TYPE_OBJECT === $stub->type ? Caster::PREFIX_VIRTUAL : '').'⚠' => new ThrowingCasterException($e)] + $a;\n        }\n\n        return $a;\n    }\n}\n"
  },
  {
    "path": "Cloner/ClonerInterface.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Cloner;\n\n/**\n * @author Nicolas Grekas <p@tchwork.com>\n */\ninterface ClonerInterface\n{\n    /**\n     * Clones a PHP variable.\n     */\n    public function cloneVar(mixed $var): Data;\n}\n"
  },
  {
    "path": "Cloner/Cursor.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Cloner;\n\n/**\n * Represents the current state of a dumper while dumping.\n *\n * @author Nicolas Grekas <p@tchwork.com>\n */\nclass Cursor\n{\n    public const HASH_INDEXED = Stub::ARRAY_INDEXED;\n    public const HASH_ASSOC = Stub::ARRAY_ASSOC;\n    public const HASH_OBJECT = Stub::TYPE_OBJECT;\n    public const HASH_RESOURCE = Stub::TYPE_RESOURCE;\n\n    public int $depth = 0;\n    public int $refIndex = 0;\n    public int $softRefTo = 0;\n    public int $softRefCount = 0;\n    public int $softRefHandle = 0;\n    public int $hardRefTo = 0;\n    public int $hardRefCount = 0;\n    public int $hardRefHandle = 0;\n    public int $hashType;\n    public string|int|null $hashKey = null;\n    public bool $hashKeyIsBinary;\n    public int $hashIndex = 0;\n    public int $hashLength = 0;\n    public int $hashCut = 0;\n    public bool $stop = false;\n    public array $attr = [];\n    public bool $skipChildren = false;\n}\n"
  },
  {
    "path": "Cloner/Data.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Cloner;\n\nuse Symfony\\Component\\VarDumper\\Caster\\Caster;\nuse Symfony\\Component\\VarDumper\\Dumper\\ContextProvider\\SourceContextProvider;\n\n/**\n * @author Nicolas Grekas <p@tchwork.com>\n */\nclass Data implements \\ArrayAccess, \\Countable, \\IteratorAggregate, \\Stringable\n{\n    private array $data;\n    private int $position = 0;\n    private int|string $key = 0;\n    private int $maxDepth = 20;\n    private int $maxItemsPerDepth = -1;\n    private int $useRefHandles = -1;\n    private array $context = [];\n\n    /**\n     * @param array $data An array as returned by ClonerInterface::cloneVar()\n     */\n    public function __construct(array $data)\n    {\n        $this->data = $data;\n    }\n\n    public function getType(): ?string\n    {\n        $item = $this->data[$this->position][$this->key];\n\n        if ($item instanceof Stub && Stub::TYPE_REF === $item->type && !$item->position) {\n            $item = $item->value;\n        }\n        if (!$item instanceof Stub) {\n            return \\gettype($item);\n        }\n        if (Stub::TYPE_STRING === $item->type) {\n            return 'string';\n        }\n        if (Stub::TYPE_ARRAY === $item->type) {\n            return 'array';\n        }\n        if (Stub::TYPE_OBJECT === $item->type) {\n            return $item->class;\n        }\n        if (Stub::TYPE_RESOURCE === $item->type) {\n            return $item->class.' resource';\n        }\n\n        return null;\n    }\n\n    /**\n     * Returns a native representation of the original value.\n     *\n     * @param array|bool $recursive Whether values should be resolved recursively or not\n     *\n     * @return string|int|float|bool|array|Data[]|null\n     */\n    public function getValue(array|bool $recursive = false): string|int|float|bool|array|null\n    {\n        $item = $this->data[$this->position][$this->key];\n\n        if ($item instanceof Stub && Stub::TYPE_REF === $item->type && !$item->position) {\n            $item = $item->value;\n        }\n        if (!($item = $this->getStub($item)) instanceof Stub) {\n            return $item;\n        }\n        if (Stub::TYPE_STRING === $item->type) {\n            return $item->value;\n        }\n\n        $children = $item->position ? $this->data[$item->position] : [];\n\n        foreach ($children as $k => $v) {\n            if ($recursive && !($v = $this->getStub($v)) instanceof Stub) {\n                continue;\n            }\n            $children[$k] = clone $this;\n            $children[$k]->key = $k;\n            $children[$k]->position = $item->position;\n\n            if ($recursive) {\n                if (Stub::TYPE_REF === $v->type && ($v = $this->getStub($v->value)) instanceof Stub) {\n                    $recursive = (array) $recursive;\n                    if (isset($recursive[$v->position])) {\n                        continue;\n                    }\n                    $recursive[$v->position] = true;\n                }\n                $children[$k] = $children[$k]->getValue($recursive);\n            }\n        }\n\n        return $children;\n    }\n\n    public function count(): int\n    {\n        return \\count($this->getValue());\n    }\n\n    public function getIterator(): \\Traversable\n    {\n        if (!\\is_array($value = $this->getValue())) {\n            throw new \\LogicException(\\sprintf('\"%s\" object holds non-iterable type \"%s\".', self::class, get_debug_type($value)));\n        }\n\n        yield from $value;\n    }\n\n    public function __get(string $key): mixed\n    {\n        if (null !== $data = $this->seek($key)) {\n            $item = $this->getStub($data->data[$data->position][$data->key]);\n\n            return $item instanceof Stub || [] === $item ? $data : $item;\n        }\n\n        return null;\n    }\n\n    public function __isset(string $key): bool\n    {\n        return null !== $this->seek($key);\n    }\n\n    public function offsetExists(mixed $key): bool\n    {\n        return $this->__isset($key);\n    }\n\n    public function offsetGet(mixed $key): mixed\n    {\n        return $this->__get($key);\n    }\n\n    public function offsetSet(mixed $key, mixed $value): void\n    {\n        throw new \\BadMethodCallException(self::class.' objects are immutable.');\n    }\n\n    public function offsetUnset(mixed $key): void\n    {\n        throw new \\BadMethodCallException(self::class.' objects are immutable.');\n    }\n\n    public function __toString(): string\n    {\n        $value = $this->getValue();\n\n        if (!\\is_array($value)) {\n            return (string) $value;\n        }\n\n        return \\sprintf('%s (count=%d)', $this->getType(), \\count($value));\n    }\n\n    /**\n     * Returns a depth limited clone of $this.\n     */\n    public function withMaxDepth(int $maxDepth): static\n    {\n        $data = clone $this;\n        $data->maxDepth = $maxDepth;\n\n        return $data;\n    }\n\n    /**\n     * Limits the number of elements per depth level.\n     */\n    public function withMaxItemsPerDepth(int $maxItemsPerDepth): static\n    {\n        $data = clone $this;\n        $data->maxItemsPerDepth = $maxItemsPerDepth;\n\n        return $data;\n    }\n\n    /**\n     * Enables/disables objects' identifiers tracking.\n     *\n     * @param bool $useRefHandles False to hide global ref. handles\n     */\n    public function withRefHandles(bool $useRefHandles): static\n    {\n        $data = clone $this;\n        $data->useRefHandles = $useRefHandles ? -1 : 0;\n\n        return $data;\n    }\n\n    public function withContext(array $context): static\n    {\n        $data = clone $this;\n        $data->context = $context;\n\n        return $data;\n    }\n\n    public function getContext(): array\n    {\n        return $this->context;\n    }\n\n    /**\n     * Seeks to a specific key in nested data structures.\n     */\n    public function seek(string|int $key): ?static\n    {\n        $item = $this->data[$this->position][$this->key];\n\n        if ($item instanceof Stub && Stub::TYPE_REF === $item->type && !$item->position) {\n            $item = $item->value;\n        }\n        if (!($item = $this->getStub($item)) instanceof Stub || !$item->position) {\n            return null;\n        }\n        $keys = [$key];\n\n        switch ($item->type) {\n            case Stub::TYPE_OBJECT:\n                $keys[] = Caster::PREFIX_DYNAMIC.$key;\n                $keys[] = Caster::PREFIX_PROTECTED.$key;\n                $keys[] = Caster::PREFIX_VIRTUAL.$key;\n                $keys[] = \"\\0$item->class\\0$key\";\n                // no break\n            case Stub::TYPE_ARRAY:\n            case Stub::TYPE_RESOURCE:\n                break;\n            default:\n                return null;\n        }\n\n        $data = null;\n        $children = $this->data[$item->position];\n\n        foreach ($keys as $key) {\n            if (isset($children[$key]) || \\array_key_exists($key, $children)) {\n                $data = clone $this;\n                $data->key = $key;\n                $data->position = $item->position;\n                break;\n            }\n        }\n\n        return $data;\n    }\n\n    /**\n     * Dumps data with a DumperInterface dumper.\n     */\n    public function dump(DumperInterface $dumper): void\n    {\n        $refs = [0];\n        $cursor = new Cursor();\n        $cursor->hashType = -1;\n        $cursor->attr = $this->context[SourceContextProvider::class] ?? [];\n        $label = $this->context['label'] ?? '';\n\n        if ($cursor->attr || '' !== $label) {\n            $dumper->dumpScalar($cursor, 'label', $label);\n        }\n        $cursor->hashType = 0;\n        $this->dumpItem($dumper, $cursor, $refs, $this->data[$this->position][$this->key]);\n    }\n\n    /**\n     * Depth-first dumping of items.\n     *\n     * @param mixed $item A Stub object or the original value being dumped\n     */\n    private function dumpItem(DumperInterface $dumper, Cursor $cursor, array &$refs, mixed $item): void\n    {\n        $cursor->refIndex = 0;\n        $cursor->softRefTo = $cursor->softRefHandle = $cursor->softRefCount = 0;\n        $cursor->hardRefTo = $cursor->hardRefHandle = $cursor->hardRefCount = 0;\n        $firstSeen = true;\n\n        if (!$item instanceof Stub) {\n            $cursor->attr = [];\n            $type = \\gettype($item);\n            if ('array' === $type && $item) {\n                $item = $this->getStub($item);\n            }\n        } elseif (Stub::TYPE_REF === $item->type) {\n            if ($item->handle) {\n                if (!isset($refs[$r = $item->handle - (\\PHP_INT_MAX >> 1)])) {\n                    $cursor->refIndex = $refs[$r] = $cursor->refIndex ?: ++$refs[0];\n                } else {\n                    $firstSeen = false;\n                }\n                $cursor->hardRefTo = $refs[$r];\n                $cursor->hardRefHandle = $this->useRefHandles & $item->handle;\n                $cursor->hardRefCount = 0 < $item->handle ? $item->refCount : 0;\n            }\n            $cursor->attr = $item->attr;\n            $type = $item->class ?: \\gettype($item->value);\n            $item = $this->getStub($item->value);\n        }\n        if ($item instanceof Stub) {\n            if ($item->refCount) {\n                if (!isset($refs[$r = $item->handle])) {\n                    $cursor->refIndex = $refs[$r] = $cursor->refIndex ?: ++$refs[0];\n                } else {\n                    $firstSeen = false;\n                }\n                $cursor->softRefTo = $refs[$r];\n            }\n            $cursor->softRefHandle = $this->useRefHandles & $item->handle;\n            $cursor->softRefCount = $item->refCount;\n            $cursor->attr = $item->attr;\n            $cut = $item->cut;\n\n            if ($item->position && $firstSeen) {\n                $children = $this->data[$item->position];\n\n                if ($cursor->stop) {\n                    if ($cut >= 0) {\n                        $cut += \\count($children);\n                    }\n                    $children = [];\n                }\n            } else {\n                $children = [];\n            }\n            switch ($item->type) {\n                case Stub::TYPE_STRING:\n                    $dumper->dumpString($cursor, $item->value, Stub::STRING_BINARY === $item->class, $cut);\n                    break;\n\n                case Stub::TYPE_ARRAY:\n                    $item = clone $item;\n                    $item->type = $item->class;\n                    $item->class = $item->value;\n                    // no break\n                case Stub::TYPE_OBJECT:\n                case Stub::TYPE_RESOURCE:\n                    $withChildren = $children && $cursor->depth !== $this->maxDepth && $this->maxItemsPerDepth;\n                    $dumper->enterHash($cursor, $item->type, $item->class, $withChildren);\n                    if ($withChildren) {\n                        if ($cursor->skipChildren) {\n                            $withChildren = false;\n                            $cut = -1;\n                        } else {\n                            $cut = $this->dumpChildren($dumper, $cursor, $refs, $children, $cut, $item->type, null !== $item->class);\n                        }\n                    } elseif ($children && 0 <= $cut) {\n                        $cut += \\count($children);\n                    }\n                    $cursor->skipChildren = false;\n                    $dumper->leaveHash($cursor, $item->type, $item->class, $withChildren, $cut);\n                    break;\n\n                case Stub::TYPE_SCALAR:\n                    $dumper->dumpScalar($cursor, 'default', $item->attr['value']);\n                    break;\n\n                default:\n                    throw new \\RuntimeException(\\sprintf('Unexpected Stub type: \"%s\".', $item->type));\n            }\n        } elseif ('array' === $type) {\n            $dumper->enterHash($cursor, Cursor::HASH_INDEXED, 0, false);\n            $dumper->leaveHash($cursor, Cursor::HASH_INDEXED, 0, false, 0);\n        } elseif ('string' === $type) {\n            $dumper->dumpString($cursor, $item, false, 0);\n        } else {\n            $dumper->dumpScalar($cursor, $type, $item);\n        }\n    }\n\n    /**\n     * Dumps children of hash structures.\n     *\n     * @return int The final number of removed items\n     */\n    private function dumpChildren(DumperInterface $dumper, Cursor $parentCursor, array &$refs, array $children, int $hashCut, int $hashType, bool $dumpKeys): int\n    {\n        $cursor = clone $parentCursor;\n        ++$cursor->depth;\n        $cursor->hashType = $hashType;\n        $cursor->hashIndex = 0;\n        $cursor->hashLength = \\count($children);\n        $cursor->hashCut = $hashCut;\n        foreach ($children as $key => $child) {\n            $cursor->hashKeyIsBinary = isset($key[0]) && !preg_match('//u', $key);\n            $cursor->hashKey = $dumpKeys ? $key : null;\n            $this->dumpItem($dumper, $cursor, $refs, $child);\n            if (++$cursor->hashIndex === $this->maxItemsPerDepth || $cursor->stop) {\n                $parentCursor->stop = true;\n\n                return $hashCut >= 0 ? $hashCut + $cursor->hashLength - $cursor->hashIndex : $hashCut;\n            }\n        }\n\n        return $hashCut;\n    }\n\n    private function getStub(mixed $item): mixed\n    {\n        if (!$item || !\\is_array($item)) {\n            return $item;\n        }\n\n        $stub = new Stub();\n        $stub->type = Stub::TYPE_ARRAY;\n        foreach ($item as $stub->class => $stub->position) {\n        }\n        if (isset($item[0])) {\n            $stub->cut = $item[0];\n        }\n        $stub->value = $stub->cut + ($stub->position ? \\count($this->data[$stub->position]) : 0);\n\n        return $stub;\n    }\n}\n"
  },
  {
    "path": "Cloner/DumperInterface.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Cloner;\n\n/**\n * DumperInterface used by Data objects.\n *\n * @author Nicolas Grekas <p@tchwork.com>\n */\ninterface DumperInterface\n{\n    /**\n     * Dumps a scalar value.\n     */\n    public function dumpScalar(Cursor $cursor, string $type, string|int|float|bool|null $value): void;\n\n    /**\n     * Dumps a string.\n     *\n     * @param string $str The string being dumped\n     * @param bool   $bin Whether $str is UTF-8 or binary encoded\n     * @param int    $cut The number of characters $str has been cut by\n     */\n    public function dumpString(Cursor $cursor, string $str, bool $bin, int $cut): void;\n\n    /**\n     * Dumps while entering an hash.\n     *\n     * @param int             $type     A Cursor::HASH_* const for the type of hash\n     * @param string|int|null $class    The object class, resource type or array count\n     * @param bool            $hasChild When the dump of the hash has child item\n     */\n    public function enterHash(Cursor $cursor, int $type, string|int|null $class, bool $hasChild): void;\n\n    /**\n     * Dumps while leaving an hash.\n     *\n     * @param int             $type     A Cursor::HASH_* const for the type of hash\n     * @param string|int|null $class    The object class, resource type or array count\n     * @param bool            $hasChild When the dump of the hash has child item\n     * @param int             $cut      The number of items the hash has been cut by\n     */\n    public function leaveHash(Cursor $cursor, int $type, string|int|null $class, bool $hasChild, int $cut): void;\n}\n"
  },
  {
    "path": "Cloner/Stub.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Cloner;\n\n/**\n * Represents the main properties of a PHP variable.\n *\n * @author Nicolas Grekas <p@tchwork.com>\n */\nclass Stub\n{\n    public const TYPE_REF = 1;\n    public const TYPE_STRING = 2;\n    public const TYPE_ARRAY = 3;\n    public const TYPE_OBJECT = 4;\n    public const TYPE_RESOURCE = 5;\n    public const TYPE_SCALAR = 6;\n\n    public const STRING_BINARY = 1;\n    public const STRING_UTF8 = 2;\n\n    public const ARRAY_ASSOC = 1;\n    public const ARRAY_INDEXED = 2;\n\n    public int $type = self::TYPE_REF;\n    public string|int|null $class = '';\n    public mixed $value = null;\n    public int $cut = 0;\n    public int $handle = 0;\n    public int $refCount = 0;\n    public int $position = 0;\n    public array $attr = [];\n\n    /**\n     * @internal\n     */\n    protected static array $propertyDefaults = [];\n\n    public function __serialize(): array\n    {\n        static $noDefault = new \\stdClass();\n\n        if (self::class === static::class) {\n            $data = [];\n            foreach ($this as $k => $v) {\n                $default = self::$propertyDefaults[$this::class][$k] ??= ($p = new \\ReflectionProperty($this, $k))->hasDefaultValue() ? $p->getDefaultValue() : ($p->hasType() ? $noDefault : null);\n                if ($noDefault === $default || $default !== $v) {\n                    $data[$k] = $v;\n                }\n            }\n\n            return $data;\n        }\n\n        return \\Closure::bind(function () use ($noDefault) {\n            $data = [];\n            foreach ($this as $k => $v) {\n                $default = self::$propertyDefaults[$this::class][$k] ??= ($p = new \\ReflectionProperty($this, $k))->hasDefaultValue() ? $p->getDefaultValue() : ($p->hasType() ? $noDefault : null);\n                if ($noDefault === $default || $default !== $v) {\n                    $data[$k] = $v;\n                }\n            }\n\n            return $data;\n        }, $this, $this::class)();\n    }\n}\n"
  },
  {
    "path": "Cloner/VarCloner.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Cloner;\n\n/**\n * @author Nicolas Grekas <p@tchwork.com>\n */\nclass VarCloner extends AbstractCloner\n{\n    private static array $arrayCache = [];\n\n    protected function doClone(mixed $var): array\n    {\n        $len = 1;                       // Length of $queue\n        $pos = 0;                       // Number of cloned items past the minimum depth\n        $refsCounter = 0;               // Hard references counter\n        $queue = [[$var]];              // This breadth-first queue is the return value\n        $hardRefs = [];                 // Map of original zval ids to stub objects\n        $objRefs = [];                  // Map of original object handles to their stub object counterpart\n        $objects = [];                  // Keep a ref to objects to ensure their handle cannot be reused while cloning\n        $resRefs = [];                  // Map of original resource handles to their stub object counterpart\n        $maxItems = $this->maxItems;\n        $maxString = $this->maxString;\n        $minDepth = $this->minDepth;\n        $currentDepth = 0;              // Current tree depth\n        $currentDepthFinalIndex = 0;    // Final $queue index for current tree depth\n        $minimumDepthReached = 0 === $minDepth; // Becomes true when minimum tree depth has been reached\n        $a = null;                      // Array cast for nested structures\n        $stub = null;                   // Stub capturing the main properties of an original item value\n                                        // or null if the original value is used directly\n\n        $arrayStub = new Stub();\n        $arrayStub->type = Stub::TYPE_ARRAY;\n\n        for ($i = 0; $i < $len; ++$i) {\n            // Detect when we move on to the next tree depth\n            if ($i > $currentDepthFinalIndex) {\n                ++$currentDepth;\n                $currentDepthFinalIndex = $len - 1;\n                if ($currentDepth >= $minDepth) {\n                    $minimumDepthReached = true;\n                }\n            }\n\n            $vals = $queue[$i];\n            foreach ($vals as $k => $v) {\n                // $v is the original value or a stub object in case of hard references\n\n                $zvalRef = ($r = \\ReflectionReference::fromArrayElement($vals, $k)) ? $r->getId() : null;\n\n                if ($zvalRef) {\n                    $vals[$k] = &$stub;         // Break hard references to make $queue completely\n                    unset($stub);               // independent from the original structure\n                    if (null !== $vals[$k] = $hardRefs[$zvalRef] ?? null) {\n                        $v = $vals[$k];\n                        if ($v->value instanceof Stub && (Stub::TYPE_OBJECT === $v->value->type || Stub::TYPE_RESOURCE === $v->value->type)) {\n                            ++$v->value->refCount;\n                        }\n                        ++$v->refCount;\n                        continue;\n                    }\n                    $vals[$k] = new Stub();\n                    $vals[$k]->value = $v;\n                    $vals[$k]->handle = ++$refsCounter;\n                    $hardRefs[$zvalRef] = $vals[$k];\n                }\n                // Create $stub when the original value $v cannot be used directly\n                // If $v is a nested structure, put that structure in array $a\n                switch (true) {\n                    case null === $v:\n                    case \\is_bool($v):\n                    case \\is_int($v):\n                    case \\is_float($v):\n                        continue 2;\n                    case \\is_string($v):\n                        if ('' === $v) {\n                            continue 2;\n                        }\n                        if (!preg_match('//u', $v)) {\n                            $stub = new Stub();\n                            $stub->type = Stub::TYPE_STRING;\n                            $stub->class = Stub::STRING_BINARY;\n                            if (0 <= $maxString && 0 < $cut = \\strlen($v) - $maxString) {\n                                $stub->cut = $cut;\n                                $stub->value = substr($v, 0, -$cut);\n                            } else {\n                                $stub->value = $v;\n                            }\n                        } elseif (0 <= $maxString && isset($v[1 + ($maxString >> 2)]) && 0 < $cut = mb_strlen($v, 'UTF-8') - $maxString) {\n                            $stub = new Stub();\n                            $stub->type = Stub::TYPE_STRING;\n                            $stub->class = Stub::STRING_UTF8;\n                            $stub->cut = $cut;\n                            $stub->value = mb_substr($v, 0, $maxString, 'UTF-8');\n                        } else {\n                            continue 2;\n                        }\n                        $a = null;\n                        break;\n\n                    case \\is_array($v):\n                        if (!$v) {\n                            continue 2;\n                        }\n                        $stub = $arrayStub;\n\n                        $stub->class = array_is_list($v) ? Stub::ARRAY_INDEXED : Stub::ARRAY_ASSOC;\n                        $a = $v;\n                        break;\n\n                    case \\is_object($v):\n                        if (empty($objRefs[$h = spl_object_id($v)])) {\n                            $stub = new Stub();\n                            $stub->type = Stub::TYPE_OBJECT;\n                            $stub->class = $v::class;\n                            $stub->value = $v;\n                            $stub->handle = $h;\n                            $a = $this->castObject($stub, 0 < $i);\n                            if ($v !== $stub->value) {\n                                if (Stub::TYPE_OBJECT !== $stub->type || null === $stub->value) {\n                                    break;\n                                }\n                                $stub->handle = $h = spl_object_id($stub->value);\n                            }\n                            $stub->value = null;\n                            if (0 <= $maxItems && $maxItems <= $pos && $minimumDepthReached) {\n                                $stub->cut = \\count($a);\n                                $a = null;\n                            }\n                        }\n                        if (empty($objRefs[$h])) {\n                            $objRefs[$h] = $stub;\n                            $objects[] = $v;\n                        } else {\n                            $stub = $objRefs[$h];\n                            ++$stub->refCount;\n                            $a = null;\n                        }\n                        break;\n\n                    default: // resource\n                        if (empty($resRefs[$h = (int) $v])) {\n                            $stub = new Stub();\n                            $stub->type = Stub::TYPE_RESOURCE;\n                            if ('Unknown' === $stub->class = @get_resource_type($v)) {\n                                $stub->class = 'Closed';\n                            }\n                            $stub->value = $v;\n                            $stub->handle = $h;\n                            $a = $this->castResource($stub, 0 < $i);\n                            $stub->value = null;\n                            if (0 <= $maxItems && $maxItems <= $pos && $minimumDepthReached) {\n                                $stub->cut = \\count($a);\n                                $a = null;\n                            }\n                        }\n                        if (empty($resRefs[$h])) {\n                            $resRefs[$h] = $stub;\n                        } else {\n                            $stub = $resRefs[$h];\n                            ++$stub->refCount;\n                            $a = null;\n                        }\n                        break;\n                }\n\n                if ($a) {\n                    if (!$minimumDepthReached || 0 > $maxItems) {\n                        $queue[$len] = $a;\n                        $stub->position = $len++;\n                    } elseif ($pos < $maxItems) {\n                        if ($maxItems < $pos += \\count($a)) {\n                            $a = \\array_slice($a, 0, $maxItems - $pos, true);\n                            if ($stub->cut >= 0) {\n                                $stub->cut += $pos - $maxItems;\n                            }\n                        }\n                        $queue[$len] = $a;\n                        $stub->position = $len++;\n                    } elseif ($stub->cut >= 0) {\n                        $stub->cut += \\count($a);\n                        $stub->position = 0;\n                    }\n                }\n\n                if ($arrayStub === $stub) {\n                    if ($arrayStub->cut) {\n                        $stub = [$arrayStub->cut, $arrayStub->class => $arrayStub->position];\n                        $arrayStub->cut = 0;\n                    } elseif (isset(self::$arrayCache[$arrayStub->class][$arrayStub->position])) {\n                        $stub = self::$arrayCache[$arrayStub->class][$arrayStub->position];\n                    } else {\n                        self::$arrayCache[$arrayStub->class][$arrayStub->position] = $stub = [$arrayStub->class => $arrayStub->position];\n                    }\n                }\n\n                if (!$zvalRef) {\n                    $vals[$k] = $stub;\n                } else {\n                    $hardRefs[$zvalRef]->value = $stub;\n                }\n            }\n\n            $queue[$i] = $vals;\n        }\n\n        return $queue;\n    }\n}\n"
  },
  {
    "path": "Command/Descriptor/CliDescriptor.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Command\\Descriptor;\n\nuse Symfony\\Component\\Console\\Input\\ArrayInput;\nuse Symfony\\Component\\Console\\Output\\OutputInterface;\nuse Symfony\\Component\\Console\\Style\\SymfonyStyle;\nuse Symfony\\Component\\VarDumper\\Cloner\\Data;\nuse Symfony\\Component\\VarDumper\\Dumper\\CliDumper;\n\n/**\n * Describe collected data clones for cli output.\n *\n * @author Maxime Steinhausser <maxime.steinhausser@gmail.com>\n *\n * @final\n */\nclass CliDescriptor implements DumpDescriptorInterface\n{\n    private mixed $lastIdentifier = null;\n\n    public function __construct(\n        private CliDumper $dumper,\n    ) {\n    }\n\n    public function describe(OutputInterface $output, Data $data, array $context, int $clientId): void\n    {\n        $io = $output instanceof SymfonyStyle ? $output : new SymfonyStyle(new ArrayInput([]), $output);\n        $this->dumper->setColors($output->isDecorated());\n\n        $rows = [['date', date('r', (int) $context['timestamp'])]];\n        $lastIdentifier = $this->lastIdentifier;\n        $this->lastIdentifier = $clientId;\n\n        $section = \"Received from client #$clientId\";\n        if (isset($context['request'])) {\n            $request = $context['request'];\n            $this->lastIdentifier = $request['identifier'];\n            $section = \\sprintf('%s %s', $request['method'], $request['uri']);\n            if ($controller = $request['controller']) {\n                $rows[] = ['controller', rtrim($this->dumper->dump($controller, true), \"\\n\")];\n            }\n        } elseif (isset($context['cli'])) {\n            $this->lastIdentifier = $context['cli']['identifier'];\n            $section = '$ '.$context['cli']['command_line'];\n        }\n\n        if ($this->lastIdentifier !== $lastIdentifier) {\n            $io->section($section);\n        }\n\n        if (isset($context['source'])) {\n            $source = $context['source'];\n            $sourceInfo = \\sprintf('%s on line %d', $source['name'], $source['line']);\n            if ($fileLink = $source['file_link'] ?? null) {\n                $sourceInfo = \\sprintf('<href=%s>%s</>', $fileLink, $sourceInfo);\n            }\n            $rows[] = ['source', $sourceInfo];\n            $file = $source['file_relative'] ?? $source['file'];\n            $rows[] = ['file', $file];\n        }\n\n        $io->table([], $rows);\n\n        $this->dumper->dump($data);\n        $io->newLine();\n    }\n}\n"
  },
  {
    "path": "Command/Descriptor/DumpDescriptorInterface.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Command\\Descriptor;\n\nuse Symfony\\Component\\Console\\Output\\OutputInterface;\nuse Symfony\\Component\\VarDumper\\Cloner\\Data;\n\n/**\n * @author Maxime Steinhausser <maxime.steinhausser@gmail.com>\n */\ninterface DumpDescriptorInterface\n{\n    public function describe(OutputInterface $output, Data $data, array $context, int $clientId): void;\n}\n"
  },
  {
    "path": "Command/Descriptor/HtmlDescriptor.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Command\\Descriptor;\n\nuse Symfony\\Component\\Console\\Output\\OutputInterface;\nuse Symfony\\Component\\VarDumper\\Cloner\\Data;\nuse Symfony\\Component\\VarDumper\\Dumper\\HtmlDumper;\n\n/**\n * Describe collected data clones for html output.\n *\n * @author Maxime Steinhausser <maxime.steinhausser@gmail.com>\n *\n * @final\n */\nclass HtmlDescriptor implements DumpDescriptorInterface\n{\n    private bool $initialized = false;\n\n    public function __construct(\n        private HtmlDumper $dumper,\n    ) {\n    }\n\n    public function describe(OutputInterface $output, Data $data, array $context, int $clientId): void\n    {\n        if (!$this->initialized) {\n            $styles = file_get_contents(__DIR__.'/../../Resources/css/htmlDescriptor.css');\n            $scripts = file_get_contents(__DIR__.'/../../Resources/js/htmlDescriptor.js');\n            $output->writeln(\"<style>$styles</style><script>$scripts</script>\");\n            $this->initialized = true;\n        }\n\n        $title = '-';\n        if (isset($context['request'])) {\n            $request = $context['request'];\n            $controller = \"<span class='dumped-tag'>{$this->dumper->dump($request['controller'], true, ['maxDepth' => 0])}</span>\";\n            $title = \\sprintf('<code>%s</code> <a href=\"%s\">%s</a>', $request['method'], $uri = $request['uri'], $uri);\n            $dedupIdentifier = $request['identifier'];\n        } elseif (isset($context['cli'])) {\n            $title = '<code>$ </code>'.$context['cli']['command_line'];\n            $dedupIdentifier = $context['cli']['identifier'];\n        } else {\n            $dedupIdentifier = bin2hex(random_bytes(4));\n        }\n\n        $sourceDescription = '';\n        if (isset($context['source'])) {\n            $source = $context['source'];\n            $projectDir = $source['project_dir'] ?? null;\n            $sourceDescription = \\sprintf('%s on line %d', $source['name'], $source['line']);\n            if (isset($source['file_link'])) {\n                $sourceDescription = \\sprintf('<a href=\"%s\">%s</a>', $source['file_link'], $sourceDescription);\n            }\n        }\n\n        $isoDate = $this->extractDate($context, 'c');\n        $tags = array_filter([\n            'controller' => $controller ?? null,\n            'project dir' => $projectDir ?? null,\n        ]);\n\n        $output->writeln(<<<HTML\n            <article data-dedup-id=\"$dedupIdentifier\">\n                <header>\n                    <div class=\"row\">\n                        <h2 class=\"col\">$title</h2>\n                        <time class=\"col text-small\" title=\"$isoDate\" datetime=\"$isoDate\">\n                            {$this->extractDate($context)}\n                        </time>\n                    </div>\n                    {$this->renderTags($tags)}\n                </header>\n                <section class=\"body\">\n                    <p class=\"text-small\">\n                        $sourceDescription\n                    </p>\n                    {$this->dumper->dump($data, true)}\n                </section>\n            </article>\n            HTML\n        );\n    }\n\n    private function extractDate(array $context, string $format = 'r'): string\n    {\n        return date($format, (int) $context['timestamp']);\n    }\n\n    private function renderTags(array $tags): string\n    {\n        if (!$tags) {\n            return '';\n        }\n\n        $renderedTags = '';\n        foreach ($tags as $key => $value) {\n            $renderedTags .= \\sprintf('<li><span class=\"badge\">%s</span>%s</li>', $key, $value);\n        }\n\n        return <<<HTML\n            <div class=\"row\">\n                <ul class=\"tags\">\n                    $renderedTags\n                </ul>\n            </div>\n            HTML;\n    }\n}\n"
  },
  {
    "path": "Command/ServerDumpCommand.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Command;\n\nuse Symfony\\Component\\Console\\Attribute\\AsCommand;\nuse Symfony\\Component\\Console\\Command\\Command;\nuse Symfony\\Component\\Console\\Completion\\CompletionInput;\nuse Symfony\\Component\\Console\\Completion\\CompletionSuggestions;\nuse Symfony\\Component\\Console\\Exception\\InvalidArgumentException;\nuse Symfony\\Component\\Console\\Input\\InputInterface;\nuse Symfony\\Component\\Console\\Input\\InputOption;\nuse Symfony\\Component\\Console\\Output\\OutputInterface;\nuse Symfony\\Component\\Console\\Style\\SymfonyStyle;\nuse Symfony\\Component\\VarDumper\\Cloner\\Data;\nuse Symfony\\Component\\VarDumper\\Command\\Descriptor\\CliDescriptor;\nuse Symfony\\Component\\VarDumper\\Command\\Descriptor\\DumpDescriptorInterface;\nuse Symfony\\Component\\VarDumper\\Command\\Descriptor\\HtmlDescriptor;\nuse Symfony\\Component\\VarDumper\\Dumper\\CliDumper;\nuse Symfony\\Component\\VarDumper\\Dumper\\HtmlDumper;\nuse Symfony\\Component\\VarDumper\\Server\\DumpServer;\n\n/**\n * Starts a dump server to collect and output dumps on a single place with multiple formats support.\n *\n * @author Maxime Steinhausser <maxime.steinhausser@gmail.com>\n *\n * @final\n */\n#[AsCommand(name: 'server:dump', description: 'Start a dump server that collects and displays dumps in a single place')]\nclass ServerDumpCommand extends Command\n{\n    /** @var DumpDescriptorInterface[] */\n    private array $descriptors;\n\n    public function __construct(\n        private DumpServer $server,\n        array $descriptors = [],\n    ) {\n        $this->descriptors = $descriptors + [\n            'cli' => new CliDescriptor(new CliDumper()),\n            'html' => new HtmlDescriptor(new HtmlDumper()),\n        ];\n\n        parent::__construct();\n    }\n\n    protected function configure(): void\n    {\n        $this\n            ->addOption('format', null, InputOption::VALUE_REQUIRED, \\sprintf('The output format (%s)', implode(', ', $this->getAvailableFormats())), 'cli')\n            ->setHelp(<<<'EOF'\n                <info>%command.name%</info> starts a dump server that collects and displays\n                dumps in a single place for debugging you application:\n\n                  <info>php %command.full_name%</info>\n\n                You can consult dumped data in HTML format in your browser by providing the <info>--format=html</info> option\n                and redirecting the output to a file:\n\n                  <info>php %command.full_name% --format=\"html\" > dump.html</info>\n\n                EOF\n            )\n        ;\n    }\n\n    protected function execute(InputInterface $input, OutputInterface $output): int\n    {\n        $io = new SymfonyStyle($input, $output);\n        $format = $input->getOption('format');\n\n        if (!$descriptor = $this->descriptors[$format] ?? null) {\n            throw new InvalidArgumentException(\\sprintf('Unsupported format \"%s\".', $format));\n        }\n\n        $errorIo = $io->getErrorStyle();\n        $errorIo->title('Symfony Var Dumper Server');\n\n        $this->server->start();\n\n        $errorIo->success(\\sprintf('Server listening on %s', $this->server->getHost()));\n        $errorIo->comment('Quit the server with CONTROL-C.');\n\n        $this->server->listen(static function (Data $data, array $context, int $clientId) use ($descriptor, $io) {\n            $descriptor->describe($io, $data, $context, $clientId);\n        });\n\n        return 0;\n    }\n\n    public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void\n    {\n        if ($input->mustSuggestOptionValuesFor('format')) {\n            $suggestions->suggestValues($this->getAvailableFormats());\n        }\n    }\n\n    private function getAvailableFormats(): array\n    {\n        return array_keys($this->descriptors);\n    }\n}\n"
  },
  {
    "path": "Dumper/AbstractDumper.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Dumper;\n\nuse Symfony\\Component\\VarDumper\\Cloner\\Data;\nuse Symfony\\Component\\VarDumper\\Cloner\\DumperInterface;\n\n/**\n * Abstract mechanism for dumping a Data object.\n *\n * @author Nicolas Grekas <p@tchwork.com>\n */\nabstract class AbstractDumper implements DataDumperInterface, DumperInterface\n{\n    public const DUMP_LIGHT_ARRAY = 1;\n    public const DUMP_STRING_LENGTH = 2;\n    public const DUMP_COMMA_SEPARATOR = 4;\n    public const DUMP_TRAILING_COMMA = 8;\n\n    /** @var callable|resource|string|null */\n    public static $defaultOutput = 'php://output';\n\n    protected string $line = '';\n    /** @var callable|null */\n    protected $lineDumper;\n    /** @var resource|null */\n    protected $outputStream;\n    protected string $decimalPoint = '.';\n    protected string $indentPad = '  ';\n\n    private string $charset = '';\n\n    /**\n     * @param callable|resource|string|null $output  A line dumper callable, an opened stream or an output path, defaults to static::$defaultOutput\n     * @param string|null                   $charset The default character encoding to use for non-UTF8 strings\n     * @param int                           $flags   A bit field of static::DUMP_* constants to fine tune dumps representation\n     */\n    public function __construct(\n        $output = null,\n        ?string $charset = null,\n        protected int $flags = 0,\n    ) {\n        $this->setCharset($charset ?: \\ini_get('php.output_encoding') ?: \\ini_get('default_charset') ?: 'UTF-8');\n        $this->setOutput($output ?: static::$defaultOutput);\n        if (!$output && \\is_string(static::$defaultOutput)) {\n            static::$defaultOutput = $this->outputStream;\n        }\n    }\n\n    /**\n     * Sets the output destination of the dumps.\n     *\n     * @param callable|resource|string|null $output A line dumper callable, an opened stream or an output path\n     *\n     * @return callable|resource|string|null The previous output destination\n     */\n    public function setOutput($output)\n    {\n        $prev = $this->outputStream ?? $this->lineDumper;\n\n        if (\\is_callable($output)) {\n            $this->outputStream = null;\n            $this->lineDumper = $output;\n        } else {\n            if (\\is_string($output)) {\n                $output = fopen($output, 'w');\n            }\n            $this->outputStream = $output;\n            $this->lineDumper = $this->echoLine(...);\n        }\n\n        return $prev;\n    }\n\n    /**\n     * Sets the default character encoding to use for non-UTF8 strings.\n     *\n     * @return string The previous charset\n     */\n    public function setCharset(string $charset): string\n    {\n        $prev = $this->charset;\n\n        $charset = strtoupper($charset);\n        $charset = 'UTF-8' === $charset || 'UTF8' === $charset ? 'CP1252' : $charset;\n\n        $this->charset = $charset;\n\n        return $prev;\n    }\n\n    /**\n     * Sets the indentation pad string.\n     *\n     * @param string $pad A string that will be prepended to dumped lines, repeated by nesting level\n     *\n     * @return string The previous indent pad\n     */\n    public function setIndentPad(string $pad): string\n    {\n        $prev = $this->indentPad;\n        $this->indentPad = $pad;\n\n        return $prev;\n    }\n\n    /**\n     * Dumps a Data object.\n     *\n     * @param callable|resource|string|true|null $output A line dumper callable, an opened stream, an output path or true to return the dump\n     *\n     * @return string|null The dump as string when $output is true\n     */\n    public function dump(Data $data, $output = null): ?string\n    {\n        if ($locale = $this->flags & (self::DUMP_COMMA_SEPARATOR | self::DUMP_TRAILING_COMMA) ? setlocale(\\LC_NUMERIC, 0) : null) {\n            setlocale(\\LC_NUMERIC, 'C');\n        }\n\n        if ($returnDump = true === $output) {\n            $output = fopen('php://memory', 'r+');\n        }\n        if ($output) {\n            $prevOutput = $this->setOutput($output);\n        }\n        try {\n            $data->dump($this);\n            $this->dumpLine(-1);\n\n            if ($returnDump) {\n                $result = stream_get_contents($output, -1, 0);\n                fclose($output);\n\n                return $result;\n            }\n        } finally {\n            if ($output) {\n                $this->setOutput($prevOutput);\n            }\n            if ($locale) {\n                setlocale(\\LC_NUMERIC, $locale);\n            }\n        }\n\n        return null;\n    }\n\n    /**\n     * Dumps the current line.\n     *\n     * @param int $depth The recursive depth in the dumped structure for the line being dumped,\n     *                   or -1 to signal the end-of-dump to the line dumper callable\n     */\n    protected function dumpLine(int $depth): void\n    {\n        ($this->lineDumper)($this->line, $depth, $this->indentPad);\n        $this->line = '';\n    }\n\n    /**\n     * Generic line dumper callback.\n     */\n    protected function echoLine(string $line, int $depth, string $indentPad): void\n    {\n        if (-1 !== $depth) {\n            fwrite($this->outputStream, str_repeat($indentPad, $depth).$line.\"\\n\");\n        }\n    }\n\n    /**\n     * Converts a non-UTF-8 string to UTF-8.\n     */\n    protected function utf8Encode(?string $s): ?string\n    {\n        if (null === $s || preg_match('//u', $s)) {\n            return $s;\n        }\n\n        if (\\function_exists('iconv')) {\n            if (false !== $c = @iconv($this->charset, 'UTF-8', $s)) {\n                return $c;\n            }\n            if ('CP1252' !== $this->charset && false !== $c = @iconv('CP1252', 'UTF-8', $s)) {\n                return $c;\n            }\n        }\n\n        $s .= $s;\n        $len = \\strlen($s);\n        $mapCp1252 = false;\n\n        for ($i = $len >> 1, $j = 0; $i < $len; ++$i, ++$j) {\n            if ($s[$i] < \"\\x80\") {\n                $s[$j] = $s[$i];\n            } elseif ($s[$i] < \"\\xC0\") {\n                $s[$j] = \"\\xC2\";\n                $s[++$j] = $s[$i];\n                if ($s[$i] < \"\\xA0\") {\n                    $mapCp1252 = true;\n                }\n            } else {\n                $s[$j] = \"\\xC3\";\n                $s[++$j] = \\chr(\\ord($s[$i]) - 64);\n            }\n        }\n\n        $s = substr($s, 0, $j);\n\n        if (!$mapCp1252) {\n            return $s;\n        }\n\n        return strtr($s, [\n            \"\\xC2\\x80\" => '€', \"\\xC2\\x82\" => '‚', \"\\xC2\\x83\" => 'ƒ', \"\\xC2\\x84\" => '„',\n            \"\\xC2\\x85\" => '…', \"\\xC2\\x86\" => '†', \"\\xC2\\x87\" => '‡', \"\\xC2\\x88\" => 'ˆ',\n            \"\\xC2\\x89\" => '‰', \"\\xC2\\x8A\" => 'Š', \"\\xC2\\x8B\" => '‹', \"\\xC2\\x8C\" => 'Œ',\n            \"\\xC2\\x8D\" => 'Ž', \"\\xC2\\x91\" => '‘', \"\\xC2\\x92\" => '’', \"\\xC2\\x93\" => '“',\n            \"\\xC2\\x94\" => '”', \"\\xC2\\x95\" => '•', \"\\xC2\\x96\" => '–', \"\\xC2\\x97\" => '—',\n            \"\\xC2\\x98\" => '˜', \"\\xC2\\x99\" => '™', \"\\xC2\\x9A\" => 'š', \"\\xC2\\x9B\" => '›',\n            \"\\xC2\\x9C\" => 'œ', \"\\xC2\\x9E\" => 'ž',\n        ]);\n    }\n}\n"
  },
  {
    "path": "Dumper/CliDumper.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Dumper;\n\nuse Symfony\\Component\\ErrorHandler\\ErrorRenderer\\FileLinkFormatter;\nuse Symfony\\Component\\VarDumper\\Cloner\\Cursor;\nuse Symfony\\Component\\VarDumper\\Cloner\\Stub;\n\n/**\n * CliDumper dumps variables for command line output.\n *\n * @author Nicolas Grekas <p@tchwork.com>\n */\nclass CliDumper extends AbstractDumper\n{\n    public static bool $defaultColors;\n    /** @var callable|resource|string|null */\n    public static $defaultOutput = 'php://stdout';\n\n    protected bool $colors;\n    protected int $maxStringWidth = 0;\n    protected array $styles = [\n        // See http://en.wikipedia.org/wiki/ANSI_escape_code#graphics\n        'default' => '0;38;5;208',\n        'num' => '1;38;5;38',\n        'const' => '1;38;5;208',\n        'virtual' => '3',\n        'str' => '1;38;5;113',\n        'note' => '38;5;38',\n        'ref' => '38;5;247',\n        'public' => '39',\n        'protected' => '39',\n        'private' => '39',\n        'meta' => '38;5;170',\n        'key' => '38;5;113',\n        'index' => '38;5;38',\n    ];\n\n    protected static string $controlCharsRx = '/[\\x00-\\x1F\\x7F]+/';\n    protected static array $controlCharsMap = [\n        \"\\t\" => '\\t',\n        \"\\n\" => '\\n',\n        \"\\v\" => '\\v',\n        \"\\f\" => '\\f',\n        \"\\r\" => '\\r',\n        \"\\033\" => '\\e',\n    ];\n    protected static string $unicodeCharsRx = \"/[\\u{00A0}\\u{00AD}\\u{034F}\\u{061C}\\u{115F}\\u{1160}\\u{17B4}\\u{17B5}\\u{180E}\\u{2000}-\\u{200F}\\u{202F}\\u{205F}\\u{2060}-\\u{2064}\\u{206A}-\\u{206F}\\u{3000}\\u{2800}\\u{3164}\\u{FEFF}\\u{FFA0}\\u{1D159}\\u{1D173}-\\u{1D17A}]/u\";\n\n    protected bool $collapseNextHash = false;\n    protected bool $expandNextHash = false;\n\n    private array $displayOptions = [\n        'fileLinkFormat' => null,\n    ];\n\n    private bool $handlesHrefGracefully;\n\n    public function __construct($output = null, ?string $charset = null, int $flags = 0)\n    {\n        parent::__construct($output, $charset, $flags);\n\n        if ('\\\\' === \\DIRECTORY_SEPARATOR && !$this->isWindowsTrueColor()) {\n            // Use only the base 16 xterm colors when using ANSICON or standard Windows 10 CLI\n            $this->setStyles([\n                'default' => '31',\n                'num' => '1;34',\n                'const' => '1;31',\n                'str' => '1;32',\n                'note' => '34',\n                'ref' => '1;30',\n                'meta' => '35',\n                'key' => '32',\n                'index' => '34',\n            ]);\n        }\n\n        $this->displayOptions['fileLinkFormat'] = class_exists(FileLinkFormatter::class) ? new FileLinkFormatter() : (\\ini_get('xdebug.file_link_format') ?: get_cfg_var('xdebug.file_link_format') ?: 'file://%f#L%l');\n    }\n\n    /**\n     * Enables/disables colored output.\n     */\n    public function setColors(bool $colors): void\n    {\n        $this->colors = $colors;\n    }\n\n    /**\n     * Sets the maximum number of characters per line for dumped strings.\n     */\n    public function setMaxStringWidth(int $maxStringWidth): void\n    {\n        $this->maxStringWidth = $maxStringWidth;\n    }\n\n    /**\n     * Configures styles.\n     *\n     * @param array $styles A map of style names to style definitions\n     */\n    public function setStyles(array $styles): void\n    {\n        $this->styles = $styles + $this->styles;\n    }\n\n    /**\n     * Configures display options.\n     *\n     * @param array $displayOptions A map of display options to customize the behavior\n     */\n    public function setDisplayOptions(array $displayOptions): void\n    {\n        $this->displayOptions = $displayOptions + $this->displayOptions;\n    }\n\n    public function dumpScalar(Cursor $cursor, string $type, string|int|float|bool|null $value): void\n    {\n        $this->dumpKey($cursor);\n        $this->collapseNextHash = $this->expandNextHash = false;\n\n        $style = 'const';\n        $attr = $cursor->attr;\n\n        switch ($type) {\n            case 'default':\n                $style = 'default';\n                break;\n\n            case 'label':\n                $this->styles += ['label' => $this->styles['default']];\n                $style = 'label';\n                break;\n\n            case 'integer':\n                $style = 'num';\n\n                if (isset($this->styles['integer'])) {\n                    $style = 'integer';\n                }\n\n                break;\n\n            case 'double':\n                $style = 'num';\n\n                if (isset($this->styles['float'])) {\n                    $style = 'float';\n                }\n\n                $value = match (true) {\n                    \\INF === $value => 'INF',\n                    -\\INF === $value => '-INF',\n                    is_nan($value) => 'NAN',\n                    default => !str_contains($value = (string) $value, $this->decimalPoint) ? $value .= $this->decimalPoint.'0' : $value,\n                };\n                break;\n\n            case 'NULL':\n                $value = 'null';\n                break;\n\n            case 'boolean':\n                $value = $value ? 'true' : 'false';\n                break;\n\n            default:\n                $attr += ['value' => $this->utf8Encode($value)];\n                $value = $this->utf8Encode($type);\n                break;\n        }\n\n        $this->line .= $this->style($style, $value, $attr);\n\n        $this->endValue($cursor);\n    }\n\n    public function dumpString(Cursor $cursor, string $str, bool $bin, int $cut): void\n    {\n        $this->dumpKey($cursor);\n        $this->collapseNextHash = $this->expandNextHash = false;\n        $attr = $cursor->attr;\n\n        if ($bin) {\n            $str = $this->utf8Encode($str);\n        }\n        if ('' === $str) {\n            $this->line .= '\"\"';\n            if ($cut) {\n                $this->line .= '…'.$cut;\n            }\n            $this->endValue($cursor);\n        } else {\n            $attr += [\n                'length' => 0 <= $cut ? mb_strlen($str, 'UTF-8') + $cut : 0,\n                'binary' => $bin,\n            ];\n            $str = $bin && str_contains($str, \"\\0\") ? [$str] : explode(\"\\n\", $str);\n            if (isset($str[1]) && !isset($str[2]) && !isset($str[1][0])) {\n                unset($str[1]);\n                $str[0] .= \"\\n\";\n            }\n            $m = \\count($str) - 1;\n            $i = $lineCut = 0;\n\n            if (self::DUMP_STRING_LENGTH & $this->flags) {\n                $this->line .= '('.$attr['length'].') ';\n            }\n            if ($bin) {\n                $this->line .= 'b';\n            }\n\n            if ($m) {\n                $this->line .= '\"\"\"';\n                $this->dumpLine($cursor->depth);\n            } else {\n                $this->line .= '\"';\n            }\n\n            foreach ($str as $str) {\n                if ($i < $m) {\n                    $str .= \"\\n\";\n                }\n                if (0 < $this->maxStringWidth && $this->maxStringWidth < $len = mb_strlen($str, 'UTF-8')) {\n                    $str = mb_substr($str, 0, $this->maxStringWidth, 'UTF-8');\n                    $lineCut = $len - $this->maxStringWidth;\n                }\n                if ($m && 0 < $cursor->depth) {\n                    $this->line .= $this->indentPad;\n                }\n                if ('' !== $str) {\n                    $this->line .= $this->style('str', $str, $attr);\n                }\n                if ($i++ == $m) {\n                    if ($m) {\n                        if ('' !== $str) {\n                            $this->dumpLine($cursor->depth);\n                            if (0 < $cursor->depth) {\n                                $this->line .= $this->indentPad;\n                            }\n                        }\n                        $this->line .= '\"\"\"';\n                    } else {\n                        $this->line .= '\"';\n                    }\n                    if ($cut < 0) {\n                        $this->line .= '…';\n                        $lineCut = 0;\n                    } elseif ($cut) {\n                        $lineCut += $cut;\n                    }\n                }\n                if ($lineCut) {\n                    $this->line .= '…'.$lineCut;\n                    $lineCut = 0;\n                }\n\n                if ($i > $m) {\n                    $this->endValue($cursor);\n                } else {\n                    $this->dumpLine($cursor->depth);\n                }\n            }\n        }\n    }\n\n    public function enterHash(Cursor $cursor, int $type, string|int|null $class, bool $hasChild): void\n    {\n        $this->colors ??= $this->supportsColors();\n\n        $this->dumpKey($cursor);\n        $this->expandNextHash = false;\n        $attr = $cursor->attr;\n\n        if ($this->collapseNextHash) {\n            $cursor->skipChildren = true;\n            $this->collapseNextHash = $hasChild = false;\n        }\n\n        $class = $this->utf8Encode($class);\n        if (Cursor::HASH_OBJECT === $type) {\n            $prefix = $class && 'stdClass' !== $class ? $this->style('note', $class, $attr).(empty($attr['cut_hash']) ? ' {' : '') : '{';\n        } elseif (Cursor::HASH_RESOURCE === $type) {\n            $prefix = $this->style('note', $class.' resource', $attr).($hasChild ? ' {' : ' ');\n        } else {\n            $prefix = $class && !(self::DUMP_LIGHT_ARRAY & $this->flags) ? $this->style('note', 'array:'.$class).' [' : '[';\n        }\n\n        if (($cursor->softRefCount || 0 < $cursor->softRefHandle) && empty($attr['cut_hash'])) {\n            $prefix .= $this->style('ref', (Cursor::HASH_RESOURCE === $type ? '@' : '#').(0 < $cursor->softRefHandle ? $cursor->softRefHandle : $cursor->softRefTo), ['count' => $cursor->softRefCount]);\n        } elseif ($cursor->hardRefTo && !$cursor->refIndex && $class) {\n            $prefix .= $this->style('ref', '&'.$cursor->hardRefTo, ['count' => $cursor->hardRefCount]);\n        } elseif (!$hasChild && Cursor::HASH_RESOURCE === $type) {\n            $prefix = substr($prefix, 0, -1);\n        }\n\n        $this->line .= $prefix;\n\n        if ($hasChild) {\n            $this->dumpLine($cursor->depth);\n        }\n    }\n\n    public function leaveHash(Cursor $cursor, int $type, string|int|null $class, bool $hasChild, int $cut): void\n    {\n        if (empty($cursor->attr['cut_hash'])) {\n            $this->dumpEllipsis($cursor, $hasChild, $cut);\n            $this->line .= Cursor::HASH_OBJECT === $type ? '}' : (Cursor::HASH_RESOURCE !== $type ? ']' : ($hasChild ? '}' : ''));\n        }\n\n        $this->endValue($cursor);\n    }\n\n    /**\n     * Dumps an ellipsis for cut children.\n     *\n     * @param bool $hasChild When the dump of the hash has child item\n     * @param int  $cut      The number of items the hash has been cut by\n     */\n    protected function dumpEllipsis(Cursor $cursor, bool $hasChild, int $cut): void\n    {\n        if ($cut) {\n            $this->line .= ' …';\n            if (0 < $cut) {\n                $this->line .= $cut;\n            }\n            if ($hasChild) {\n                $this->dumpLine($cursor->depth + 1);\n            }\n        }\n    }\n\n    /**\n     * Dumps a key in a hash structure.\n     */\n    protected function dumpKey(Cursor $cursor): void\n    {\n        if (null !== $key = $cursor->hashKey) {\n            if ($cursor->hashKeyIsBinary) {\n                $key = $this->utf8Encode($key);\n            }\n            $attr = [\n                'binary' => $cursor->hashKeyIsBinary,\n                'virtual' => $cursor->attr['virtual'] ?? false,\n            ];\n            $bin = $cursor->hashKeyIsBinary ? 'b' : '';\n            $style = 'key';\n            switch ($cursor->hashType) {\n                default:\n                case Cursor::HASH_INDEXED:\n                    if (self::DUMP_LIGHT_ARRAY & $this->flags) {\n                        break;\n                    }\n                    $style = 'index';\n                    // no break\n                case Cursor::HASH_ASSOC:\n                    if (\\is_int($key)) {\n                        $this->line .= $this->style($style, $key).' => ';\n                    } else {\n                        $this->line .= $bin.'\"'.$this->style($style, $key).'\" => ';\n                    }\n                    break;\n\n                case Cursor::HASH_RESOURCE:\n                    $key = \"\\0~\\0\".$key;\n                    // no break\n                case Cursor::HASH_OBJECT:\n                    if (!isset($key[0]) || \"\\0\" !== $key[0]) {\n                        $this->line .= '+'.$bin.$this->style('public', $key, $attr).': ';\n                    } elseif (0 < strpos($key, \"\\0\", 1)) {\n                        $key = explode(\"\\0\", substr($key, 1), 2);\n\n                        switch ($key[0][0]) {\n                            case '+': // User inserted keys\n                                $attr['dynamic'] = true;\n                                $this->line .= '+'.$bin.'\"'.$this->style('public', $key[1], $attr).'\": ';\n                                break 2;\n                            case '~':\n                                $style = 'meta';\n                                if (isset($key[0][1])) {\n                                    parse_str(substr($key[0], 1), $attr);\n                                    $attr += ['binary' => $cursor->hashKeyIsBinary];\n                                }\n                                break;\n                            case '*':\n                                $style = 'protected';\n                                $bin = '#'.$bin;\n                                break;\n                            default:\n                                $attr['class'] = $key[0];\n                                $style = 'private';\n                                $bin = '-'.$bin;\n                                break;\n                        }\n\n                        if (isset($attr['collapse'])) {\n                            if ($attr['collapse']) {\n                                $this->collapseNextHash = true;\n                            } else {\n                                $this->expandNextHash = true;\n                            }\n                        }\n\n                        $this->line .= $bin.$this->style($style, $key[1], $attr).($attr['separator'] ?? ': ');\n                    } else {\n                        // This case should not happen\n                        $this->line .= '-'.$bin.'\"'.$this->style('private', $key, ['class' => '']).'\": ';\n                    }\n                    break;\n            }\n\n            if ($cursor->hardRefTo) {\n                $this->line .= $this->style('ref', '&'.($cursor->hardRefCount ? $cursor->hardRefTo : ''), ['count' => $cursor->hardRefCount]).' ';\n            }\n        }\n    }\n\n    /**\n     * Decorates a value with some style.\n     *\n     * @param string $style The type of style being applied\n     * @param string $value The value being styled\n     * @param array  $attr  Optional context information\n     */\n    protected function style(string $style, string $value, array $attr = []): string\n    {\n        $this->colors ??= $this->supportsColors();\n\n        $this->handlesHrefGracefully ??= 'JetBrains-JediTerm' !== getenv('TERMINAL_EMULATOR')\n            && (!getenv('KONSOLE_VERSION') || (int) getenv('KONSOLE_VERSION') > 201100)\n            && !isset($_SERVER['IDEA_INITIAL_DIRECTORY']);\n\n        if (isset($attr['ellipsis'], $attr['ellipsis-type'])) {\n            $prefix = substr($value, 0, -$attr['ellipsis']);\n            if ('cli' === \\PHP_SAPI && 'path' === $attr['ellipsis-type'] && isset($_SERVER[$pwd = '\\\\' === \\DIRECTORY_SEPARATOR ? 'CD' : 'PWD']) && str_starts_with($prefix, $_SERVER[$pwd])) {\n                $prefix = '.'.substr($prefix, \\strlen($_SERVER[$pwd]));\n            }\n            if (!empty($attr['ellipsis-tail'])) {\n                $prefix .= substr($value, -$attr['ellipsis'], $attr['ellipsis-tail']);\n                $value = substr($value, -$attr['ellipsis'] + $attr['ellipsis-tail']);\n            } else {\n                $value = substr($value, -$attr['ellipsis']);\n            }\n\n            $value = $this->style('default', $prefix).$this->style($style, $value);\n\n            goto href;\n        }\n\n        $map = static::$controlCharsMap;\n        $startCchr = $this->colors ? \"\\033[m\\033[{$this->styles['default']}m\" : '';\n        $endCchr = $this->colors ? \"\\033[m\\033[{$this->styles[$style]}m\" : '';\n        $value = preg_replace_callback(static::$controlCharsRx, static function ($c) use ($map, $startCchr, $endCchr) {\n            $s = $startCchr;\n            $c = $c[$i = 0];\n            do {\n                $s .= $map[$c[$i]] ?? \\sprintf('\\x%02X', \\ord($c[$i]));\n            } while (isset($c[++$i]));\n\n            return $s.$endCchr;\n        }, $value, -1, $cchrCount);\n\n        if (!($attr['binary'] ?? false)) {\n            $value = preg_replace_callback(static::$unicodeCharsRx, static function ($c) use (&$cchrCount, $startCchr, $endCchr) {\n                ++$cchrCount;\n\n                return $startCchr.'\\u{'.strtoupper(dechex(mb_ord($c[0]))).'}'.$endCchr;\n            }, $value);\n        }\n\n        if ($this->colors && '' !== $value) {\n            if ($cchrCount && \"\\033\" === $value[0]) {\n                $value = substr($value, \\strlen($startCchr));\n            } else {\n                $value = \"\\033[{$this->styles[$style]}m\".$value;\n            }\n            if ($cchrCount && str_ends_with($value, $endCchr)) {\n                $value = substr($value, 0, -\\strlen($endCchr));\n            } else {\n                $value .= \"\\033[{$this->styles['default']}m\";\n            }\n        }\n\n        href:\n        if ($this->colors && $this->handlesHrefGracefully) {\n            if (isset($attr['file']) && $href = $this->getSourceLink($attr['file'], $attr['line'] ?? 0)) {\n                if ('note' === $style) {\n                    $value .= \"\\033]8;;{$href}\\033\\\\^\\033]8;;\\033\\\\\";\n                } else {\n                    $attr['href'] = $href;\n                }\n            }\n            if (isset($attr['href'])) {\n                if ('label' === $style) {\n                    $value .= '^';\n                }\n                $value = \"\\033]8;;{$attr['href']}\\033\\\\{$value}\\033]8;;\\033\\\\\";\n            }\n        }\n\n        if ('label' === $style && '' !== $value) {\n            $value .= ' ';\n        }\n        if ($this->colors && ($attr['virtual'] ?? false)) {\n            $value = \"\\033[{$this->styles['virtual']}m\".$value;\n        }\n\n        return $value;\n    }\n\n    protected function supportsColors(): bool\n    {\n        if ($this->outputStream !== static::$defaultOutput) {\n            return $this->hasColorSupport($this->outputStream);\n        }\n        if (isset(static::$defaultColors)) {\n            return static::$defaultColors;\n        }\n        if (isset($_SERVER['argv'][1])) {\n            $colors = $_SERVER['argv'];\n            $i = \\count($colors);\n            while (--$i > 0) {\n                if (isset($colors[$i][5])) {\n                    switch ($colors[$i]) {\n                        case '--ansi':\n                        case '--color':\n                        case '--color=yes':\n                        case '--color=force':\n                        case '--color=always':\n                        case '--colors=always':\n                            return static::$defaultColors = true;\n\n                        case '--no-ansi':\n                        case '--color=no':\n                        case '--color=none':\n                        case '--color=never':\n                        case '--colors=never':\n                            return static::$defaultColors = false;\n                    }\n                }\n            }\n        }\n\n        $h = stream_get_meta_data($this->outputStream) + ['wrapper_type' => null];\n        $h = 'Output' === $h['stream_type'] && 'PHP' === $h['wrapper_type'] ? fopen('php://stdout', 'w') : $this->outputStream;\n\n        return static::$defaultColors = $this->hasColorSupport($h);\n    }\n\n    protected function dumpLine(int $depth, bool $endOfValue = false): void\n    {\n        if ($this->colors ??= $this->supportsColors()) {\n            $this->line = \\sprintf(\"\\033[%sm%s\\033[m\", $this->styles['default'], $this->line);\n        }\n        parent::dumpLine($depth);\n    }\n\n    protected function endValue(Cursor $cursor): void\n    {\n        if (-1 === $cursor->hashType) {\n            return;\n        }\n\n        if (Stub::ARRAY_INDEXED === $cursor->hashType || Stub::ARRAY_ASSOC === $cursor->hashType) {\n            if (self::DUMP_TRAILING_COMMA & $this->flags && 0 < $cursor->depth) {\n                $this->line .= ',';\n            } elseif (self::DUMP_COMMA_SEPARATOR & $this->flags && 1 < $cursor->hashLength - $cursor->hashIndex) {\n                $this->line .= ',';\n            }\n        }\n\n        $this->dumpLine($cursor->depth, true);\n    }\n\n    /**\n     * Returns true if the stream supports colorization.\n     *\n     * Reference: Composer\\XdebugHandler\\Process::supportsColor\n     * https://github.com/composer/xdebug-handler\n     */\n    private function hasColorSupport(mixed $stream): bool\n    {\n        if (!\\is_resource($stream) || 'stream' !== get_resource_type($stream)) {\n            return false;\n        }\n\n        // Follow https://no-color.org/\n        if ('' !== (($_SERVER['NO_COLOR'] ?? getenv('NO_COLOR'))[0] ?? '')) {\n            return false;\n        }\n\n        // Follow https://force-color.org/\n        if ('' !== (($_SERVER['FORCE_COLOR'] ?? getenv('FORCE_COLOR'))[0] ?? '')) {\n            return true;\n        }\n\n        // Detect msysgit/mingw and assume this is a tty because detection\n        // does not work correctly, see https://github.com/composer/composer/issues/9690\n        if (!@stream_isatty($stream) && !\\in_array(strtoupper((string) getenv('MSYSTEM')), ['MINGW32', 'MINGW64'], true)) {\n            return false;\n        }\n\n        if ('\\\\' === \\DIRECTORY_SEPARATOR && @sapi_windows_vt100_support($stream)) {\n            return true;\n        }\n\n        if ('Hyper' === getenv('TERM_PROGRAM')\n            || false !== getenv('COLORTERM')\n            || false !== getenv('ANSICON')\n            || 'ON' === getenv('ConEmuANSI')\n        ) {\n            return true;\n        }\n\n        if ('dumb' === $term = (string) getenv('TERM')) {\n            return false;\n        }\n\n        // See https://github.com/chalk/supports-color/blob/d4f413efaf8da045c5ab440ed418ef02dbb28bf1/index.js#L157\n        return preg_match('/^((screen|xterm|vt100|vt220|putty|rxvt|ansi|cygwin|linux).*)|(.*-256(color)?(-bce)?)$/', $term);\n    }\n\n    /**\n     * Returns true if the Windows terminal supports true color.\n     *\n     * Note that this does not check an output stream, but relies on environment\n     * variables from known implementations, or a PHP and Windows version that\n     * supports true color.\n     */\n    private function isWindowsTrueColor(): bool\n    {\n        $result = 183 <= getenv('ANSICON_VER')\n            || 'ON' === getenv('ConEmuANSI')\n            || 'xterm' === getenv('TERM')\n            || 'Hyper' === getenv('TERM_PROGRAM');\n\n        if (!$result) {\n            $version = \\sprintf(\n                '%s.%s.%s',\n                PHP_WINDOWS_VERSION_MAJOR,\n                PHP_WINDOWS_VERSION_MINOR,\n                PHP_WINDOWS_VERSION_BUILD\n            );\n            $result = $version >= '10.0.15063';\n        }\n\n        return $result;\n    }\n\n    private function getSourceLink(string $file, int $line): string|false\n    {\n        if ($fmt = $this->displayOptions['fileLinkFormat']) {\n            return \\is_string($fmt) ? strtr($fmt, ['%f' => $file, '%l' => $line]) : ($fmt->format($file, $line) ?: 'file://'.$file.'#L'.$line);\n        }\n\n        return false;\n    }\n}\n"
  },
  {
    "path": "Dumper/ContextProvider/CliContextProvider.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Dumper\\ContextProvider;\n\n/**\n * Tries to provide context on CLI.\n *\n * @author Maxime Steinhausser <maxime.steinhausser@gmail.com>\n */\nfinal class CliContextProvider implements ContextProviderInterface\n{\n    public function getContext(): ?array\n    {\n        if ('cli' !== \\PHP_SAPI) {\n            return null;\n        }\n\n        return [\n            'command_line' => $commandLine = implode(' ', $_SERVER['argv'] ?? []),\n            'identifier' => hash('xxh128', $commandLine.'@'.$_SERVER['REQUEST_TIME_FLOAT']),\n        ];\n    }\n}\n"
  },
  {
    "path": "Dumper/ContextProvider/ContextProviderInterface.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Dumper\\ContextProvider;\n\n/**\n * Interface to provide contextual data about dump data clones sent to a server.\n *\n * @author Maxime Steinhausser <maxime.steinhausser@gmail.com>\n */\ninterface ContextProviderInterface\n{\n    public function getContext(): ?array;\n}\n"
  },
  {
    "path": "Dumper/ContextProvider/RequestContextProvider.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Dumper\\ContextProvider;\n\nuse Symfony\\Component\\HttpFoundation\\RequestStack;\nuse Symfony\\Component\\VarDumper\\Caster\\ReflectionCaster;\nuse Symfony\\Component\\VarDumper\\Cloner\\VarCloner;\n\n/**\n * Tries to provide context from a request.\n *\n * @author Maxime Steinhausser <maxime.steinhausser@gmail.com>\n */\nfinal class RequestContextProvider implements ContextProviderInterface\n{\n    private VarCloner $cloner;\n\n    public function __construct(\n        private RequestStack $requestStack,\n    ) {\n        $this->cloner = new VarCloner();\n        $this->cloner->setMaxItems(0);\n        $this->cloner->addCasters(ReflectionCaster::UNSET_CLOSURE_FILE_INFO);\n    }\n\n    public function getContext(): ?array\n    {\n        if (null === $request = $this->requestStack->getCurrentRequest()) {\n            return null;\n        }\n\n        $controller = $request->attributes->get('_controller');\n\n        return [\n            'uri' => $request->getUri(),\n            'method' => $request->getMethod(),\n            'controller' => $controller ? $this->cloner->cloneVar($controller) : $controller,\n            'identifier' => hash('xxh128', spl_object_id($request).'@'.$_SERVER['REQUEST_TIME_FLOAT']),\n        ];\n    }\n}\n"
  },
  {
    "path": "Dumper/ContextProvider/SourceContextProvider.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Dumper\\ContextProvider;\n\nuse Symfony\\Component\\ErrorHandler\\ErrorRenderer\\FileLinkFormatter;\nuse Symfony\\Component\\VarDumper\\Cloner\\VarCloner;\nuse Symfony\\Component\\VarDumper\\Dumper\\HtmlDumper;\nuse Symfony\\Component\\VarDumper\\VarDumper;\nuse Twig\\Template;\n\n/**\n * Tries to provide context from sources (class name, file, line, code excerpt, ...).\n *\n * @author Nicolas Grekas <p@tchwork.com>\n * @author Maxime Steinhausser <maxime.steinhausser@gmail.com>\n */\nfinal class SourceContextProvider implements ContextProviderInterface\n{\n    public function __construct(\n        private ?string $charset = null,\n        private ?string $projectDir = null,\n        private ?FileLinkFormatter $fileLinkFormatter = null,\n        private int $limit = 9,\n    ) {\n    }\n\n    public function getContext(): ?array\n    {\n        $trace = debug_backtrace(\\DEBUG_BACKTRACE_PROVIDE_OBJECT | \\DEBUG_BACKTRACE_IGNORE_ARGS, $this->limit);\n\n        $file = $trace[1]['file'];\n        $line = $trace[1]['line'];\n        $name = '-' === $file || 'Standard input code' === $file ? 'Standard input code' : false;\n        $fileExcerpt = false;\n\n        for ($i = 2; $i < $this->limit; ++$i) {\n            if (isset($trace[$i]['class'], $trace[$i]['function'])\n                && 'dump' === $trace[$i]['function']\n                && VarDumper::class === $trace[$i]['class']\n            ) {\n                $file = $trace[$i]['file'] ?? $file;\n                $line = $trace[$i]['line'] ?? $line;\n\n                while (++$i < $this->limit) {\n                    if (isset($trace[$i]['function'], $trace[$i]['file']) && empty($trace[$i]['class']) && !str_starts_with($trace[$i]['function'], 'call_user_func')) {\n                        $file = $trace[$i]['file'];\n                        $line = $trace[$i]['line'];\n\n                        break;\n                    } elseif (isset($trace[$i]['object']) && $trace[$i]['object'] instanceof Template) {\n                        $template = $trace[$i]['object'];\n                        $name = $template->getTemplateName();\n                        $src = method_exists($template, 'getSourceContext') ? $template->getSourceContext()->getCode() : (method_exists($template, 'getSource') ? $template->getSource() : false);\n                        $info = $template->getDebugInfo();\n                        if (isset($info[$trace[$i - 1]['line']])) {\n                            $line = $info[$trace[$i - 1]['line']];\n                            $file = method_exists($template, 'getSourceContext') ? $template->getSourceContext()->getPath() : null;\n\n                            if ($src) {\n                                $src = explode(\"\\n\", $src);\n                                $fileExcerpt = [];\n\n                                for ($i = max($line - 3, 1), $max = min($line + 3, \\count($src)); $i <= $max; ++$i) {\n                                    $fileExcerpt[] = '<li'.($i === $line ? ' class=\"selected\"' : '').'><code>'.$this->htmlEncode($src[$i - 1]).'</code></li>';\n                                }\n\n                                $fileExcerpt = '<ol start=\"'.max($line - 3, 1).'\">'.implode(\"\\n\", $fileExcerpt).'</ol>';\n                            }\n                        }\n                        break;\n                    }\n                }\n                break;\n            }\n        }\n\n        if (false === $name) {\n            $name = str_replace('\\\\', '/', $file);\n            $name = substr($name, strrpos($name, '/') + 1);\n        }\n\n        $context = ['name' => $name, 'file' => $file, 'line' => $line];\n        $context['file_excerpt'] = $fileExcerpt;\n\n        if (null !== $this->projectDir) {\n            $context['project_dir'] = $this->projectDir;\n            if (str_starts_with($file, $this->projectDir)) {\n                $context['file_relative'] = ltrim(substr($file, \\strlen($this->projectDir)), \\DIRECTORY_SEPARATOR);\n            }\n        }\n\n        if ($this->fileLinkFormatter && $fileLink = $this->fileLinkFormatter->format($context['file'], $context['line'])) {\n            $context['file_link'] = $fileLink;\n        }\n\n        return $context;\n    }\n\n    private function htmlEncode(string $s): string\n    {\n        $html = '';\n\n        $dumper = new HtmlDumper(static function ($line) use (&$html) { $html .= $line; }, $this->charset);\n        $dumper->setDumpHeader('');\n        $dumper->setDumpBoundaries('', '');\n\n        $cloner = new VarCloner();\n        $dumper->dump($cloner->cloneVar($s));\n\n        return substr(strip_tags($html), 1, -1);\n    }\n}\n"
  },
  {
    "path": "Dumper/ContextualizedDumper.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Dumper;\n\nuse Symfony\\Component\\VarDumper\\Cloner\\Data;\nuse Symfony\\Component\\VarDumper\\Dumper\\ContextProvider\\ContextProviderInterface;\n\n/**\n * @author Kévin Thérage <therage.kevin@gmail.com>\n */\nclass ContextualizedDumper implements DataDumperInterface\n{\n    /**\n     * @param ContextProviderInterface[] $contextProviders\n     */\n    public function __construct(\n        private DataDumperInterface $wrappedDumper,\n        private array $contextProviders,\n    ) {\n    }\n\n    public function dump(Data $data): ?string\n    {\n        $context = $data->getContext();\n        foreach ($this->contextProviders as $contextProvider) {\n            $context[$contextProvider::class] = $contextProvider->getContext();\n        }\n\n        return $this->wrappedDumper->dump($data->withContext($context));\n    }\n}\n"
  },
  {
    "path": "Dumper/DataDumperInterface.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Dumper;\n\nuse Symfony\\Component\\VarDumper\\Cloner\\Data;\n\n/**\n * DataDumperInterface for dumping Data objects.\n *\n * @author Nicolas Grekas <p@tchwork.com>\n */\ninterface DataDumperInterface\n{\n    public function dump(Data $data): ?string;\n}\n"
  },
  {
    "path": "Dumper/HtmlDumper.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Dumper;\n\nuse Symfony\\Component\\VarDumper\\Cloner\\Cursor;\nuse Symfony\\Component\\VarDumper\\Cloner\\Data;\n\n/**\n * HtmlDumper dumps variables as HTML.\n *\n * @author Nicolas Grekas <p@tchwork.com>\n */\nclass HtmlDumper extends CliDumper\n{\n    /** @var callable|resource|string|null */\n    public static $defaultOutput = 'php://output';\n\n    protected static $themes = [\n        'dark' => [\n            'default' => 'background-color:#18171B; color:#FF8400; line-height:1.2em; font:12px Menlo, Monaco, Consolas, monospace; word-wrap: break-word; white-space: pre-wrap; position:relative; z-index:99999; word-break: break-all',\n            'num' => 'font-weight:bold; color:#1299DA',\n            'const' => 'font-weight:bold',\n            'virtual' => 'font-style:italic',\n            'str' => 'font-weight:bold; color:#56DB3A',\n            'note' => 'color:#1299DA',\n            'ref' => 'color:#A0A0A0',\n            'public' => 'color:#FFFFFF',\n            'protected' => 'color:#FFFFFF',\n            'private' => 'color:#FFFFFF',\n            'meta' => 'color:#B729D9',\n            'key' => 'color:#56DB3A',\n            'index' => 'color:#1299DA',\n            'ellipsis' => 'color:#FF8400',\n            'ns' => 'user-select:none;',\n        ],\n        'light' => [\n            'default' => 'background:none; color:#CC7832; line-height:1.2em; font:12px Menlo, Monaco, Consolas, monospace; word-wrap: break-word; white-space: pre-wrap; position:relative; z-index:99999; word-break: break-all',\n            'num' => 'font-weight:bold; color:#1299DA',\n            'const' => 'font-weight:bold',\n            'virtual' => 'font-style:italic',\n            'str' => 'font-weight:bold; color:#629755;',\n            'note' => 'color:#6897BB',\n            'ref' => 'color:#6E6E6E',\n            'public' => 'color:#262626',\n            'protected' => 'color:#262626',\n            'private' => 'color:#262626',\n            'meta' => 'color:#B729D9',\n            'key' => 'color:#789339',\n            'index' => 'color:#1299DA',\n            'ellipsis' => 'color:#CC7832',\n            'ns' => 'user-select:none;',\n        ],\n    ];\n\n    protected ?string $dumpHeader = null;\n    protected string $dumpPrefix = '<pre class=sf-dump id=%s data-indent-pad=\"%s\">';\n    protected string $dumpSuffix = '</pre><script>Sfdump(%s)</script>';\n    protected string $dumpId;\n    protected bool $colors = true;\n    protected $headerIsDumped = false;\n    protected int $lastDepth = -1;\n\n    private array $displayOptions = [\n        'maxDepth' => 1,\n        'maxStringLength' => 160,\n        'fileLinkFormat' => null,\n    ];\n    private array $extraDisplayOptions = [];\n\n    public function __construct($output = null, ?string $charset = null, int $flags = 0)\n    {\n        AbstractDumper::__construct($output, $charset, $flags);\n        $this->dumpId = 'sf-dump-'.mt_rand();\n        $this->displayOptions['fileLinkFormat'] = \\ini_get('xdebug.file_link_format') ?: get_cfg_var('xdebug.file_link_format');\n        $this->styles = static::$themes['dark'] ?? self::$themes['dark'];\n    }\n\n    public function setStyles(array $styles): void\n    {\n        $this->headerIsDumped = false;\n        $this->styles = $styles + $this->styles;\n    }\n\n    public function setTheme(string $themeName): void\n    {\n        if (!isset(static::$themes[$themeName])) {\n            throw new \\InvalidArgumentException(\\sprintf('Theme \"%s\" does not exist in class \"%s\".', $themeName, static::class));\n        }\n\n        $this->setStyles(static::$themes[$themeName]);\n    }\n\n    /**\n     * Configures display options.\n     *\n     * @param array $displayOptions A map of display options to customize the behavior\n     */\n    public function setDisplayOptions(array $displayOptions): void\n    {\n        $this->headerIsDumped = false;\n        $this->displayOptions = $displayOptions + $this->displayOptions;\n    }\n\n    /**\n     * Sets an HTML header that will be dumped once in the output stream.\n     */\n    public function setDumpHeader(?string $header): void\n    {\n        $this->dumpHeader = $header;\n    }\n\n    /**\n     * Sets an HTML prefix and suffix that will encapse every single dump.\n     */\n    public function setDumpBoundaries(string $prefix, string $suffix): void\n    {\n        $this->dumpPrefix = $prefix;\n        $this->dumpSuffix = $suffix;\n    }\n\n    public function dump(Data $data, $output = null, array $extraDisplayOptions = []): ?string\n    {\n        $this->extraDisplayOptions = $extraDisplayOptions;\n        $result = parent::dump($data, $output);\n        $this->dumpId = 'sf-dump-'.mt_rand();\n\n        return $result;\n    }\n\n    /**\n     * Dumps the HTML header.\n     */\n    protected function getDumpHeader(): string\n    {\n        $this->headerIsDumped = $this->outputStream ?? $this->lineDumper;\n\n        if (null !== $this->dumpHeader) {\n            return $this->dumpHeader;\n        }\n\n        $line = str_replace('{$options}', json_encode($this->displayOptions, \\JSON_FORCE_OBJECT), <<<'EOHTML'\n            <script>\n            Sfdump = window.Sfdump || (function (doc) {\n            doc.documentElement.classList.add('sf-js-enabled');\n\n            var rxEsc = /([.*+?^${}()|\\[\\]\\/\\\\])/g,\n                idRx = /\\bsf-dump-\\d+-ref[012]\\w+\\b/,\n                keyHint = 0 <= navigator.platform.toUpperCase().indexOf('MAC') ? 'Cmd' : 'Ctrl',\n                addEventListener = function (e, n, cb) {\n                    e.addEventListener(n, cb, false);\n                };\n\n            if (!doc.addEventListener) {\n                addEventListener = function (element, eventName, callback) {\n                    element.attachEvent('on' + eventName, function (e) {\n                        e.preventDefault = function () {e.returnValue = false;};\n                        e.target = e.srcElement;\n                        callback(e);\n                    });\n                };\n            }\n\n            function toggle(a, recursive) {\n                var s = a.nextSibling || {}, oldClass = s.className, arrow, newClass;\n\n                if (/\\bsf-dump-compact\\b/.test(oldClass)) {\n                    arrow = '▼';\n                    newClass = 'sf-dump-expanded';\n                } else if (/\\bsf-dump-expanded\\b/.test(oldClass)) {\n                    arrow = '▶';\n                    newClass = 'sf-dump-compact';\n                } else {\n                    return false;\n                }\n\n                if (doc.createEvent && s.dispatchEvent) {\n                    var event = doc.createEvent('Event');\n                    event.initEvent('sf-dump-expanded' === newClass ? 'sfbeforedumpexpand' : 'sfbeforedumpcollapse', true, false);\n\n                    s.dispatchEvent(event);\n                }\n\n                a.lastChild.innerHTML = arrow;\n                s.className = s.className.replace(/\\bsf-dump-(compact|expanded)\\b/, newClass);\n\n                if (recursive) {\n                    try {\n                        a = s.querySelectorAll('.'+oldClass);\n                        for (s = 0; s < a.length; ++s) {\n                            if (-1 == a[s].className.indexOf(newClass)) {\n                                a[s].className = newClass;\n                                a[s].previousSibling.lastChild.innerHTML = arrow;\n                            }\n                        }\n                    } catch (e) {\n                    }\n                }\n\n                return true;\n            };\n\n            function collapse(a, recursive) {\n                var s = a.nextSibling || {}, oldClass = s.className;\n\n                if (/\\bsf-dump-expanded\\b/.test(oldClass)) {\n                    toggle(a, recursive);\n\n                    return true;\n                }\n\n                return false;\n            };\n\n            function expand(a, recursive) {\n                var s = a.nextSibling || {}, oldClass = s.className;\n\n                if (/\\bsf-dump-compact\\b/.test(oldClass)) {\n                    toggle(a, recursive);\n\n                    return true;\n                }\n\n                return false;\n            };\n\n            function collapseAll(root) {\n                var a = root.querySelector('a.sf-dump-toggle');\n                if (a) {\n                    collapse(a, true);\n                    expand(a);\n\n                    return true;\n                }\n\n                return false;\n            }\n\n            function reveal(node) {\n                var previous, parents = [];\n\n                while ((node = node.parentNode || {}) && (previous = node.previousSibling) && 'A' === previous.tagName) {\n                    parents.push(previous);\n                }\n\n                if (0 !== parents.length) {\n                    parents.forEach(function (parent) {\n                        expand(parent);\n                    });\n\n                    return true;\n                }\n\n                return false;\n            }\n\n            function highlight(root, activeNode, nodes) {\n                resetHighlightedNodes(root);\n\n                Array.from(nodes||[]).forEach(function (node) {\n                    if (!/\\bsf-dump-highlight\\b/.test(node.className)) {\n                        node.className = node.className + ' sf-dump-highlight';\n                    }\n                });\n\n                if (!/\\bsf-dump-highlight-active\\b/.test(activeNode.className)) {\n                    activeNode.className = activeNode.className + ' sf-dump-highlight-active';\n                }\n            }\n\n            function resetHighlightedNodes(root) {\n                Array.from(root.querySelectorAll('.sf-dump-str, .sf-dump-key, .sf-dump-public, .sf-dump-protected, .sf-dump-private')).forEach(function (strNode) {\n                    strNode.className = strNode.className.replace(/\\bsf-dump-highlight\\b/, '');\n                    strNode.className = strNode.className.replace(/\\bsf-dump-highlight-active\\b/, '');\n                });\n            }\n\n            return function (root, x) {\n                root = doc.getElementById(root);\n\n                var indentRx = new RegExp('^('+(root.getAttribute('data-indent-pad') || '  ').replace(rxEsc, '\\\\$1')+')+', 'm'),\n                    options = {$options},\n                    elt = root.getElementsByTagName('A'),\n                    len = elt.length,\n                    i = 0, s, h,\n                    t = [];\n\n                while (i < len) t.push(elt[i++]);\n\n                for (i in x) {\n                    options[i] = x[i];\n                }\n\n                function a(e, f) {\n                    addEventListener(root, e, function (e, n) {\n                        if ('A' == e.target.tagName) {\n                            f(e.target, e);\n                        } else if ('A' == e.target.parentNode.tagName) {\n                            f(e.target.parentNode, e);\n                        } else {\n                            n = /\\bsf-dump-ellipsis\\b/.test(e.target.className) ? e.target.parentNode : e.target;\n\n                            if ((n = n.nextElementSibling) && 'A' == n.tagName) {\n                                if (!/\\bsf-dump-toggle\\b/.test(n.className)) {\n                                    n = n.nextElementSibling || n;\n                                }\n\n                                f(n, e, true);\n                            }\n                        }\n                    });\n                };\n                function isCtrlKey(e) {\n                    return e.ctrlKey || e.metaKey;\n                }\n                function xpathString(str) {\n                    var parts = str.match(/[^'\"]+|['\"]/g).map(function (part) {\n                        if (\"'\" == part)  {\n                            return '\"\\'\"';\n                        }\n                        if ('\"' == part) {\n                            return \"'\\\"'\";\n                        }\n\n                        return \"'\" + part + \"'\";\n                    });\n\n                    return \"concat(\" + parts.join(\",\") + \", '')\";\n                }\n                function xpathHasClass(className) {\n                    return \"contains(concat(' ', normalize-space(@class), ' '), ' \" + className +\" ')\";\n                }\n                a('mouseover', function (a, e, c) {\n                    if (c) {\n                        e.target.style.cursor = \"pointer\";\n                    }\n                });\n                a('click', function (a, e, c) {\n                    if (/\\bsf-dump-toggle\\b/.test(a.className)) {\n                        e.preventDefault();\n                        if (!toggle(a, isCtrlKey(e))) {\n                            var r = doc.getElementById(a.getAttribute('href').slice(1)),\n                                s = r.previousSibling,\n                                f = r.parentNode,\n                                t = a.parentNode;\n                            t.replaceChild(r, a);\n                            f.replaceChild(a, s);\n                            t.insertBefore(s, r);\n                            f = f.firstChild.nodeValue.match(indentRx);\n                            t = t.firstChild.nodeValue.match(indentRx);\n                            if (f && t && f[0] !== t[0]) {\n                                r.innerHTML = r.innerHTML.replace(new RegExp('^'+f[0].replace(rxEsc, '\\\\$1'), 'mg'), t[0]);\n                            }\n                            if (/\\bsf-dump-compact\\b/.test(r.className)) {\n                                toggle(s, isCtrlKey(e));\n                            }\n                        }\n\n                        if (c) {\n                        } else if (doc.getSelection) {\n                            try {\n                                doc.getSelection().removeAllRanges();\n                            } catch (e) {\n                                doc.getSelection().empty();\n                            }\n                        } else {\n                            doc.selection.empty();\n                        }\n                    } else if (/\\bsf-dump-str-toggle\\b/.test(a.className)) {\n                        e.preventDefault();\n                        e = a.parentNode.parentNode;\n                        e.className = e.className.replace(/\\bsf-dump-str-(expand|collapse)\\b/, a.parentNode.className);\n                    }\n                });\n\n                elt = root.getElementsByTagName('SAMP');\n                len = elt.length;\n                i = 0;\n\n                while (i < len) t.push(elt[i++]);\n                len = t.length;\n\n                for (i = 0; i < len; ++i) {\n                    elt = t[i];\n                    if ('SAMP' == elt.tagName) {\n                        a = elt.previousSibling || {};\n                        if ('A' != a.tagName) {\n                            a = doc.createElement('A');\n                            a.className = 'sf-dump-ref';\n                            elt.parentNode.insertBefore(a, elt);\n                        } else {\n                            a.innerHTML += ' ';\n                        }\n                        a.title = (a.title ? a.title+'\\n[' : '[')+keyHint+'+click] Expand all children';\n                        a.innerHTML += elt.className == 'sf-dump-compact' ? '<span>▶</span>' : '<span>▼</span>';\n                        a.className += ' sf-dump-toggle';\n\n                        x = 1;\n                        if ('sf-dump' != elt.parentNode.className) {\n                            x += elt.parentNode.getAttribute('data-depth')/1;\n                        }\n                    } else if (/\\bsf-dump-ref\\b/.test(elt.className) && (a = elt.getAttribute('href'))) {\n                        a = a.slice(1);\n                        elt.className += ' sf-dump-hover';\n                        elt.className += ' '+a;\n\n                        if (/[\\[{]$/.test(elt.previousSibling.nodeValue)) {\n                            a = a != elt.nextSibling.id && doc.getElementById(a);\n                            try {\n                                s = a.nextSibling;\n                                elt.appendChild(a);\n                                s.parentNode.insertBefore(a, s);\n                                if (/^[@#]/.test(elt.innerHTML)) {\n                                    elt.innerHTML += ' <span>▶</span>';\n                                } else {\n                                    elt.innerHTML = '<span>▶</span>';\n                                    elt.className = 'sf-dump-ref';\n                                }\n                                elt.className += ' sf-dump-toggle';\n                            } catch (e) {\n                                if ('&' == elt.innerHTML.charAt(0)) {\n                                    elt.innerHTML = '…';\n                                    elt.className = 'sf-dump-ref';\n                                }\n                            }\n                        }\n                    }\n                }\n\n                if (doc.evaluate && Array.from && root.children.length > 1) {\n                    root.setAttribute('tabindex', 0);\n\n                    SearchState = function () {\n                        this.nodes = [];\n                        this.idx = 0;\n                    };\n                    SearchState.prototype = {\n                        next: function () {\n                            if (this.isEmpty()) {\n                                return this.current();\n                            }\n                            this.idx = this.idx < (this.nodes.length - 1) ? this.idx + 1 : 0;\n\n                            return this.current();\n                        },\n                        previous: function () {\n                            if (this.isEmpty()) {\n                                return this.current();\n                            }\n                            this.idx = this.idx > 0 ? this.idx - 1 : (this.nodes.length - 1);\n\n                            return this.current();\n                        },\n                        isEmpty: function () {\n                            return 0 === this.count();\n                        },\n                        current: function () {\n                            if (this.isEmpty()) {\n                                return null;\n                            }\n                            return this.nodes[this.idx];\n                        },\n                        reset: function () {\n                            this.nodes = [];\n                            this.idx = 0;\n                        },\n                        count: function () {\n                            return this.nodes.length;\n                        },\n                    };\n\n                    function showCurrent(state)\n                    {\n                        var currentNode = state.current(), currentRect, searchRect;\n                        if (currentNode) {\n                            reveal(currentNode);\n                            highlight(root, currentNode, state.nodes);\n                            if ('scrollIntoView' in currentNode) {\n                                currentNode.scrollIntoView(true);\n                                currentRect = currentNode.getBoundingClientRect();\n                                searchRect = search.getBoundingClientRect();\n                                if (currentRect.top < (searchRect.top + searchRect.height)) {\n                                    window.scrollBy(0, -(searchRect.top + searchRect.height + 5));\n                                }\n                            }\n                        }\n                        counter.textContent = (state.isEmpty() ? 0 : state.idx + 1) + ' of ' + state.count();\n                    }\n\n                    var search = doc.createElement('div');\n                    search.className = 'sf-dump-search-wrapper sf-dump-search-hidden';\n                    search.innerHTML = '\n                        <input type=\"text\" class=\"sf-dump-search-input\">\n                        <span class=\"sf-dump-search-count\">0 of 0<\\/span>\n                        <button type=\"button\" class=\"sf-dump-search-input-previous\" tabindex=\"-1\">\n                            <svg viewBox=\"0 0 1792 1792\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M1683 1331l-166 165q-19 19-45 19t-45-19L896 965l-531 531q-19 19-45 19t-45-19l-166-165q-19-19-19-45.5t19-45.5l742-741q19-19 45-19t45 19l742 741q19 19 19 45.5t-19 45.5z\"\\/><\\/svg>\n                        <\\/button>\n                        <button type=\"button\" class=\"sf-dump-search-input-next\" tabindex=\"-1\">\n                            <svg viewBox=\"0 0 1792 1792\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M1683 808l-742 741q-19 19-45 19t-45-19L109 808q-19-19-19-45.5t19-45.5l166-165q19-19 45-19t45 19l531 531 531-531q19-19 45-19t45 19l166 165q19 19 19 45.5t-19 45.5z\"\\/><\\/svg>\n                        <\\/button>\n                    ';\n                    root.insertBefore(search, root.firstChild);\n\n                    var state = new SearchState();\n                    var searchInput = search.querySelector('.sf-dump-search-input');\n                    var counter = search.querySelector('.sf-dump-search-count');\n                    var searchInputTimer = 0;\n                    var previousSearchQuery = '';\n\n                    addEventListener(searchInput, 'keyup', function (e) {\n                        var searchQuery = e.target.value;\n                        /* Don't perform anything if the pressed key didn't change the query */\n                        if (searchQuery === previousSearchQuery) {\n                            return;\n                        }\n                        previousSearchQuery = searchQuery;\n                        clearTimeout(searchInputTimer);\n                        searchInputTimer = setTimeout(function () {\n                            state.reset();\n                            collapseAll(root);\n                            resetHighlightedNodes(root);\n                            if ('' === searchQuery) {\n                                counter.textContent = '0 of 0';\n\n                                return;\n                            }\n\n                            var classMatches = [\n                                \"sf-dump-str\",\n                                \"sf-dump-key\",\n                                \"sf-dump-public\",\n                                \"sf-dump-protected\",\n                                \"sf-dump-private\",\n                            ].map(xpathHasClass).join(' or ');\n\n                            var xpathResult = doc.evaluate('.//span[' + classMatches + '][contains(translate(child::text(), ' + xpathString(searchQuery.toUpperCase()) + ', ' + xpathString(searchQuery.toLowerCase()) + '), ' + xpathString(searchQuery.toLowerCase()) + ')]', root, null, XPathResult.ORDERED_NODE_ITERATOR_TYPE, null);\n\n                            while (node = xpathResult.iterateNext()) state.nodes.push(node);\n\n                            showCurrent(state);\n                        }, 400);\n                    });\n\n                    Array.from(search.querySelectorAll('.sf-dump-search-input-next, .sf-dump-search-input-previous')).forEach(function (btn) {\n                        addEventListener(btn, 'click', function (e) {\n                            e.preventDefault();\n                            -1 !== e.target.className.indexOf('next') ? state.next() : state.previous();\n                            searchInput.focus();\n                            collapseAll(root);\n                            showCurrent(state);\n                        })\n                    });\n\n                    addEventListener(root, 'keydown', function (e) {\n                        var isSearchActive = !/\\bsf-dump-search-hidden\\b/.test(search.className);\n                        if ((114 === e.keyCode && !isSearchActive) || (isCtrlKey(e) && 70 === e.keyCode)) {\n                            /* F3 or CMD/CTRL + F */\n                            if (70 === e.keyCode && document.activeElement === searchInput) {\n                               /*\n                                * If CMD/CTRL + F is hit while having focus on search input,\n                                * the user probably meant to trigger browser search instead.\n                                * Let the browser execute its behavior:\n                                */\n                                return;\n                            }\n\n                            e.preventDefault();\n                            search.className = search.className.replace(/\\bsf-dump-search-hidden\\b/, '');\n                            searchInput.focus();\n                        } else if (isSearchActive) {\n                            if (27 === e.keyCode) {\n                                /* ESC key */\n                                search.className += ' sf-dump-search-hidden';\n                                e.preventDefault();\n                                resetHighlightedNodes(root);\n                                searchInput.value = '';\n                            } else if (\n                                (isCtrlKey(e) && 71 === e.keyCode) /* CMD/CTRL + G */\n                                || 13 === e.keyCode /* Enter */\n                                || 114 === e.keyCode /* F3 */\n                            ) {\n                                e.preventDefault();\n                                e.shiftKey ? state.previous() : state.next();\n                                collapseAll(root);\n                                showCurrent(state);\n                            }\n                        }\n                    });\n                }\n\n                if (0 >= options.maxStringLength) {\n                    return;\n                }\n                try {\n                    elt = root.querySelectorAll('.sf-dump-str');\n                    len = elt.length;\n                    i = 0;\n                    t = [];\n\n                    while (i < len) t.push(elt[i++]);\n                    len = t.length;\n\n                    for (i = 0; i < len; ++i) {\n                        elt = t[i];\n                        s = elt.innerText || elt.textContent;\n                        x = s.length - options.maxStringLength;\n                        if (0 < x) {\n                            h = elt.innerHTML;\n                            elt[elt.innerText ? 'innerText' : 'textContent'] = s.substring(0, options.maxStringLength);\n                            elt.className += ' sf-dump-str-collapse';\n                            elt.innerHTML = '<span class=sf-dump-str-collapse>'+h+'<a class=\"sf-dump-ref sf-dump-str-toggle\" title=\"Collapse\"> ◀</a></span>'+\n                                '<span class=sf-dump-str-expand>'+elt.innerHTML+'<a class=\"sf-dump-ref sf-dump-str-toggle\" title=\"'+x+' remaining characters\"> ▶</a></span>';\n                        }\n                    }\n                } catch (e) {\n                }\n            };\n\n            })(document);\n            </script><style>\n            .sf-js-enabled pre.sf-dump .sf-dump-compact,\n            .sf-js-enabled .sf-dump-str-collapse .sf-dump-str-collapse,\n            .sf-js-enabled .sf-dump-str-expand .sf-dump-str-expand {\n                display: none;\n            }\n            .sf-dump-hover:hover {\n                background-color: #B729D9;\n                color: #FFF !important;\n                border-radius: 2px;\n            }\n            pre.sf-dump {\n                display: block;\n                white-space: pre;\n                padding: 5px;\n                overflow: initial !important;\n            }\n            pre.sf-dump:after {\n               content: \"\";\n               visibility: hidden;\n               display: block;\n               height: 0;\n               clear: both;\n            }\n            pre.sf-dump .sf-dump-ellipsization {\n                display: inline-flex;\n            }\n            pre.sf-dump a {\n                text-decoration: none;\n                cursor: pointer;\n                border: 0;\n                outline: none;\n                color: inherit;\n            }\n            pre.sf-dump img {\n                max-width: 50em;\n                max-height: 50em;\n                margin: .5em 0 0 0;\n                padding: 0;\n                background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAAAAAA6mKC9AAAAHUlEQVQY02O8zAABilCaiQEN0EeA8QuUcX9g3QEAAjcC5piyhyEAAAAASUVORK5CYII=) #D3D3D3;\n            }\n            pre.sf-dump .sf-dump-ellipsis {\n                text-overflow: ellipsis;\n                white-space: nowrap;\n                overflow: hidden;\n            }\n            pre.sf-dump .sf-dump-ellipsis-tail {\n                flex-shrink: 0;\n            }\n            pre.sf-dump code {\n                display:inline;\n                padding:0;\n                background:none;\n            }\n            .sf-dump-public.sf-dump-highlight,\n            .sf-dump-protected.sf-dump-highlight,\n            .sf-dump-private.sf-dump-highlight,\n            .sf-dump-str.sf-dump-highlight,\n            .sf-dump-key.sf-dump-highlight {\n                background: rgba(111, 172, 204, 0.3);\n                border: 1px solid #7DA0B1;\n                border-radius: 3px;\n            }\n            .sf-dump-public.sf-dump-highlight-active,\n            .sf-dump-protected.sf-dump-highlight-active,\n            .sf-dump-private.sf-dump-highlight-active,\n            .sf-dump-str.sf-dump-highlight-active,\n            .sf-dump-key.sf-dump-highlight-active {\n                background: rgba(253, 175, 0, 0.4);\n                border: 1px solid #ffa500;\n                border-radius: 3px;\n            }\n            pre.sf-dump .sf-dump-search-hidden {\n                display: none !important;\n            }\n            pre.sf-dump .sf-dump-search-wrapper {\n                font-size: 0;\n                white-space: nowrap;\n                margin-bottom: 5px;\n                display: flex;\n                position: -webkit-sticky;\n                position: sticky;\n                top: 5px;\n            }\n            pre.sf-dump .sf-dump-search-wrapper > * {\n                vertical-align: top;\n                box-sizing: border-box;\n                height: 21px;\n                font-weight: normal;\n                border-radius: 0;\n                background: #FFF;\n                color: #757575;\n                border: 1px solid #BBB;\n            }\n            pre.sf-dump .sf-dump-search-wrapper > input.sf-dump-search-input {\n                padding: 3px;\n                height: 21px;\n                font-size: 12px;\n                border-right: none;\n                border-top-left-radius: 3px;\n                border-bottom-left-radius: 3px;\n                color: #000;\n                min-width: 15px;\n                width: 100%;\n            }\n            pre.sf-dump .sf-dump-search-wrapper > .sf-dump-search-input-next,\n            pre.sf-dump .sf-dump-search-wrapper > .sf-dump-search-input-previous {\n                background: #F2F2F2;\n                outline: none;\n                border-left: none;\n                font-size: 0;\n                line-height: 0;\n            }\n            pre.sf-dump .sf-dump-search-wrapper > .sf-dump-search-input-next {\n                border-top-right-radius: 3px;\n                border-bottom-right-radius: 3px;\n            }\n            pre.sf-dump .sf-dump-search-wrapper > .sf-dump-search-input-next > svg,\n            pre.sf-dump .sf-dump-search-wrapper > .sf-dump-search-input-previous > svg {\n                pointer-events: none;\n                width: 12px;\n                height: 12px;\n            }\n            pre.sf-dump .sf-dump-search-wrapper > .sf-dump-search-count {\n                display: inline-block;\n                padding: 0 5px;\n                margin: 0;\n                border-left: none;\n                line-height: 21px;\n                font-size: 12px;\n            }\n            EOHTML\n        );\n\n        foreach ($this->styles as $class => $style) {\n            $line .= 'pre.sf-dump'.('default' === $class ? ', pre.sf-dump' : '').' .sf-dump-'.$class.'{'.$style.'}';\n        }\n        $line .= 'pre.sf-dump .sf-dump-ellipsis-note{'.$this->styles['note'].'}';\n\n        return $this->dumpHeader = preg_replace('/\\s+/', ' ', $line).'</style>'.$this->dumpHeader;\n    }\n\n    public function dumpString(Cursor $cursor, string $str, bool $bin, int $cut): void\n    {\n        if ('' === $str && isset($cursor->attr['img-data'], $cursor->attr['content-type'])) {\n            $this->dumpKey($cursor);\n            $this->line .= $this->style('default', $cursor->attr['img-size'] ?? '', []);\n            $this->line .= $cursor->depth >= $this->displayOptions['maxDepth'] ? ' <samp class=sf-dump-compact>' : ' <samp class=sf-dump-expanded>';\n            $this->endValue($cursor);\n            $this->line .= $this->indentPad;\n            $this->line .= \\sprintf('<img src=\"data:%s;base64,%s\" /></samp>', $cursor->attr['content-type'], base64_encode($cursor->attr['img-data']));\n            $this->endValue($cursor);\n        } else {\n            parent::dumpString($cursor, $str, $bin, $cut);\n        }\n    }\n\n    public function enterHash(Cursor $cursor, int $type, string|int|null $class, bool $hasChild): void\n    {\n        if (Cursor::HASH_OBJECT === $type) {\n            $cursor->attr['depth'] = $cursor->depth;\n        }\n        parent::enterHash($cursor, $type, $class, false);\n\n        if ($cursor->skipChildren || $cursor->depth >= $this->displayOptions['maxDepth']) {\n            $cursor->skipChildren = false;\n            $eol = ' class=sf-dump-compact>';\n        } else {\n            $this->expandNextHash = false;\n            $eol = ' class=sf-dump-expanded>';\n        }\n\n        if ($hasChild) {\n            $this->line .= '<samp data-depth='.($cursor->depth + 1);\n            if ($cursor->refIndex) {\n                $r = Cursor::HASH_OBJECT !== $type ? 1 - (Cursor::HASH_RESOURCE !== $type) : 2;\n                $r .= $r && 0 < $cursor->softRefHandle ? $cursor->softRefHandle : $cursor->refIndex;\n\n                $this->line .= \\sprintf(' id=%s-ref%s', $this->dumpId, $r);\n            }\n            $this->line .= $eol;\n            $this->dumpLine($cursor->depth);\n        }\n    }\n\n    public function leaveHash(Cursor $cursor, int $type, string|int|null $class, bool $hasChild, int $cut): void\n    {\n        $this->dumpEllipsis($cursor, $hasChild, $cut);\n        if ($hasChild) {\n            $this->line .= '</samp>';\n        }\n        parent::leaveHash($cursor, $type, $class, $hasChild, 0);\n    }\n\n    protected function style(string $style, string $value, array $attr = []): string\n    {\n        if ('' === $value && ('label' !== $style || !isset($attr['file']) && !isset($attr['href']))) {\n            return '';\n        }\n\n        $v = esc($value);\n\n        if ('ref' === $style) {\n            if (empty($attr['count'])) {\n                return \\sprintf('<a class=sf-dump-ref>%s</a>', $v);\n            }\n            $r = ('#' !== $v[0] ? 1 - ('@' !== $v[0]) : 2).substr($value, 1);\n\n            return \\sprintf('<a class=sf-dump-ref href=#%s-ref%s title=\"%d occurrences\">%s</a>', $this->dumpId, $r, 1 + $attr['count'], $v);\n        }\n\n        $dumpClasses = ['sf-dump-'.$style];\n        $dumpTitle = '';\n\n        if ('const' === $style && isset($attr['value'])) {\n            $dumpTitle = esc(\\is_scalar($attr['value']) ? $attr['value'] : json_encode($attr['value']));\n        } elseif ('public' === $style) {\n            $dumpTitle = empty($attr['dynamic']) ? 'Public property' : 'Runtime added dynamic property';\n        } elseif ('str' === $style && 1 < $attr['length']) {\n            $dumpTitle = \\sprintf('%d%s characters', $attr['length'], $attr['binary'] ? ' binary or non-UTF-8' : '');\n        } elseif ('note' === $style && 0 < ($attr['depth'] ?? 0) && false !== $c = strrpos($value, '\\\\')) {\n            $attr += [\n                'ellipsis' => \\strlen($value) - $c,\n                'ellipsis-type' => 'note',\n                'ellipsis-tail' => 1,\n            ];\n        } elseif ('protected' === $style) {\n            $dumpTitle = 'Protected property';\n        } elseif ('meta' === $style && isset($attr['title'])) {\n            $dumpTitle = esc($this->utf8Encode($attr['title']));\n        } elseif ('private' === $style) {\n            $dumpTitle = \\sprintf('Private property defined in class:&#10;`%s`', esc($this->utf8Encode($attr['class'])));\n        }\n\n        if (isset($attr['ellipsis'])) {\n            $dumpClasses[] = 'sf-dump-ellipsization';\n            $ellipsisClass = 'sf-dump-ellipsis';\n            if (isset($attr['ellipsis-type'])) {\n                $ellipsisClass .= ' sf-dump-ellipsis-'.$attr['ellipsis-type'];\n            }\n            $label = esc(substr($value, -$attr['ellipsis']));\n            $dumpTitle = $v.\"\\n\".$dumpTitle;\n            $v = \\sprintf('<span class=\"%s\">%s</span>', $ellipsisClass, substr($v, 0, -\\strlen($label)));\n\n            if (!empty($attr['ellipsis-tail'])) {\n                $tail = \\strlen(esc(substr($value, -$attr['ellipsis'], $attr['ellipsis-tail'])));\n                $v .= \\sprintf('<span class=\"%s\">%s</span><span class=\"sf-dump-ellipsis-tail\">%s</span>', $ellipsisClass, substr($label, 0, $tail), substr($label, $tail));\n            } else {\n                $v .= \\sprintf('<span class=\"sf-dump-ellipsis-tail\">%s</span>', $label);\n            }\n        }\n\n        $map = static::$controlCharsMap;\n        $v = \\sprintf(\n            '<span class=%s%s%1$s%s>%s</span>',\n            1 === \\count($dumpClasses) ? '' : '\"',\n            implode(' ', $dumpClasses),\n            $dumpTitle ? ' title=\"'.$dumpTitle.'\"' : '',\n            preg_replace_callback(static::$controlCharsRx, static function ($c) use ($map) {\n                $s = $b = '<span class=\"sf-dump-default';\n                $c = $c[$i = 0];\n                if ($ns = \"\\r\" === $c[$i] || \"\\n\" === $c[$i]) {\n                    $s .= ' sf-dump-ns';\n                }\n                $s .= '\">';\n                do {\n                    if ((\"\\r\" === $c[$i] || \"\\n\" === $c[$i]) !== $ns) {\n                        $s .= '</span>'.$b;\n                        if ($ns = !$ns) {\n                            $s .= ' sf-dump-ns';\n                        }\n                        $s .= '\">';\n                    }\n\n                    $s .= $map[$c[$i]] ?? \\sprintf('\\x%02X', \\ord($c[$i]));\n                } while (isset($c[++$i]));\n\n                return $s.'</span>';\n            }, $v)\n        );\n\n        if (!($attr['binary'] ?? false)) {\n            $v = preg_replace_callback(static::$unicodeCharsRx, static fn ($c) => '<span class=sf-dump-default>\\u{'.strtoupper(dechex(mb_ord($c[0]))).'}</span>', $v);\n        }\n\n        if (isset($attr['file']) && $href = $this->getSourceLink($attr['file'], $attr['line'] ?? 0)) {\n            $attr['href'] = $href;\n        }\n        if (isset($attr['href'])) {\n            if ('label' === $style) {\n                $v .= '^';\n            }\n            $target = isset($attr['file']) ? '' : ' target=\"_blank\"';\n            $v = \\sprintf('<a href=\"%s\"%s rel=\"noopener noreferrer\">%s</a>', esc($this->utf8Encode($attr['href'])), $target, $v);\n        }\n        if (isset($attr['lang'])) {\n            $v = \\sprintf('<code class=\"%s\">%s</code>', esc($attr['lang']), $v);\n        }\n        if ('label' === $style) {\n            $v .= ' ';\n        }\n        if ($attr['virtual'] ?? false) {\n            $v = '<span class=sf-dump-virtual>'.$v.'</span>';\n        }\n\n        return $v;\n    }\n\n    protected function dumpLine(int $depth, bool $endOfValue = false): void\n    {\n        if (-1 === $this->lastDepth) {\n            $this->line = \\sprintf($this->dumpPrefix, $this->dumpId, $this->indentPad).$this->line;\n        }\n        if ($this->headerIsDumped !== ($this->outputStream ?? $this->lineDumper)) {\n            $this->line = $this->getDumpHeader().$this->line;\n        }\n\n        if (-1 === $depth) {\n            $args = ['\"'.$this->dumpId.'\"'];\n            if ($this->extraDisplayOptions) {\n                $args[] = json_encode($this->extraDisplayOptions, \\JSON_FORCE_OBJECT);\n            }\n            // Replace is for BC\n            $this->line .= \\sprintf(str_replace('\"%s\"', '%s', $this->dumpSuffix), implode(', ', $args));\n        }\n        $this->lastDepth = $depth;\n\n        $this->line = mb_encode_numericentity($this->line, [0x80, 0x10FFFF, 0, 0x1FFFFF], 'UTF-8');\n\n        if (-1 === $depth) {\n            AbstractDumper::dumpLine(0);\n        }\n        AbstractDumper::dumpLine($depth);\n    }\n\n    private function getSourceLink(string $file, int $line): string|false\n    {\n        $options = $this->extraDisplayOptions + $this->displayOptions;\n\n        if ($fmt = $options['fileLinkFormat']) {\n            return \\is_string($fmt) ? strtr($fmt, ['%f' => $file, '%l' => $line]) : $fmt->format($file, $line);\n        }\n\n        return false;\n    }\n}\n\nfunction esc(string $str): string\n{\n    return htmlspecialchars($str, \\ENT_QUOTES, 'UTF-8');\n}\n"
  },
  {
    "path": "Dumper/ServerDumper.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Dumper;\n\nuse Symfony\\Component\\VarDumper\\Cloner\\Data;\nuse Symfony\\Component\\VarDumper\\Dumper\\ContextProvider\\ContextProviderInterface;\nuse Symfony\\Component\\VarDumper\\Server\\Connection;\n\n/**\n * ServerDumper forwards serialized Data clones to a server.\n *\n * @author Maxime Steinhausser <maxime.steinhausser@gmail.com>\n */\nclass ServerDumper implements DataDumperInterface\n{\n    private Connection $connection;\n\n    /**\n     * @param string                     $host             The server host\n     * @param DataDumperInterface|null   $wrappedDumper    A wrapped instance used whenever we failed contacting the server\n     * @param ContextProviderInterface[] $contextProviders Context providers indexed by context name\n     */\n    public function __construct(\n        string $host,\n        private ?DataDumperInterface $wrappedDumper = null,\n        array $contextProviders = [],\n    ) {\n        $this->connection = new Connection($host, $contextProviders);\n    }\n\n    public function getContextProviders(): array\n    {\n        return $this->connection->getContextProviders();\n    }\n\n    public function dump(Data $data): ?string\n    {\n        if (!$this->connection->write($data) && $this->wrappedDumper) {\n            return $this->wrappedDumper->dump($data);\n        }\n\n        return null;\n    }\n}\n"
  },
  {
    "path": "Exception/ThrowingCasterException.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Exception;\n\n/**\n * @author Nicolas Grekas <p@tchwork.com>\n */\nclass ThrowingCasterException extends \\Exception\n{\n    /**\n     * @param \\Throwable $prev The exception thrown from the caster\n     */\n    public function __construct(\\Throwable $prev)\n    {\n        parent::__construct('Unexpected '.$prev::class.' thrown from a caster: '.$prev->getMessage(), 0, $prev);\n    }\n}\n"
  },
  {
    "path": "LICENSE",
    "content": "Copyright (c) 2014-present Fabien Potencier\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is furnished\nto do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "VarDumper Component\n===================\n\nThe VarDumper component provides mechanisms for walking through any arbitrary\nPHP variable. It provides a better `dump()` function that you can use instead\nof `var_dump()`.\n\nResources\n---------\n\n * [Documentation](https://symfony.com/doc/current/components/var_dumper/introduction.html)\n * [Contributing](https://symfony.com/doc/current/contributing/index.html)\n * [Report issues](https://github.com/symfony/symfony/issues) and\n   [send Pull Requests](https://github.com/symfony/symfony/pulls)\n   in the [main Symfony repository](https://github.com/symfony/symfony)\n"
  },
  {
    "path": "Resources/bin/var-dump-server",
    "content": "#!/usr/bin/env php\n<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nif ('cli' !== PHP_SAPI) {\n    throw new Exception('This script must be run from the command line.');\n}\n\n/**\n * Starts a dump server to collect and output dumps on a single place with multiple formats support.\n *\n * @author Maxime Steinhausser <maxime.steinhausser@gmail.com>\n */\n\nuse Psr\\Log\\LoggerInterface;\nuse Symfony\\Component\\Console\\Application;\nuse Symfony\\Component\\Console\\Input\\ArgvInput;\nuse Symfony\\Component\\Console\\Input\\InputOption;\nuse Symfony\\Component\\Console\\Logger\\ConsoleLogger;\nuse Symfony\\Component\\Console\\Output\\ConsoleOutput;\nuse Symfony\\Component\\VarDumper\\Command\\ServerDumpCommand;\nuse Symfony\\Component\\VarDumper\\Server\\DumpServer;\n\nfunction includeIfExists(string $file): bool\n{\n    return file_exists($file) && include $file;\n}\n\nif (\n    !includeIfExists(__DIR__ . '/../../../../autoload.php') &&\n    !includeIfExists(__DIR__ . '/../../vendor/autoload.php') &&\n    !includeIfExists(__DIR__ . '/../../../../../../vendor/autoload.php')\n) {\n    fwrite(STDERR, 'Install dependencies using Composer.'.PHP_EOL);\n    exit(1);\n}\n\nif (!class_exists(Application::class)) {\n    fwrite(STDERR, 'You need the \"symfony/console\" component in order to run the VarDumper server.'.PHP_EOL);\n    exit(1);\n}\n\n$input = new ArgvInput();\n$output = new ConsoleOutput();\n$defaultHost = '127.0.0.1:9912';\n$host = $input->getParameterOption(['--host'], $_SERVER['VAR_DUMPER_SERVER'] ?? $defaultHost, true);\n$logger = interface_exists(LoggerInterface::class) ? new ConsoleLogger($output->getErrorOutput()) : null;\n\n$app = new Application();\n\n$app->getDefinition()->addOption(\n    new InputOption('--host', null, InputOption::VALUE_REQUIRED, 'The address the server should listen to', $defaultHost)\n);\n\n$app->addCommand($command = new ServerDumpCommand(new DumpServer($host, $logger)))\n    ->getApplication()\n    ->setDefaultCommand($command->getName(), true)\n    ->run($input, $output)\n;\n"
  },
  {
    "path": "Resources/css/htmlDescriptor.css",
    "content": "body {\n    display: flex;\n    flex-direction: column-reverse;\n    justify-content: flex-end;\n    max-width: 1140px;\n    margin: auto;\n    padding: 15px;\n    word-wrap: break-word;\n    background-color: #F9F9F9;\n    color: #222;\n    font-family: Helvetica, Arial, sans-serif;\n    font-size: 14px;\n    line-height: 1.4;\n}\np {\n    margin: 0;\n}\na {\n    color: #218BC3;\n    text-decoration: none;\n}\na:hover {\n    text-decoration: underline;\n}\n.text-small {\n    font-size: 12px !important;\n}\narticle {\n    margin: 5px;\n    margin-bottom: 10px;\n}\narticle > header > .row {\n    display: flex;\n    flex-direction: row;\n    align-items: baseline;\n    margin-bottom: 10px;\n}\narticle > header > .row > .col {\n    flex: 1;\n    display: flex;\n    align-items: baseline;\n}\narticle > header > .row > h2 {\n    font-size: 14px;\n    color: #222;\n    font-weight: normal;\n    font-family: \"Lucida Console\", monospace, sans-serif;\n    word-break: break-all;\n    margin: 20px 5px 0 0;\n    user-select: all;\n}\narticle > header > .row > h2 > code {\n    white-space: nowrap;\n    user-select: none;\n    color: #cc2255;\n    background-color: #f7f7f9;\n    border: 1px solid #e1e1e8;\n    border-radius: 3px;\n    margin-right: 5px;\n    padding: 0 3px;\n}\narticle > header > .row > time.col {\n    flex: 0;\n    text-align: right;\n    white-space: nowrap;\n    color: #999;\n    font-style: italic;\n}\narticle > header ul.tags {\n    list-style: none;\n    padding: 0;\n    margin: 0;\n    font-size: 12px;\n}\narticle > header ul.tags > li {\n    user-select: all;\n    margin-bottom: 2px;\n}\narticle > header ul.tags > li > span.badge {\n    display: inline-block;\n    padding: .25em .4em;\n    margin-right: 5px;\n    border-radius: 4px;\n    background-color: #6c757d3b;\n    color: #524d4d;\n    font-size: 12px;\n    text-align: center;\n    font-weight: 700;\n    line-height: 1;\n    white-space: nowrap;\n    vertical-align: baseline;\n    user-select: none;\n}\narticle > section.body {\n    border: 1px solid #d8d8d8;\n    background: #FFF;\n    padding: 10px;\n    border-radius: 3px;\n}\npre.sf-dump {\n    border-radius: 3px;\n    margin-bottom: 0;\n}\n.hidden {\n    display: none !important;\n}\n.dumped-tag > .sf-dump {\n    display: inline-block;\n    margin: 0;\n    padding: 1px 5px;\n    line-height: 1.4;\n    vertical-align: top;\n    background-color: transparent;\n    user-select: auto;\n}\n.dumped-tag > pre.sf-dump,\n.dumped-tag > .sf-dump-default {\n    color: #CC7832;\n    background: none;\n}\n.dumped-tag > .sf-dump .sf-dump-str { color: #629755; }\n.dumped-tag > .sf-dump .sf-dump-private,\n.dumped-tag > .sf-dump .sf-dump-protected,\n.dumped-tag > .sf-dump .sf-dump-public { color: #262626; }\n.dumped-tag > .sf-dump .sf-dump-note { color: #6897BB; }\n.dumped-tag > .sf-dump .sf-dump-key { color: #789339; }\n.dumped-tag > .sf-dump .sf-dump-ref { color: #6E6E6E; }\n.dumped-tag > .sf-dump .sf-dump-ellipsis { color: #CC7832; max-width: 100em; }\n.dumped-tag > .sf-dump .sf-dump-ellipsis-path { max-width: 5em; }\n.dumped-tag > .sf-dump .sf-dump-ns { user-select: none; }\n"
  },
  {
    "path": "Resources/functions/dump.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nuse Symfony\\Component\\VarDumper\\Caster\\ScalarStub;\nuse Symfony\\Component\\VarDumper\\VarDumper;\n\nif (!function_exists('dump')) {\n    /**\n     * @author Nicolas Grekas <p@tchwork.com>\n     * @author Alexandre Daubois <alex.daubois@gmail.com>\n     */\n    function dump(mixed ...$vars): mixed\n    {\n        if (!$vars) {\n            VarDumper::dump(new ScalarStub('🐛'));\n\n            return null;\n        }\n\n        if (array_key_exists(0, $vars) && 1 === count($vars)) {\n            VarDumper::dump($vars[0]);\n            $k = 0;\n        } else {\n            foreach ($vars as $k => $v) {\n                VarDumper::dump($v, is_int($k) ? 1 + $k : $k);\n            }\n        }\n\n        if (1 < count($vars)) {\n            return $vars;\n        }\n\n        return $vars[$k];\n    }\n}\n\nif (!function_exists('dd')) {\n    function dd(mixed ...$vars): never\n    {\n        if (!in_array(\\PHP_SAPI, ['cli', 'phpdbg', 'embed'], true) && !headers_sent()) {\n            header('HTTP/1.1 500 Internal Server Error');\n        }\n\n        if (!$vars) {\n            VarDumper::dump(new ScalarStub('🐛'));\n\n            exit(1);\n        }\n\n        if (array_key_exists(0, $vars) && 1 === count($vars)) {\n            VarDumper::dump($vars[0]);\n        } else {\n            foreach ($vars as $k => $v) {\n                VarDumper::dump($v, is_int($k) ? 1 + $k : $k);\n            }\n        }\n\n        exit(1);\n    }\n}\n"
  },
  {
    "path": "Resources/js/htmlDescriptor.js",
    "content": "document.addEventListener('DOMContentLoaded', function() {\n  let prev = null;\n  Array.from(document.getElementsByTagName('article')).reverse().forEach(function (article) {\n    const dedupId = article.dataset.dedupId;\n    if (dedupId === prev) {\n      article.getElementsByTagName('header')[0].classList.add('hidden');\n    }\n    prev = dedupId;\n  });\n});\n"
  },
  {
    "path": "Server/Connection.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Server;\n\nuse Symfony\\Component\\VarDumper\\Cloner\\Data;\nuse Symfony\\Component\\VarDumper\\Dumper\\ContextProvider\\ContextProviderInterface;\n\n/**\n * Forwards serialized Data clones to a server.\n *\n * @author Maxime Steinhausser <maxime.steinhausser@gmail.com>\n */\nclass Connection\n{\n    private string $host;\n\n    /**\n     * @var resource|null\n     */\n    private $socket;\n\n    /**\n     * @param string                     $host             The server host\n     * @param ContextProviderInterface[] $contextProviders Context providers indexed by context name\n     */\n    public function __construct(\n        string $host,\n        private array $contextProviders = [],\n    ) {\n        if (!str_contains($host, '://')) {\n            $host = 'tcp://'.$host;\n        }\n\n        $this->host = $host;\n    }\n\n    public function getContextProviders(): array\n    {\n        return $this->contextProviders;\n    }\n\n    public function write(Data $data): bool\n    {\n        $socketIsFresh = !$this->socket;\n        if (!$this->socket = $this->socket ?: $this->createSocket()) {\n            return false;\n        }\n\n        $context = ['timestamp' => microtime(true)];\n        foreach ($this->contextProviders as $name => $provider) {\n            $context[$name] = $provider->getContext();\n        }\n        $context = array_filter($context);\n        $encodedPayload = base64_encode(serialize([$data, $context])).\"\\n\";\n\n        set_error_handler(static fn () => null);\n        try {\n            if (-1 !== stream_socket_sendto($this->socket, $encodedPayload)) {\n                return true;\n            }\n            if (!$socketIsFresh) {\n                stream_socket_shutdown($this->socket, \\STREAM_SHUT_RDWR);\n                fclose($this->socket);\n                $this->socket = $this->createSocket();\n            }\n            if (-1 !== stream_socket_sendto($this->socket, $encodedPayload)) {\n                return true;\n            }\n        } finally {\n            restore_error_handler();\n        }\n\n        return false;\n    }\n\n    /**\n     * @return resource|null\n     */\n    private function createSocket()\n    {\n        set_error_handler(static fn () => null);\n        try {\n            return stream_socket_client($this->host, $errno, $errstr, 3) ?: null;\n        } finally {\n            restore_error_handler();\n        }\n    }\n}\n"
  },
  {
    "path": "Server/DumpServer.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Server;\n\nuse Psr\\Log\\LoggerInterface;\nuse Symfony\\Component\\VarDumper\\Cloner\\Data;\nuse Symfony\\Component\\VarDumper\\Cloner\\Stub;\n\n/**\n * A server collecting Data clones sent by a ServerDumper.\n *\n * @author Maxime Steinhausser <maxime.steinhausser@gmail.com>\n *\n * @final\n */\nclass DumpServer\n{\n    private string $host;\n\n    /**\n     * @var resource|null\n     */\n    private $socket;\n\n    public function __construct(\n        string $host,\n        private ?LoggerInterface $logger = null,\n    ) {\n        if (!str_contains($host, '://')) {\n            $host = 'tcp://'.$host;\n        }\n\n        $this->host = $host;\n    }\n\n    public function start(): void\n    {\n        if (!$this->socket = stream_socket_server($this->host, $errno, $errstr)) {\n            throw new \\RuntimeException(\\sprintf('Server start failed on \"%s\": ', $this->host).$errstr.' '.$errno);\n        }\n    }\n\n    public function listen(callable $callback): void\n    {\n        if (null === $this->socket) {\n            $this->start();\n        }\n\n        foreach ($this->getMessages() as $clientId => $message) {\n            $this->logger?->info('Received a payload from client {clientId}', ['clientId' => $clientId]);\n\n            $payload = @unserialize(base64_decode($message), ['allowed_classes' => [Data::class, Stub::class]]);\n\n            // Impossible to decode the message, give up.\n            if (false === $payload) {\n                $this->logger?->warning('Unable to decode a message from {clientId} client.', ['clientId' => $clientId]);\n\n                continue;\n            }\n\n            if (!\\is_array($payload) || \\count($payload) < 2 || !$payload[0] instanceof Data || !\\is_array($payload[1])) {\n                $this->logger?->warning('Invalid payload from {clientId} client. Expected an array of two elements (Data $data, array $context)', ['clientId' => $clientId]);\n\n                continue;\n            }\n\n            [$data, $context] = $payload;\n\n            $callback($data, $context, $clientId);\n        }\n    }\n\n    public function getHost(): string\n    {\n        return $this->host;\n    }\n\n    private function getMessages(): iterable\n    {\n        $sockets = [(int) $this->socket => $this->socket];\n        $write = [];\n\n        while (true) {\n            $read = $sockets;\n            stream_select($read, $write, $write, null);\n\n            foreach ($read as $stream) {\n                if ($this->socket === $stream) {\n                    $stream = stream_socket_accept($this->socket);\n                    $sockets[(int) $stream] = $stream;\n                } elseif (feof($stream)) {\n                    unset($sockets[(int) $stream]);\n                    fclose($stream);\n                } else {\n                    yield (int) $stream => fgets($stream);\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Test/VarDumperTestTrait.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Test;\n\nuse PHPUnit\\Framework\\Attributes\\After;\nuse Symfony\\Component\\VarDumper\\Cloner\\VarCloner;\nuse Symfony\\Component\\VarDumper\\Dumper\\CliDumper;\n\n/**\n * @author Nicolas Grekas <p@tchwork.com>\n */\ntrait VarDumperTestTrait\n{\n    /**\n     * @internal\n     */\n    private array $varDumperConfig = [\n        'casters' => [],\n        'flags' => null,\n    ];\n\n    /**\n     * @param array<string, callable> $casters\n     */\n    protected function setUpVarDumper(array $casters, ?int $flags = null): void\n    {\n        $this->varDumperConfig['casters'] = $casters;\n        $this->varDumperConfig['flags'] = $flags;\n    }\n\n    /**\n     * @after\n     */\n    #[After]\n    protected function tearDownVarDumper(): void\n    {\n        $this->varDumperConfig['casters'] = [];\n        $this->varDumperConfig['flags'] = null;\n    }\n\n    public function assertDumpEquals(mixed $expected, mixed $data, int $filter = 0, string $message = ''): void\n    {\n        $this->assertSame($this->prepareExpectation($expected, $filter), $this->getDump($data, null, $filter), $message);\n    }\n\n    public function assertDumpMatchesFormat(mixed $expected, mixed $data, int $filter = 0, string $message = ''): void\n    {\n        $this->assertStringMatchesFormat($this->prepareExpectation($expected, $filter), $this->getDump($data, null, $filter), $message);\n    }\n\n    protected function getDump(mixed $data, string|int|null $key = null, int $filter = 0): ?string\n    {\n        if (null === $flags = $this->varDumperConfig['flags']) {\n            $flags = getenv('DUMP_LIGHT_ARRAY') ? CliDumper::DUMP_LIGHT_ARRAY : 0;\n            $flags |= getenv('DUMP_STRING_LENGTH') ? CliDumper::DUMP_STRING_LENGTH : 0;\n            $flags |= getenv('DUMP_COMMA_SEPARATOR') ? CliDumper::DUMP_COMMA_SEPARATOR : 0;\n        }\n\n        $cloner = new VarCloner();\n        $cloner->addCasters($this->varDumperConfig['casters']);\n        $cloner->setMaxItems(-1);\n        $dumper = new CliDumper(null, null, $flags);\n        $dumper->setColors(false);\n        $data = $cloner->cloneVar($data, $filter)->withRefHandles(false);\n        if (null !== $key && null === $data = $data->seek($key)) {\n            return null;\n        }\n\n        return rtrim($dumper->dump($data, true));\n    }\n\n    private function prepareExpectation(mixed $expected, int $filter): string\n    {\n        if (!\\is_string($expected)) {\n            $expected = $this->getDump($expected, null, $filter);\n        }\n\n        return rtrim($expected);\n    }\n}\n"
  },
  {
    "path": "Tests/Caster/AddressInfoCasterTest.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Tests\\Caster;\n\nuse PHPUnit\\Framework\\Attributes\\RequiresPhpExtension;\nuse PHPUnit\\Framework\\TestCase;\nuse Symfony\\Component\\VarDumper\\Test\\VarDumperTestTrait;\n\n#[RequiresPhpExtension('sockets')]\nclass AddressInfoCasterTest extends TestCase\n{\n    use VarDumperTestTrait;\n\n    public function testCaster()\n    {\n        $xDump = <<<EODUMP\n            AddressInfo {\n              ai_flags: 0\n              ai_family: AF_INET%A\n            }\n            EODUMP;\n\n        $this->assertDumpMatchesFormat($xDump, socket_addrinfo_lookup('localhost')[0]);\n    }\n}\n"
  },
  {
    "path": "Tests/Caster/CasterTest.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Tests\\Caster;\n\nuse PHPUnit\\Framework\\Attributes\\DataProvider;\nuse PHPUnit\\Framework\\TestCase;\nuse Symfony\\Component\\VarDumper\\Caster\\Caster;\nuse Symfony\\Component\\VarDumper\\Test\\VarDumperTestTrait;\n\n/**\n * @author Nicolas Grekas <p@tchwork.com>\n */\nclass CasterTest extends TestCase\n{\n    use VarDumperTestTrait;\n\n    private static array $referenceArray = [\n        'null' => null,\n        'empty' => false,\n        'public' => 'pub',\n        \"\\0~\\0virtual\" => 'virt',\n        \"\\0+\\0dynamic\" => 'dyn',\n        \"\\0*\\0protected\" => 'prot',\n        \"\\0Foo\\0private\" => 'priv',\n    ];\n\n    #[DataProvider('provideFilter')]\n    public function testFilter($filter, $expectedDiff, $listedProperties = null)\n    {\n        if (null === $listedProperties) {\n            $filteredArray = Caster::filter(self::$referenceArray, $filter);\n        } else {\n            $filteredArray = Caster::filter(self::$referenceArray, $filter, $listedProperties);\n        }\n\n        $this->assertSame($expectedDiff, array_diff_assoc(self::$referenceArray, $filteredArray));\n    }\n\n    public static function provideFilter()\n    {\n        return [\n            [\n                0,\n                [],\n            ],\n            [\n                Caster::EXCLUDE_PUBLIC,\n                [\n                    'null' => null,\n                    'empty' => false,\n                    'public' => 'pub',\n                ],\n            ],\n            [\n                Caster::EXCLUDE_NULL,\n                [\n                    'null' => null,\n                ],\n            ],\n            [\n                Caster::EXCLUDE_EMPTY,\n                [\n                    'null' => null,\n                    'empty' => false,\n                ],\n            ],\n            [\n                Caster::EXCLUDE_VIRTUAL,\n                [\n                    \"\\0~\\0virtual\" => 'virt',\n                ],\n            ],\n            [\n                Caster::EXCLUDE_DYNAMIC,\n                [\n                    \"\\0+\\0dynamic\" => 'dyn',\n                ],\n            ],\n            [\n                Caster::EXCLUDE_PROTECTED,\n                [\n                    \"\\0*\\0protected\" => 'prot',\n                ],\n            ],\n            [\n                Caster::EXCLUDE_PRIVATE,\n                [\n                    \"\\0Foo\\0private\" => 'priv',\n                ],\n            ],\n            [\n                Caster::EXCLUDE_VERBOSE,\n                [\n                    'public' => 'pub',\n                    \"\\0*\\0protected\" => 'prot',\n                ],\n                ['public', \"\\0*\\0protected\"],\n            ],\n            [\n                Caster::EXCLUDE_NOT_IMPORTANT,\n                [\n                    'null' => null,\n                    'empty' => false,\n                    \"\\0~\\0virtual\" => 'virt',\n                    \"\\0+\\0dynamic\" => 'dyn',\n                    \"\\0Foo\\0private\" => 'priv',\n                ],\n                ['public', \"\\0*\\0protected\"],\n            ],\n            [\n                Caster::EXCLUDE_VIRTUAL | Caster::EXCLUDE_DYNAMIC,\n                [\n                    \"\\0~\\0virtual\" => 'virt',\n                    \"\\0+\\0dynamic\" => 'dyn',\n                ],\n            ],\n            [\n                Caster::EXCLUDE_NOT_IMPORTANT | Caster::EXCLUDE_VERBOSE,\n                self::$referenceArray,\n                ['public', \"\\0*\\0protected\"],\n            ],\n            [\n                Caster::EXCLUDE_NOT_IMPORTANT | Caster::EXCLUDE_EMPTY,\n                [\n                    'null' => null,\n                    'empty' => false,\n                    \"\\0~\\0virtual\" => 'virt',\n                    \"\\0+\\0dynamic\" => 'dyn',\n                    \"\\0*\\0protected\" => 'prot',\n                    \"\\0Foo\\0private\" => 'priv',\n                ],\n                ['public', 'empty'],\n            ],\n            [\n                Caster::EXCLUDE_VERBOSE | Caster::EXCLUDE_EMPTY | Caster::EXCLUDE_STRICT,\n                [\n                    'empty' => false,\n                ],\n                ['public', 'empty'],\n            ],\n        ];\n    }\n\n    public function testAnonymousClass()\n    {\n        $c = eval('return new class extends stdClass { private $foo = \"foo\"; };');\n\n        $this->assertDumpMatchesFormat(\n            <<<'EOTXT'\n                stdClass@anonymous {\n                  -foo: \"foo\"\n                }\n                EOTXT,\n            $c\n        );\n\n        $c = eval('return new class implements \\Countable { private $foo = \"foo\"; public function count(): int { return 0; } };');\n\n        $this->assertDumpMatchesFormat(\n            <<<'EOTXT'\n                Countable@anonymous {\n                  -foo: \"foo\"\n                }\n                EOTXT,\n            $c\n        );\n    }\n\n    public function testTypeErrorInDebugInfo()\n    {\n        $this->assertDumpMatchesFormat('class@anonymous {}', new class {\n            public function __debugInfo(): array\n            {\n                return ['class' => \\get_class(null)];\n            }\n        });\n    }\n\n    public function testClassHierarchy()\n    {\n        $this->assertDumpMatchesFormat(<<<'DUMP'\n            Symfony\\Component\\VarDumper\\Tests\\Caster\\B {\n              +a: \"a\"\n              #b: \"b\"\n              -c: \"c\"\n              +d: \"d\"\n              #e: \"e\"\n              -f: \"f\"\n            }\n            DUMP,\n            new B()\n        );\n    }\n}\n\nclass A\n{\n    public $a = 'a';\n    protected $b = 'b';\n    private $c = 'c';\n}\n\nclass B extends A\n{\n    public $d = 'd';\n    protected $e = 'e';\n    private $f = 'f';\n}\n"
  },
  {
    "path": "Tests/Caster/CurlCasterTest.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Tests\\Caster;\n\nuse PHPUnit\\Framework\\Attributes\\RequiresPhpExtension;\nuse PHPUnit\\Framework\\TestCase;\nuse Symfony\\Component\\VarDumper\\Test\\VarDumperTestTrait;\n\n#[RequiresPhpExtension('curl')]\nclass CurlCasterTest extends TestCase\n{\n    use VarDumperTestTrait;\n\n    public function testCastCurl()\n    {\n        $ch = curl_init('http://example.com');\n        curl_setopt($ch, \\CURLOPT_RETURNTRANSFER, true);\n        curl_exec($ch);\n\n        $this->assertDumpMatchesFormat(\n            <<<'EODUMP'\n                CurlHandle {\n                  url: \"http://example.com/\"\n                  content_type: \"text/html%S\"\n                  http_code: %d\n                %A\n                }\n                EODUMP,\n            $ch\n        );\n    }\n}\n"
  },
  {
    "path": "Tests/Caster/DOMCasterTest.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Tests\\Caster;\n\nuse PHPUnit\\Framework\\TestCase;\nuse Symfony\\Component\\VarDumper\\Test\\VarDumperTestTrait;\n\nclass DOMCasterTest extends TestCase\n{\n    use VarDumperTestTrait;\n\n    public function testCastImplementation()\n    {\n        $implementation = new \\DOMImplementation();\n\n        $this->assertDumpEquals(<<<'EODUMP'\n            DOMImplementation {\n              Core: \"1.0\"\n              XML: \"2.0\"\n            }\n            EODUMP,\n            $implementation\n        );\n    }\n\n    public function testCastModernImplementation()\n    {\n        $implementation = new \\Dom\\Implementation();\n\n        $this->assertDumpEquals(<<<'EODUMP'\n            Dom\\Implementation {\n              Core: \"1.0\"\n              XML: \"2.0\"\n            }\n            EODUMP,\n            $implementation\n        );\n    }\n\n    public function testCastNode()\n    {\n        $doc = new \\DOMDocument();\n        $doc->loadXML('<foo><bar/></foo>');\n        $node = $doc->documentElement->firstChild;\n\n        $this->assertDumpMatchesFormat(<<<'EODUMP'\n            DOMElement {%A\n              +parentNode: DOMElement {%a…}\n            %A}\n            EODUMP,\n            $node\n        );\n    }\n\n    public function testCastModernNode()\n    {\n        $doc = \\Dom\\XMLDocument::createFromString('<foo><bar/></foo>');\n        $node = $doc->documentElement->firstChild;\n\n        $this->assertDumpMatchesFormat(<<<'EODUMP'\n            Dom\\Element {%A\n              +parentElement: Dom\\Element {#1 …}\n            %A}\n            EODUMP,\n            $node\n        );\n    }\n\n    public function testCastDocument()\n    {\n        $doc = new \\DOMDocument();\n        $doc->loadXML('<foo><bar/></foo>');\n\n        $this->assertDumpMatchesFormat(<<<'EODUMP'\n            DOMDocument {%A\n              xml: \"\"\"\n                <?xml version=\"1.0\"?>\\n\n                <foo>\\n\n                  <bar/>\\n\n                </foo>\\n\n                \"\"\"\n            }\n            EODUMP,\n            $doc\n        );\n    }\n\n    public function testCastXMLDocument()\n    {\n        $doc = \\Dom\\XMLDocument::createFromString('<foo><bar/></foo>');\n\n        $this->assertDumpMatchesFormat(<<<'EODUMP'\n            Dom\\XMLDocument {%A\n              xml: \"\"\"\n                <?xml version=\"1.0\" encoding=\"UTF-8\"?>\\n\n                <foo>\\n\n                  <bar/>\\n\n                </foo>\n                \"\"\"\n            }\n            EODUMP,\n            $doc\n        );\n    }\n\n    public function testCastHTMLDocument()\n    {\n        $doc = \\Dom\\HTMLDocument::createFromString('<!DOCTYPE html><html><body><p>foo</p></body></html>');\n\n        $this->assertDumpMatchesFormat(<<<'EODUMP'\n            Dom\\HTMLDocument {%A\n              html: \"<!DOCTYPE html><html><head></head><body><p>foo</p></body></html>\"\n            }\n            EODUMP,\n            $doc\n        );\n    }\n\n    public function testCastText()\n    {\n        $doc = new \\DOMText('foo');\n\n        $this->assertDumpMatchesFormat(<<<'EODUMP'\n            DOMText {%A\n              +nodeName: \"#text\"\n            %A}\n            EODUMP,\n            $doc\n        );\n    }\n\n    public function testCastModernText()\n    {\n        $text = \\Dom\\HTMLDocument::createEmpty()->createTextNode('foo');\n        $this->assertDumpMatchesFormat(<<<'EODUMP'\n            Dom\\Text {%A\n              +nodeName: \"#text\"\n            %A}\n            EODUMP,\n            $text\n        );\n    }\n\n    public function testCastAttr()\n    {\n        $attr = new \\DOMAttr('attr', 'value');\n\n        $this->assertDumpMatchesFormat(<<<'EODUMP'\n            DOMAttr {%A\n              +nodeName: \"attr\"\n            %A}\n            EODUMP,\n            $attr\n        );\n    }\n\n    public function testCastModernAttr()\n    {\n        $attr = \\Dom\\HTMLDocument::createEmpty()->createAttribute('attr');\n\n        $this->assertDumpMatchesFormat(<<<'EODUMP'\n            Dom\\Attr {%A\n              +nodeName: \"attr\"\n            %A}\n            EODUMP,\n            $attr\n        );\n    }\n\n    public function testCastElement()\n    {\n        $attr = new \\DOMElement('foo');\n\n        $this->assertDumpMatchesFormat(<<<'EODUMP'\n            DOMElement {%A\n              +tagName: \"foo\"\n            %A}\n            EODUMP,\n            $attr\n        );\n    }\n\n    public function testCastModernElement()\n    {\n        $attr = \\Dom\\HTMLDocument::createEmpty()->createElement('foo');\n\n        $this->assertDumpMatchesFormat(<<<'EODUMP'\n            Dom\\HTMLElement {%A\n              +tagName: \"FOO\"\n            %A}\n            EODUMP,\n            $attr\n        );\n    }\n\n    public function testCastDocumentType()\n    {\n        $implementation = new \\DOMImplementation();\n        $type = $implementation->createDocumentType('html', 'publicId', 'systemId');\n\n        $this->assertDumpMatchesFormat(<<<'EODUMP'\n            DOMDocumentType {\n              +nodeName: \"html\"\n              +nodeValue: null\n              +nodeType: XML_DOCUMENT_TYPE_NODE\n            %A}\n            EODUMP,\n            $type\n        );\n    }\n\n    public function testCastModernDocumentType()\n    {\n        $implementation = new \\Dom\\Implementation();\n        $type = $implementation->createDocumentType('html', 'publicId', 'systemId');\n\n        $this->assertDumpMatchesFormat(<<<'EODUMP'\n            Dom\\DocumentType {\n              +nodeType: XML_DOCUMENT_TYPE_NODE\n            %A}\n            EODUMP,\n            $type\n        );\n    }\n\n    public function testCastProcessingInstruction()\n    {\n        $entity = new \\DOMProcessingInstruction('target', 'data');\n\n        $this->assertDumpMatchesFormat(<<<'EODUMP'\n            DOMProcessingInstruction {%A\n              +data: \"data\"\n            }\n            EODUMP,\n            $entity\n        );\n    }\n\n    public function testCastModernProcessingInstruction()\n    {\n        $entity = \\Dom\\HTMLDocument::createEmpty()->createProcessingInstruction('target', 'data');\n\n        $this->assertDumpMatchesFormat(<<<'EODUMP'\n            Dom\\ProcessingInstruction {%A\n              +target: \"target\"\n            }\n            EODUMP,\n            $entity\n        );\n    }\n\n    public function testCastXPath()\n    {\n        $xpath = new \\DOMXPath(new \\DOMDocument());\n\n        $this->assertDumpEquals(<<<'EODUMP'\n            DOMXPath {\n              +document: DOMDocument { …}\n              +registerNodeNamespaces: true\n            }\n            EODUMP,\n            $xpath\n        );\n    }\n\n    public function testCastModernXPath()\n    {\n        $entity = new \\Dom\\XPath(\\Dom\\HTMLDocument::createEmpty());\n\n        $this->assertDumpEquals(<<<'EODUMP'\n            Dom\\XPath {\n              +document: Dom\\HTMLDocument { …}\n              +registerNodeNamespaces: true\n            }\n            EODUMP,\n            $entity\n        );\n    }\n}\n"
  },
  {
    "path": "Tests/Caster/DateCasterTest.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Tests\\Caster;\n\nuse PHPUnit\\Framework\\Attributes\\DataProvider;\nuse PHPUnit\\Framework\\TestCase;\nuse Symfony\\Component\\VarDumper\\Caster\\Caster;\nuse Symfony\\Component\\VarDumper\\Caster\\DateCaster;\nuse Symfony\\Component\\VarDumper\\Cloner\\Stub;\nuse Symfony\\Component\\VarDumper\\Test\\VarDumperTestTrait;\nuse Symfony\\Component\\VarDumper\\Tests\\Fixtures\\DateTimeChild;\n\n/**\n * @author Dany Maillard <danymaillard93b@gmail.com>\n */\nclass DateCasterTest extends TestCase\n{\n    use VarDumperTestTrait;\n\n    private string $previousTimezone;\n\n    protected function setUp(): void\n    {\n        $this->previousTimezone = date_default_timezone_get();\n    }\n\n    protected function tearDown(): void\n    {\n        date_default_timezone_set($this->previousTimezone);\n    }\n\n    #[DataProvider('provideDateTimes')]\n    public function testDumpDateTime($time, $timezone, $xDate, $xTimestamp, $xInfos)\n    {\n        $date = new \\DateTime($time, new \\DateTimeZone($timezone));\n\n        $xDump = <<<EODUMP\n            DateTime @$xTimestamp {\n              date: $xDate\n            }\n            EODUMP;\n\n        $this->assertDumpEquals($xDump, $date);\n    }\n\n    #[DataProvider('provideDateTimes')]\n    public function testDumpDateTimeImmutable($time, $timezone, $xDate, $xTimestamp, $xInfos)\n    {\n        $date = new \\DateTimeImmutable($time, new \\DateTimeZone($timezone));\n\n        $xDump = <<<EODUMP\n            DateTimeImmutable @$xTimestamp {\n              date: $xDate\n            }\n            EODUMP;\n\n        $this->assertDumpEquals($xDump, $date);\n    }\n\n    #[DataProvider('provideDateTimes')]\n    public function testCastDateTime($time, $timezone, $xDate, $xTimestamp, $xInfos)\n    {\n        $stub = new Stub();\n        $date = new \\DateTimeImmutable($time, new \\DateTimeZone($timezone));\n        $cast = DateCaster::castDateTime($date, Caster::castObject($date, \\DateTimeImmutable::class), $stub, false, 0);\n\n        $xDump = <<<EODUMP\n            array:1 [\n              \"\\\\x00~\\\\x00date\" => $xDate\n            ]\n            EODUMP;\n\n        $this->assertDumpEquals($xDump, $cast);\n\n        $xDump = <<<EODUMP\n            Symfony\\Component\\VarDumper\\Caster\\ConstStub {\n              +type: 1\n              +class: \"$xDate\"\n              +value: \"%A$xInfos%A\"\n              +cut: 0\n              +handle: 0\n              +refCount: 0\n              +position: 0\n              +attr: []\n            }\n            EODUMP;\n\n        $this->assertDumpMatchesFormat($xDump, $cast[\"\\0~\\0date\"]);\n    }\n\n    public static function provideDateTimes()\n    {\n        return [\n            ['2017-04-30 00:00:00.000000', 'Europe/Zurich', '2017-04-30 00:00:00.0 Europe/Zurich (+02:00)', 1493503200, 'Sunday, April 30, 2017%Afrom now%ADST On'],\n            ['2017-12-31 00:00:00.000000', 'Europe/Zurich', '2017-12-31 00:00:00.0 Europe/Zurich (+01:00)', 1514674800, 'Sunday, December 31, 2017%Afrom now%ADST Off'],\n            ['2017-04-30 00:00:00.000000', '+02:00', '2017-04-30 00:00:00.0 +02:00', 1493503200, 'Sunday, April 30, 2017%Afrom now'],\n\n            ['2017-04-30 00:00:00.100000', '+00:00', '2017-04-30 00:00:00.100 +00:00', 1493510400, 'Sunday, April 30, 2017%Afrom now'],\n            ['2017-04-30 00:00:00.120000', '+00:00', '2017-04-30 00:00:00.120 +00:00', 1493510400, 'Sunday, April 30, 2017%Afrom now'],\n            ['2017-04-30 00:00:00.123000', '+00:00', '2017-04-30 00:00:00.123 +00:00', 1493510400, 'Sunday, April 30, 2017%Afrom now'],\n            ['2017-04-30 00:00:00.123400', '+00:00', '2017-04-30 00:00:00.123400 +00:00', 1493510400, 'Sunday, April 30, 2017%Afrom now'],\n            ['2017-04-30 00:00:00.123450', '+00:00', '2017-04-30 00:00:00.123450 +00:00', 1493510400, 'Sunday, April 30, 2017%Afrom now'],\n            ['2017-04-30 00:00:00.123456', '+00:00', '2017-04-30 00:00:00.123456 +00:00', 1493510400, 'Sunday, April 30, 2017%Afrom now'],\n        ];\n    }\n\n    #[DataProvider('provideNoTimezoneDateTimes')]\n    public function testCastDateTimeNoTimezone($time, $xDate, $xInfos)\n    {\n        date_default_timezone_set('UTC');\n\n        $stub = new Stub();\n        $date = new NoTimezoneDate($time);\n        $cast = DateCaster::castDateTime($date, Caster::castObject($date, \\DateTime::class), $stub, false, 0);\n\n        $xDump = <<<EODUMP\n            array:1 [\n              \"\\\\x00~\\\\x00date\" => $xDate\n            ]\n            EODUMP;\n\n        $this->assertDumpEquals($xDump, $cast);\n\n        $xDump = <<<EODUMP\n            Symfony\\Component\\VarDumper\\Caster\\ConstStub {\n              +type: 1\n              +class: \"$xDate\"\n              +value: \"%A$xInfos%A\"\n              +cut: 0\n              +handle: 0\n              +refCount: 0\n              +position: 0\n              +attr: []\n            }\n            EODUMP;\n\n        $this->assertDumpMatchesFormat($xDump, $cast[\"\\0~\\0date\"]);\n    }\n\n    public static function provideNoTimezoneDateTimes()\n    {\n        return [\n            ['2017-04-30 00:00:00.000000', '2017-04-30 00:00:00.0 +00:00', 'Sunday, April 30, 2017'],\n            ['2017-04-30 00:00:00.100000', '2017-04-30 00:00:00.100 +00:00', 'Sunday, April 30, 2017'],\n            ['2017-04-30 00:00:00.120000', '2017-04-30 00:00:00.120 +00:00', 'Sunday, April 30, 2017'],\n            ['2017-04-30 00:00:00.123000', '2017-04-30 00:00:00.123 +00:00', 'Sunday, April 30, 2017'],\n            ['2017-04-30 00:00:00.123400', '2017-04-30 00:00:00.123400 +00:00', 'Sunday, April 30, 2017'],\n            ['2017-04-30 00:00:00.123450', '2017-04-30 00:00:00.123450 +00:00', 'Sunday, April 30, 2017'],\n            ['2017-04-30 00:00:00.123456', '2017-04-30 00:00:00.123456 +00:00', 'Sunday, April 30, 2017'],\n        ];\n    }\n\n    public function testCastDateTimeWithAdditionalChildProperty()\n    {\n        $stub = new Stub();\n        $date = new DateTimeChild('2020-02-13 00:00:00.123456', new \\DateTimeZone('Europe/Paris'));\n        $objectCast = Caster::castObject($date, DateTimeChild::class);\n        $dateCast = DateCaster::castDateTime($date, $objectCast, $stub, false, 0);\n\n        $xDate = '2020-02-13 00:00:00.123456 Europe/Paris (+01:00)';\n        $xInfo = 'Thursday, February 13, 2020%Afrom now';\n        $xDump = <<<EODUMP\n            array:2 [\n              \"\\\\x00Symfony\\Component\\VarDumper\\Tests\\Fixtures\\DateTimeChild\\\\x00addedProperty\" => \"foo\"\n              \"\\\\x00~\\\\x00date\" => $xDate\n            ]\n            EODUMP;\n\n        $this->assertDumpEquals($xDump, $dateCast);\n\n        $xDump = <<<EODUMP\n            Symfony\\Component\\VarDumper\\Caster\\ConstStub {\n              +type: 1\n              +class: \"$xDate\"\n              +value: \"%A$xInfo%A\"\n              +cut: 0\n              +handle: 0\n              +refCount: 0\n              +position: 0\n              +attr: []\n            }\n            EODUMP;\n\n        $this->assertDumpMatchesFormat($xDump, $dateCast[\"\\0~\\0date\"]);\n    }\n\n    #[DataProvider('provideIntervals')]\n    public function testDumpInterval($intervalSpec, $ms, $invert, $expected, $xSeconds)\n    {\n        $interval = $this->createInterval($intervalSpec, $ms, $invert);\n\n        $xDump = <<<EODUMP\n            DateInterval {\n              interval: $expected\n            %A}\n            EODUMP;\n\n        $this->assertDumpMatchesFormat($xDump, $interval);\n    }\n\n    #[DataProvider('provideIntervals')]\n    public function testDumpIntervalExcludingVerbosity($intervalSpec, $ms, $invert, $expected, $xSeconds)\n    {\n        $interval = $this->createInterval($intervalSpec, $ms, $invert);\n\n        $xDump = <<<EODUMP\n            DateInterval {\n              interval: $expected\n            }\n            EODUMP;\n\n        $this->assertDumpEquals($xDump, $interval, Caster::EXCLUDE_VERBOSE);\n    }\n\n    #[DataProvider('provideIntervals')]\n    public function testCastInterval($intervalSpec, $ms, $invert, $xInterval, $xSeconds)\n    {\n        $interval = $this->createInterval($intervalSpec, $ms, $invert);\n        $stub = new Stub();\n\n        $cast = DateCaster::castInterval($interval, ['foo' => 'bar'], $stub, false, Caster::EXCLUDE_VERBOSE);\n\n        $xDump = <<<EODUMP\n            array:1 [\n              \"\\\\x00~\\\\x00interval\" => $xInterval\n            ]\n            EODUMP;\n\n        $this->assertDumpEquals($xDump, $cast);\n\n        if (null === $xSeconds) {\n            return;\n        }\n\n        $xDump = <<<EODUMP\n            Symfony\\Component\\VarDumper\\Caster\\ConstStub {\n              +type: 1\n              +class: \"$xInterval\"\n              +value: \"$xSeconds\"\n              +cut: 0\n              +handle: 0\n              +refCount: 0\n              +position: 0\n              +attr: []\n            }\n            EODUMP;\n\n        $this->assertDumpMatchesFormat($xDump, $cast[\"\\0~\\0interval\"]);\n    }\n\n    public static function provideIntervals()\n    {\n        return [\n            ['PT0S', 0, 0, '0s', '0s'],\n            ['PT0S', 0.1, 0, '+ 00:00:00.100', '%is'],\n            ['PT1S', 0, 0, '+ 00:00:01.0', '%is'],\n            ['PT2M', 0, 0, '+ 00:02:00.0', '%is'],\n            ['PT3H', 0, 0, '+ 03:00:00.0', '%ss'],\n            ['P4D', 0, 0, '+ 4d', '%ss'],\n            ['P5M', 0, 0, '+ 5m', null],\n            ['P6Y', 0, 0, '+ 6y', null],\n            ['P1Y2M3DT4H5M6S', 0, 0, '+ 1y 2m 3d 04:05:06.0', null],\n            ['PT1M60S', 0, 0, '+ 00:02:00.0', null],\n            ['PT1H60M', 0, 0, '+ 02:00:00.0', null],\n            ['P1DT24H', 0, 0, '+ 2d', null],\n            ['P1M32D', 0, 0, '+ 1m 32d', null],\n\n            ['PT0S', 0, 1, '0s', '0s'],\n            ['PT0S', 0.1, 1, '- 00:00:00.100', '%is'],\n            ['PT1S', 0, 1, '- 00:00:01.0', '%is'],\n            ['PT2M', 0, 1, '- 00:02:00.0', '%is'],\n            ['PT3H', 0, 1, '- 03:00:00.0', '%ss'],\n            ['P4D', 0, 1, '- 4d', '%ss'],\n            ['P5M', 0, 1, '- 5m', null],\n            ['P6Y', 0, 1, '- 6y', null],\n            ['P1Y2M3DT4H5M6S', 0, 1, '- 1y 2m 3d 04:05:06.0', null],\n            ['PT1M60S', 0, 1, '- 00:02:00.0', null],\n            ['PT1H60M', 0, 1, '- 02:00:00.0', null],\n            ['P1DT24H', 0, 1, '- 2d', null],\n            ['P1M32D', 0, 1, '- 1m 32d', null],\n        ];\n    }\n\n    #[DataProvider('provideTimeZones')]\n    public function testDumpTimeZone($timezone, $expected, $xRegion)\n    {\n        $timezone = new \\DateTimeZone($timezone);\n\n        $xDump = <<<EODUMP\n            DateTimeZone {\n              timezone: $expected\n            %A}\n            EODUMP;\n\n        $this->assertDumpMatchesFormat($xDump, $timezone);\n    }\n\n    #[DataProvider('provideTimeZones')]\n    public function testDumpTimeZoneExcludingVerbosity($timezone, $expected, $xRegion)\n    {\n        $timezone = new \\DateTimeZone($timezone);\n\n        $xDump = <<<EODUMP\n            DateTimeZone {\n              timezone: $expected\n            }\n            EODUMP;\n\n        $this->assertDumpMatchesFormat($xDump, $timezone, Caster::EXCLUDE_VERBOSE);\n    }\n\n    #[DataProvider('provideTimeZones')]\n    public function testCastTimeZone($timezone, $xTimezone, $xRegion)\n    {\n        $timezone = new \\DateTimeZone($timezone);\n        $stub = new Stub();\n\n        $cast = DateCaster::castTimeZone($timezone, ['foo' => 'bar'], $stub, false, Caster::EXCLUDE_VERBOSE);\n\n        $xDump = <<<EODUMP\n            array:1 [\n              \"\\\\x00~\\\\x00timezone\" => $xTimezone\n            ]\n            EODUMP;\n\n        $this->assertDumpMatchesFormat($xDump, $cast);\n\n        $xDump = <<<EODUMP\n            Symfony\\Component\\VarDumper\\Caster\\ConstStub {\n              +type: 1\n              +class: \"$xTimezone\"\n              +value: \"$xRegion\"\n              +cut: 0\n              +handle: 0\n              +refCount: 0\n              +position: 0\n              +attr: []\n            }\n            EODUMP;\n\n        $this->assertDumpMatchesFormat($xDump, $cast[\"\\0~\\0timezone\"]);\n    }\n\n    public static function provideTimeZones()\n    {\n        $xRegion = \\extension_loaded('intl') ? '%s' : '';\n\n        return [\n            // type 1 (UTC offset)\n            ['-12:00', '-12:00', ''],\n            ['+00:00', '+00:00', ''],\n            ['+14:00', '+14:00', ''],\n\n            // type 2 (timezone abbreviation)\n            ['GMT', '+00:00', ''],\n            ['a', '+01:00', ''],\n            ['b', '+02:00', ''],\n            ['z', '+00:00', ''],\n\n            // type 3 (timezone identifier)\n            ['Africa/Tunis', 'Africa/Tunis (%s:00)', $xRegion],\n            ['America/Panama', 'America/Panama (%s:00)', $xRegion],\n            ['Asia/Jerusalem', 'Asia/Jerusalem (%s:00)', $xRegion],\n            ['Atlantic/Canary', 'Atlantic/Canary (%s:00)', $xRegion],\n            ['Australia/Perth', 'Australia/Perth (%s:00)', $xRegion],\n            ['Europe/Zurich', 'Europe/Zurich (%s:00)', $xRegion],\n            ['Pacific/Tahiti', 'Pacific/Tahiti (%s:00)', $xRegion],\n        ];\n    }\n\n    #[DataProvider('providePeriods')]\n    public function testDumpPeriod($start, $interval, $end, $options, $expected, $xDates)\n    {\n        $p = new \\DatePeriod(new \\DateTimeImmutable($start), new \\DateInterval($interval), \\is_int($end) ? $end : new \\DateTime($end), $options);\n\n        $xDump = <<<EODUMP\n            DatePeriod {\n              period: $expected\n            %A}\n            EODUMP;\n\n        $this->assertDumpMatchesFormat($xDump, $p);\n    }\n\n    #[DataProvider('providePeriods')]\n    public function testCastPeriod($start, $interval, $end, $options, $xPeriod, $xDates)\n    {\n        $p = new \\DatePeriod(new \\DateTimeImmutable($start, new \\DateTimeZone('UTC')), new \\DateInterval($interval), \\is_int($end) ? $end : new \\DateTimeImmutable($end, new \\DateTimeZone('UTC')), $options);\n        $stub = new Stub();\n\n        $cast = DateCaster::castPeriod($p, [], $stub, false, 0);\n\n        $xDump = <<<EODUMP\n            array:1 [\n              \"\\\\x00~\\\\x00period\" => $xPeriod\n            ]\n            EODUMP;\n\n        $this->assertDumpEquals($xDump, $cast);\n\n        $xDump = <<<EODUMP\n            Symfony\\Component\\VarDumper\\Caster\\ConstStub {\n              +type: 1\n              +class: \"$xPeriod\"\n              +value: \"%A$xDates%A\"\n              +cut: 0\n              +handle: 0\n              +refCount: 0\n              +position: 0\n              +attr: []\n            }\n            EODUMP;\n\n        $this->assertDumpMatchesFormat($xDump, $cast[\"\\0~\\0period\"]);\n    }\n\n    public static function providePeriods()\n    {\n        $periods = [\n            ['2017-01-01', 'P1D', '2017-01-03', 0, 'every + 1d, from [2017-01-01 00:00:00.0 to 2017-01-03 00:00:00.0[', '1) 2017-01-01%a2) 2017-01-02'],\n            ['2017-01-01', 'P1D', 1, 0, 'every + 1d, from [2017-01-01 00:00:00.0 recurring 2 time/s', '1) 2017-01-01%a2) 2017-01-02'],\n\n            ['2017-01-01', 'P1D', '2017-01-04', 0, 'every + 1d, from [2017-01-01 00:00:00.0 to 2017-01-04 00:00:00.0[', '1) 2017-01-01%a2) 2017-01-02%a3) 2017-01-03'],\n            ['2017-01-01', 'P1D', 2, 0, 'every + 1d, from [2017-01-01 00:00:00.0 recurring 3 time/s', '1) 2017-01-01%a2) 2017-01-02%a3) 2017-01-03'],\n\n            ['2017-01-01', 'P1D', '2017-01-05', 0, 'every + 1d, from [2017-01-01 00:00:00.0 to 2017-01-05 00:00:00.0[', '1) 2017-01-01%a2) 2017-01-02%a1 more'],\n            ['2017-01-01', 'P1D', 3, 0, 'every + 1d, from [2017-01-01 00:00:00.0 recurring 4 time/s', '1) 2017-01-01%a2) 2017-01-02%a3) 2017-01-03%a1 more'],\n\n            ['2017-01-01', 'P1D', '2017-01-21', 0, 'every + 1d, from [2017-01-01 00:00:00.0 to 2017-01-21 00:00:00.0[', '1) 2017-01-01%a17 more'],\n            ['2017-01-01', 'P1D', 19, 0, 'every + 1d, from [2017-01-01 00:00:00.0 recurring 20 time/s', '1) 2017-01-01%a17 more'],\n\n            ['2017-01-01 01:00:00', 'P1D', '2017-01-03 01:00:00', 0, 'every + 1d, from [2017-01-01 01:00:00.0 to 2017-01-03 01:00:00.0[', '1) 2017-01-01 01:00:00.0%a2) 2017-01-02 01:00:00.0'],\n            ['2017-01-01 01:00:00', 'P1D', 1, 0, 'every + 1d, from [2017-01-01 01:00:00.0 recurring 2 time/s', '1) 2017-01-01 01:00:00.0%a2) 2017-01-02 01:00:00.0'],\n\n            ['2017-01-01', 'P1DT1H', '2017-01-03', 0, 'every + 1d 01:00:00.0, from [2017-01-01 00:00:00.0 to 2017-01-03 00:00:00.0[', '1) 2017-01-01 00:00:00.0%a2) 2017-01-02 01:00:00.0'],\n            ['2017-01-01', 'P1DT1H', 1, 0, 'every + 1d 01:00:00.0, from [2017-01-01 00:00:00.0 recurring 2 time/s', '1) 2017-01-01 00:00:00.0%a2) 2017-01-02 01:00:00.0'],\n\n            ['2017-01-01', 'P1D', '2017-01-04', \\DatePeriod::EXCLUDE_START_DATE, 'every + 1d, from ]2017-01-01 00:00:00.0 to 2017-01-04 00:00:00.0[', '1) 2017-01-02%a2) 2017-01-03'],\n            ['2017-01-01', 'P1D', 2, \\DatePeriod::EXCLUDE_START_DATE, 'every + 1d, from ]2017-01-01 00:00:00.0 recurring 2 time/s', '1) 2017-01-02%a2) 2017-01-03'],\n        ];\n\n        return $periods;\n    }\n\n    private function createInterval($intervalSpec, $ms, $invert)\n    {\n        $interval = new \\DateInterval($intervalSpec);\n        $interval->f = $ms;\n        $interval->invert = $invert;\n\n        return $interval;\n    }\n}\n\nclass NoTimezoneDate extends \\DateTime\n{\n    public function getTimezone(): \\DateTimeZone|false\n    {\n        return false;\n    }\n}\n"
  },
  {
    "path": "Tests/Caster/DoctrineCasterTest.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Tests\\Caster;\n\nuse Doctrine\\Common\\Collections\\ArrayCollection;\nuse Doctrine\\ORM\\EntityManagerInterface;\nuse Doctrine\\ORM\\Mapping\\ClassMetadata;\nuse Doctrine\\ORM\\PersistentCollection;\nuse PHPUnit\\Framework\\Attributes\\RequiresMethod;\nuse PHPUnit\\Framework\\TestCase;\nuse Symfony\\Component\\VarDumper\\Test\\VarDumperTestTrait;\n\n#[RequiresMethod(ArrayCollection::class, '__construct')]\nclass DoctrineCasterTest extends TestCase\n{\n    use VarDumperTestTrait;\n\n    public function testCastPersistentCollection()\n    {\n        $classMetadata = new ClassMetadata(__CLASS__);\n\n        $entityManager = $this->createStub(EntityManagerInterface::class);\n        $entityManagerClass = $entityManager::class;\n        $collection = new PersistentCollection($entityManager, $classMetadata, new ArrayCollection(['test']));\n\n        if (property_exists(PersistentCollection::class, 'isDirty')) {\n            // Collections >= 2\n            $expected = <<<EODUMP\n                Doctrine\\ORM\\PersistentCollection {\n                %A\n                  -backRefFieldName: null\n                  -isDirty: false\n                  -em: $entityManagerClass { …%d}\n                  -typeClass: Doctrine\\ORM\\Mapping\\ClassMetadata { …}\n                %A\n                EODUMP;\n        } else {\n            // Collections 1\n            $expected = <<<EODUMP\n                Doctrine\\ORM\\PersistentCollection {\n                %A\n                  -em: $entityManagerClass { …%d}\n                  -backRefFieldName: null\n                  -typeClass: Doctrine\\ORM\\Mapping\\ClassMetadata { …}\n                %A\n                EODUMP;\n        }\n\n        $this->assertDumpMatchesFormat($expected, $collection);\n    }\n}\n"
  },
  {
    "path": "Tests/Caster/ExceptionCasterTest.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Tests\\Caster;\n\nuse PHPUnit\\Framework\\Attributes\\RequiresMethod;\nuse PHPUnit\\Framework\\TestCase;\nuse Symfony\\Component\\ErrorHandler\\Exception\\FlattenException;\nuse Symfony\\Component\\ErrorHandler\\Exception\\SilencedErrorContext;\nuse Symfony\\Component\\VarDumper\\Caster\\Caster;\nuse Symfony\\Component\\VarDumper\\Caster\\ExceptionCaster;\nuse Symfony\\Component\\VarDumper\\Caster\\FrameStub;\nuse Symfony\\Component\\VarDumper\\Caster\\TraceStub;\nuse Symfony\\Component\\VarDumper\\Cloner\\VarCloner;\nuse Symfony\\Component\\VarDumper\\Dumper\\HtmlDumper;\nuse Symfony\\Component\\VarDumper\\Test\\VarDumperTestTrait;\n\nclass ExceptionCasterTest extends TestCase\n{\n    use VarDumperTestTrait;\n\n    private function getTestException($msg, &$ref = null)\n    {\n        return new \\Exception(''.$msg);\n    }\n\n    private function getTestError($msg): \\Error\n    {\n        return new \\Error(''.$msg);\n    }\n\n    private function getTestErrorException($msg): \\ErrorException\n    {\n        return new \\ErrorException(''.$msg);\n    }\n\n    private function getTestSilencedErrorContext(): SilencedErrorContext\n    {\n        return new SilencedErrorContext(\\E_ERROR, __FILE__, __LINE__);\n    }\n\n    protected function tearDown(): void\n    {\n        ExceptionCaster::$srcContext = 1;\n        ExceptionCaster::$traceArgs = true;\n    }\n\n    public function testDefaultSettings()\n    {\n        $ref = ['foo'];\n        $e = $this->getTestException('foo', $ref);\n\n        $expectedDump = <<<'EODUMP'\n            Exception {\n              #message: \"foo\"\n              #code: 0\n              #file: \"%sExceptionCasterTest.php\"\n              #line: %d\n              trace: {\n                %s%eTests%eCaster%eExceptionCasterTest.php:%d {\n                  Symfony\\Component\\VarDumper\\Tests\\Caster\\ExceptionCasterTest->getTestException($msg, &$ref = null)\n                  › {\n                  ›     return new \\Exception(''.$msg);\n                  › }\n                }\n                %s%eTests%eCaster%eExceptionCasterTest.php:%d { …}\n            %A\n            EODUMP;\n\n        $this->assertDumpMatchesFormat($expectedDump, $e);\n        $this->assertSame(['foo'], $ref);\n    }\n\n    public function testDefaultSettingsOnError()\n    {\n        $e = $this->getTestError('foo');\n\n        $expectedDump = <<<'EODUMP'\n            Error {\n              #message: \"foo\"\n              #code: 0\n              #file: \"%sExceptionCasterTest.php\"\n              #line: %d\n              trace: {\n                %s%eTests%eCaster%eExceptionCasterTest.php:%d {\n                  Symfony\\Component\\VarDumper\\Tests\\Caster\\ExceptionCasterTest->getTestError($msg): Error\n                  › {\n                  ›     return new \\Error(''.$msg);\n                  › }\n                }\n                %s%eTests%eCaster%eExceptionCasterTest.php:%d { …}\n            %A\n            EODUMP;\n\n        $this->assertDumpMatchesFormat($expectedDump, $e);\n    }\n\n    public function testDefaultSettingsOnErrorException()\n    {\n        $e = $this->getTestErrorException('foo');\n\n        $expectedDump = <<<'EODUMP'\n            ErrorException {\n              #message: \"foo\"\n              #code: 0\n              #file: \"%sExceptionCasterTest.php\"\n              #line: %d\n              #severity: E_ERROR\n              trace: {\n                %s%eTests%eCaster%eExceptionCasterTest.php:%d {\n                  Symfony\\Component\\VarDumper\\Tests\\Caster\\ExceptionCasterTest->getTestErrorException($msg): ErrorException\n                  › {\n                  ›     return new \\ErrorException(''.$msg);\n                  › }\n                }\n                %s%eTests%eCaster%eExceptionCasterTest.php:%d { …}\n            %A\n            EODUMP;\n\n        $this->assertDumpMatchesFormat($expectedDump, $e);\n    }\n\n    #[RequiresMethod(SilencedErrorContext::class, '__construct')]\n    public function testCastSilencedErrorContext()\n    {\n        $e = $this->getTestSilencedErrorContext();\n\n        $expectedDump = <<<'EODUMP'\n            Symfony\\Component\\ErrorHandler\\Exception\\SilencedErrorContext {\n              +count: 1\n              -severity: E_ERROR\n              trace: {\n                %s%eTests%eCaster%eExceptionCasterTest.php:%d {\n                  › {\n                  ›     return new SilencedErrorContext(\\E_ERROR, __FILE__, __LINE__);\n                  › }\n                }\n              }\n            }\n            EODUMP;\n\n        $this->assertDumpMatchesFormat($expectedDump, $e);\n    }\n\n    public function testSeek()\n    {\n        $e = $this->getTestException(2);\n\n        $expectedDump = <<<'EODUMP'\n            {\n              %s%eTests%eCaster%eExceptionCasterTest.php:%d {\n                Symfony\\Component\\VarDumper\\Tests\\Caster\\ExceptionCasterTest->getTestException($msg, &$ref = null)\n                › {\n                ›     return new \\Exception(''.$msg);\n                › }\n              }\n              %s%eTests%eCaster%eExceptionCasterTest.php:%d { …}\n            %A\n            EODUMP;\n\n        $this->assertStringMatchesFormat($expectedDump, $this->getDump($e, 'trace'));\n    }\n\n    public function testNoArgs()\n    {\n        $e = $this->getTestException(1);\n        ExceptionCaster::$traceArgs = false;\n\n        $expectedDump = <<<'EODUMP'\n            Exception {\n              #message: \"1\"\n              #code: 0\n              #file: \"%sExceptionCasterTest.php\"\n              #line: %d\n              trace: {\n                %sExceptionCasterTest.php:%d {\n                  Symfony\\Component\\VarDumper\\Tests\\Caster\\ExceptionCasterTest->getTestException($msg, &$ref = null)\n                  › {\n                  ›     return new \\Exception(''.$msg);\n                  › }\n                }\n                %s%eTests%eCaster%eExceptionCasterTest.php:%d { …}\n            %A\n            EODUMP;\n\n        $this->assertDumpMatchesFormat($expectedDump, $e);\n    }\n\n    public function testNoSrcContext()\n    {\n        $e = $this->getTestException(1);\n        ExceptionCaster::$srcContext = -1;\n\n        $expectedDump = <<<'EODUMP'\n            Exception {\n              #message: \"1\"\n              #code: 0\n              #file: \"%sExceptionCasterTest.php\"\n              #line: %d\n              trace: {\n                %s%eTests%eCaster%eExceptionCasterTest.php:%d\n                %s%eTests%eCaster%eExceptionCasterTest.php:%d\n            %A\n            EODUMP;\n\n        $this->assertDumpMatchesFormat($expectedDump, $e);\n    }\n\n    public function testShouldReturnTraceForConcreteTwigWithError()\n    {\n        require_once \\dirname(__DIR__).'/Fixtures/Twig.php';\n\n        $innerExc = (new \\__TwigTemplate_VarDumperFixture_u75a09(null, __FILE__))->provideError();\n        $nestingWrapper = new \\stdClass();\n        $nestingWrapper->trace = new TraceStub($innerExc->getTrace());\n\n        $expectedDump = <<<'EODUMP'\n            {\n              +\"trace\": {\n                %sTwig.php:%d {\n                  AbstractTwigTemplate->provideError()\n                  › {\n                  ›     return $this->createError();\n                  › }\n                }\n                %sExceptionCasterTest.php:%d { …}\n            %A\n            EODUMP;\n\n        $this->assertDumpMatchesFormat($expectedDump, $nestingWrapper);\n    }\n\n    public function testHtmlDump()\n    {\n        if (\\ini_get('xdebug.file_link_format') || get_cfg_var('xdebug.file_link_format')) {\n            $this->markTestSkipped('A custom file_link_format is defined.');\n        }\n\n        $e = $this->getTestException(1);\n        ExceptionCaster::$srcContext = -1;\n\n        $cloner = new VarCloner();\n        $cloner->setMaxItems(1);\n        $dumper = new HtmlDumper();\n        $dumper->setDumpHeader('<foo></foo>');\n        $dumper->setDumpBoundaries('<bar>', '</bar>');\n        $dump = $dumper->dump($cloner->cloneVar($e)->withRefHandles(false), true);\n\n        $expectedDump = <<<'EODUMP'\n            <foo></foo><bar><span class=sf-dump-note>Exception</span> {<samp data-depth=1 class=sf-dump-expanded>\n              #<span class=sf-dump-protected title=\"Protected property\">message</span>: \"<span class=sf-dump-str>1</span>\"\n              #<span class=sf-dump-protected title=\"Protected property\">code</span>: <span class=sf-dump-num>0</span>\n              #<span class=sf-dump-protected title=\"Protected property\">file</span>: \"<span class=\"sf-dump-str sf-dump-ellipsization\" title=\"%sExceptionCasterTest.php\n            %d characters\"><span class=\"sf-dump-ellipsis sf-dump-ellipsis-path\">%s%eVarDumper</span><span class=\"sf-dump-ellipsis sf-dump-ellipsis-path\">%e</span><span class=\"sf-dump-ellipsis-tail\">Tests%eCaster%eExceptionCasterTest.php</span></span>\"\n              #<span class=sf-dump-protected title=\"Protected property\">line</span>: <span class=sf-dump-num>%d</span>\n              <span class=sf-dump-meta>trace</span>: {<samp data-depth=2 class=sf-dump-compact>\n                <span class=\"sf-dump-meta sf-dump-ellipsization\" title=\"%sExceptionCasterTest.php\n            Stack level %d.\"><span class=\"sf-dump-ellipsis sf-dump-ellipsis-path\">%s%eVarDumper</span><span class=\"sf-dump-ellipsis sf-dump-ellipsis-path\">%e</span><span class=\"sf-dump-ellipsis-tail\">Tests%eCaster%eExceptionCasterTest.php</span></span>:<span class=sf-dump-num>%d</span>\n                 &#8230;%d\n              </samp>}\n            </samp>}\n            </bar>\n            EODUMP;\n\n        $this->assertStringMatchesFormat($expectedDump, $dump);\n    }\n\n    public function testFrameWithTwig()\n    {\n        require_once \\dirname(__DIR__).'/Fixtures/Twig.php';\n\n        $f = [\n            new FrameStub([\n                'file' => \\dirname(__DIR__).'/Fixtures/Twig.php',\n                'line' => 33,\n                'class' => '__TwigTemplate_VarDumperFixture_u75a09',\n            ]),\n            new FrameStub([\n                'file' => \\dirname(__DIR__).'/Fixtures/Twig.php',\n                'line' => 34,\n                'class' => '__TwigTemplate_VarDumperFixture_u75a09',\n                'object' => new \\__TwigTemplate_VarDumperFixture_u75a09(null, __FILE__),\n            ]),\n        ];\n\n        $expectedDump = <<<'EODUMP'\n            array:2 [\n              0 => {\n                class: \"__TwigTemplate_VarDumperFixture_u75a09\"\n                src: {\n                  %sTwig.php:1 {\n                    ›%s\n                    › foo bar\n                    ›   twig source\n                  }\n                }\n              }\n              1 => {\n                class: \"__TwigTemplate_VarDumperFixture_u75a09\"\n                object: __TwigTemplate_VarDumperFixture_u75a09 {\n                %A\n                }\n                src: {\n                  %sExceptionCasterTest.php:2 {\n                    › foo bar\n                    ›   twig source\n                    ›%s\n                  }\n                }\n              }\n            ]\n            EODUMP;\n\n        $this->assertDumpMatchesFormat($expectedDump, $f);\n    }\n\n    public function testExcludeVerbosity()\n    {\n        $e = $this->getTestException('foo');\n\n        $expectedDump = <<<'EODUMP'\n            Exception {\n              #message: \"foo\"\n              #code: 0\n              #file: \"%sExceptionCasterTest.php\"\n              #line: %d\n            }\n            EODUMP;\n\n        $this->assertDumpMatchesFormat($expectedDump, $e, Caster::EXCLUDE_VERBOSE);\n    }\n\n    public function testAnonymous()\n    {\n        $e = new \\Exception(\\sprintf('Boo \"%s\" ba.', (new class('Foo') extends \\Exception {\n        })::class));\n\n        $expectedDump = <<<'EODUMP'\n            Exception {\n              #message: \"Boo \"Exception@anonymous\" ba.\"\n              #code: 0\n              #file: \"%sExceptionCasterTest.php\"\n              #line: %d\n            }\n            EODUMP;\n\n        $this->assertDumpMatchesFormat($expectedDump, $e, Caster::EXCLUDE_VERBOSE);\n    }\n\n    #[RequiresMethod(FlattenException::class, 'create')]\n    public function testFlattenException()\n    {\n        $f = FlattenException::createFromThrowable(new \\Exception('Hello'));\n\n        $expectedDump = <<<'EODUMP'\n            array:1 [\n              0 => Symfony\\Component\\ErrorHandler\\Exception\\FlattenException {\n                -message: \"Hello\"\n                -code: 0\n                -previous: null\n                -trace: array:%d %a\n                -traceAsString: \"\"…%d\n                -class: \"Exception\"\n                -statusCode: 500\n                -statusText: \"Internal Server Error\"\n                -headers: []\n                -file: \"%sExceptionCasterTest.php\"\n                -line: %d\n                -asString: null\n                -dataRepresentation: ? Symfony\\Component\\VarDumper\\Cloner\\Data\n              }\n            ]\n            EODUMP;\n\n        $this->assertDumpMatchesFormat($expectedDump, [$f], Caster::EXCLUDE_VERBOSE);\n    }\n}\n"
  },
  {
    "path": "Tests/Caster/FFICasterTest.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Tests\\Caster;\n\nuse PHPUnit\\Framework\\Attributes\\DataProvider;\nuse PHPUnit\\Framework\\Attributes\\RequiresPhpExtension;\nuse PHPUnit\\Framework\\TestCase;\nuse Symfony\\Component\\VarDumper\\Caster\\FFICaster;\nuse Symfony\\Component\\VarDumper\\Test\\VarDumperTestTrait;\n\n/**\n * @author Kirill Nesmeyanov <nesk@xakep.ru>\n */\n#[RequiresPhpExtension('ffi')]\nclass FFICasterTest extends TestCase\n{\n    use VarDumperTestTrait;\n\n    /**\n     * @see FFICaster::MAX_STRING_LENGTH\n     */\n    private const MAX_STRING_LENGTH = 255;\n\n    protected function setUp(): void\n    {\n        if (\\in_array(\\PHP_SAPI, ['cli', 'phpdbg'], true) && 'preload' === \\ini_get('ffi.enable')) {\n            return;\n        }\n        if (!filter_var(\\ini_get('ffi.enable'), \\FILTER_VALIDATE_BOOL)) {\n            $this->markTestSkipped('FFI not enabled for CLI SAPI');\n        }\n    }\n\n    public function testCastAnonymousStruct()\n    {\n        $this->assertDumpEquals(<<<'PHP'\n            FFI\\CData<struct <anonymous>> size 4 align 4 {\n              uint32_t x: 0\n            }\n            PHP,\n            \\FFI::cdef()->new('struct { uint32_t x; }')\n        );\n    }\n\n    public function testCastNamedStruct()\n    {\n        $this->assertDumpEquals(<<<'PHP'\n            FFI\\CData<struct Example> size 4 align 4 {\n              uint32_t x: 0\n            }\n            PHP,\n            \\FFI::cdef()->new('struct Example { uint32_t x; }')\n        );\n    }\n\n    public function testCastAnonymousUnion()\n    {\n        $this->assertDumpEquals(<<<'PHP'\n            FFI\\CData<union <anonymous>> size 4 align 4 {\n              uint32_t x: 0\n              uint32_t y: 0\n            }\n            PHP,\n            \\FFI::cdef()->new('union { uint32_t x; uint32_t y; }')\n        );\n    }\n\n    public function testCastNamedUnion()\n    {\n        $this->assertDumpEquals(<<<'PHP'\n            FFI\\CData<union Example> size 4 align 4 {\n              uint32_t x: 0\n              uint32_t y: 0\n            }\n            PHP,\n            \\FFI::cdef()->new('union Example { uint32_t x; uint32_t y; }')\n        );\n    }\n\n    public function testCastAnonymousEnum()\n    {\n        $this->assertDumpEquals(<<<'PHP'\n            FFI\\CData<enum <anonymous>> size 4 align 4 {\n              cdata: 0\n            }\n            PHP,\n            \\FFI::cdef()->new('enum { a, b }')\n        );\n    }\n\n    public function testCastNamedEnum()\n    {\n        $this->assertDumpEquals(<<<'PHP'\n            FFI\\CData<enum Example> size 4 align 4 {\n              cdata: 0\n            }\n            PHP,\n            \\FFI::cdef()->new('enum Example { a, b }')\n        );\n    }\n\n    public static function scalarsDataProvider(): array\n    {\n        return [\n            'int8_t' => ['int8_t', '0', 1, 1],\n            'uint8_t' => ['uint8_t', '0', 1, 1],\n            'int16_t' => ['int16_t', '0', 2, 2],\n            'uint16_t' => ['uint16_t', '0', 2, 2],\n            'int32_t' => ['int32_t', '0', 4, 4],\n            'uint32_t' => ['uint32_t', '0', 4, 4],\n            'int64_t' => ['int64_t', '0', 8, 8],\n            'uint64_t' => ['uint64_t', '0', 8, 8],\n\n            'bool' => ['bool', 'false', 1, 1],\n            'char' => ['char', '\"\\x00\"', 1, 1],\n            'float' => ['float', '0.0', 4, 4],\n            'double' => ['double', '0.0', 8, 8],\n        ];\n    }\n\n    #[DataProvider('scalarsDataProvider')]\n    public function testCastScalar(string $type, string $value, int $size, int $align)\n    {\n        $this->assertDumpEquals(<<<PHP\n            FFI\\CData<$type> size $size align $align {\n              cdata: $value\n            }\n            PHP,\n            \\FFI::cdef()->new($type)\n        );\n    }\n\n    public function testCastVoidFunction()\n    {\n        $abi = \\PHP_OS_FAMILY === 'Windows' ? '[cdecl]' : '[fastcall]';\n\n        $this->assertDumpEquals(<<<PHP\n            $abi callable(): void {\n              returnType: FFI\\CType<void> size 1 align 1 {}\n            }\n            PHP,\n            \\FFI::cdef()->new('void (*)(void)')\n        );\n    }\n\n    public function testCastIntFunction()\n    {\n        $abi = \\PHP_OS_FAMILY === 'Windows' ? '[cdecl]' : '[fastcall]';\n\n        $this->assertDumpEquals(<<<PHP\n            $abi callable(): uint64_t {\n              returnType: FFI\\CType<uint64_t> size 8 align 8 {}\n            }\n            PHP,\n            \\FFI::cdef()->new('unsigned long long (*)(void)')\n        );\n    }\n\n    public function testCastFunctionWithArguments()\n    {\n        $abi = \\PHP_OS_FAMILY === 'Windows' ? '[cdecl]' : '[fastcall]';\n\n        $this->assertDumpEquals(<<<PHP\n            $abi callable(int32_t, char*): void {\n              returnType: FFI\\CType<void> size 1 align 1 {}\n            }\n            PHP,\n            \\FFI::cdef()->new('void (*)(int a, const char* b)')\n        );\n    }\n\n    public function testCastNonCuttedPointerToChar()\n    {\n        $actualMessage = \"Hello World!\\0\";\n\n        $string = \\FFI::cdef()->new('char[100]');\n        $pointer = \\FFI::addr($string[0]);\n        \\FFI::memcpy($pointer, $actualMessage, \\strlen($actualMessage));\n\n        $this->assertDumpEquals(<<<'PHP'\n            FFI\\CData<char*> size 8 align 8 {\n              cdata: \"Hello World!\\x00\"\n            }\n            PHP,\n            $pointer\n        );\n    }\n\n    public function testCastCuttedPointerToChar()\n    {\n        $actualMessage = str_repeat('Hello World!', 30).\"\\0\";\n        $actualLength = \\strlen($actualMessage);\n        $expectedMessage = substr($actualMessage, 0, self::MAX_STRING_LENGTH);\n\n        $string = \\FFI::cdef()->new('char['.$actualLength.']');\n        $pointer = \\FFI::addr($string[0]);\n        \\FFI::memcpy($pointer, $actualMessage, $actualLength);\n\n        // the max length is platform-dependent and can be less than 255,\n        // so we need to cut the expected message to the maximum length\n        // allowed by pages size of the current system\n        $ffi = \\FFI::cdef(<<<C\n                size_t zend_get_page_size(void);\n            C\n        );\n\n        $pageSize = $ffi->zend_get_page_size();\n        $start = $ffi->cast('uintptr_t', $ffi->cast('char*', $pointer))->cdata;\n        $max = min(self::MAX_STRING_LENGTH, ($start | ($pageSize - 1)) - $start);\n        $expectedMessage = substr($expectedMessage, 0, $max);\n\n        $this->assertDumpEquals(<<<PHP\n            FFI\\CData<char*> size 8 align 8 {\n              cdata: \"$expectedMessage\"…\n            }\n            PHP,\n            $pointer\n        );\n    }\n\n    public function testCastNonTrailingCharPointer()\n    {\n        $actualMessage = 'Hello World!';\n        $actualLength = \\strlen($actualMessage);\n\n        $string = \\FFI::cdef()->new('char['.($actualLength + 1).']');\n        $pointer = \\FFI::addr($string[0]);\n        \\FFI::memcpy($pointer, $actualMessage, $actualLength);\n\n        $pointer = \\FFI::cdef()->cast('char*', \\FFI::cdef()->cast('void*', $pointer));\n        $pointer[$actualLength] = \"\\x01\";\n\n        $this->assertDumpMatchesFormat(<<<PHP\n            FFI\\CData<char*> size 8 align 8 {\n              cdata: %A\"$actualMessage%s\"\n            }\n            PHP,\n            $pointer\n        );\n    }\n\n    public function testCastUnionWithDirectReferencedFields()\n    {\n        $ffi = \\FFI::cdef(<<<'CPP'\n            typedef union Event {\n                int32_t x;\n                float y;\n            } Event;\n            CPP\n        );\n\n        $this->assertDumpEquals(<<<'OUTPUT'\n            FFI\\CData<union Event> size 4 align 4 {\n              int32_t x: 0\n              float y: 0.0\n            }\n            OUTPUT,\n            $ffi->new('Event')\n        );\n    }\n\n    public function testCastUnionWithPointerReferencedFields()\n    {\n        $ffi = \\FFI::cdef(<<<'CPP'\n            typedef union Event {\n                void* something;\n                char* string;\n            } Event;\n            CPP\n        );\n\n        $this->assertDumpEquals(<<<'OUTPUT'\n            FFI\\CData<union Event> size 8 align 8 {\n              something?: FFI\\CType<void*> size 8 align 8 {\n                0: FFI\\CType<void> size 1 align 1 {}\n              }\n              string?: FFI\\CType<char*> size 8 align 8 {\n                0: FFI\\CType<char> size 1 align 1 {}\n              }\n            }\n            OUTPUT,\n            $ffi->new('Event')\n        );\n    }\n\n    public function testCastUnionWithMixedFields()\n    {\n        $ffi = \\FFI::cdef(<<<'CPP'\n            typedef union Event {\n                void* a;\n                int32_t b;\n                char* c;\n                ptrdiff_t d;\n            } Event;\n            CPP\n        );\n\n        $this->assertDumpEquals(<<<'OUTPUT'\n            FFI\\CData<union Event> size 8 align 8 {\n              a?: FFI\\CType<void*> size 8 align 8 {\n                0: FFI\\CType<void> size 1 align 1 {}\n              }\n              int32_t b: 0\n              c?: FFI\\CType<char*> size 8 align 8 {\n                0: FFI\\CType<char> size 1 align 1 {}\n              }\n              int64_t d: 0\n            }\n            OUTPUT,\n            $ffi->new('Event')\n        );\n    }\n\n    public function testCastPointerToEmptyScalars()\n    {\n        $ffi = \\FFI::cdef(<<<'CPP'\n            typedef struct {\n                int8_t *a;\n                uint8_t *b;\n                int64_t *c;\n                uint64_t *d;\n                float *e;\n                double *f;\n                bool *g;\n            } Example;\n            CPP\n        );\n\n        $this->assertDumpEquals(<<<'OUTPUT'\n            FFI\\CData<struct <anonymous>> size 56 align 8 {\n              int8_t* a: null\n              uint8_t* b: null\n              int64_t* c: null\n              uint64_t* d: null\n              float* e: null\n              double* f: null\n              bool* g: null\n            }\n            OUTPUT,\n            $ffi->new('Example')\n        );\n    }\n\n    public function testCastPointerToNonEmptyScalars()\n    {\n        $ffi = \\FFI::cdef(<<<'CPP'\n            typedef struct {\n                int8_t *a;\n                uint8_t *b;\n                int64_t *c;\n                uint64_t *d;\n                float *e;\n                double *f;\n                bool *g;\n            } Example;\n            CPP\n        );\n\n        // Create values\n        $int = \\FFI::cdef()->new('int64_t');\n        $int->cdata = 42;\n        $float = \\FFI::cdef()->new('float');\n        $float->cdata = 42.0;\n        $double = \\FFI::cdef()->new('double');\n        $double->cdata = 42.2;\n        $bool = \\FFI::cdef()->new('bool');\n        $bool->cdata = true;\n\n        // Fill struct\n        $struct = $ffi->new('Example');\n        $struct->a = \\FFI::addr(\\FFI::cdef()->cast('int8_t', $int));\n        $struct->b = \\FFI::addr(\\FFI::cdef()->cast('uint8_t', $int));\n        $struct->c = \\FFI::addr(\\FFI::cdef()->cast('int64_t', $int));\n        $struct->d = \\FFI::addr(\\FFI::cdef()->cast('uint64_t', $int));\n        $struct->e = \\FFI::addr(\\FFI::cdef()->cast('float', $float));\n        $struct->f = \\FFI::addr(\\FFI::cdef()->cast('double', $double));\n        $struct->g = \\FFI::addr(\\FFI::cdef()->cast('bool', $bool));\n\n        $this->assertDumpEquals(<<<'OUTPUT'\n            FFI\\CData<struct <anonymous>> size 56 align 8 {\n              a: FFI\\CData<int8_t*> size 8 align 8 {\n                cdata: 42\n              }\n              b: FFI\\CData<uint8_t*> size 8 align 8 {\n                cdata: 42\n              }\n              c: FFI\\CData<int64_t*> size 8 align 8 {\n                cdata: 42\n              }\n              d: FFI\\CData<uint64_t*> size 8 align 8 {\n                cdata: 42\n              }\n              e: FFI\\CData<float*> size 8 align 8 {\n                cdata: 42.0\n              }\n              f: FFI\\CData<double*> size 8 align 8 {\n                cdata: 42.2\n              }\n              g: FFI\\CData<bool*> size 8 align 8 {\n                cdata: true\n              }\n            }\n            OUTPUT,\n            $struct\n        );\n    }\n\n    public function testCastPointerToStruct()\n    {\n        $ffi = \\FFI::cdef(<<<'CPP'\n            typedef struct {\n                int8_t a;\n            } Example;\n            CPP\n        );\n\n        $struct = $ffi->new('Example', false);\n\n        $this->assertDumpEquals(<<<'OUTPUT'\n            FFI\\CData<struct <anonymous>*> size 8 align 8 {\n              cdata: FFI\\CData<struct <anonymous>> size 1 align 1 {\n                int8_t a: 0\n              }\n            }\n            OUTPUT,\n            \\FFI::addr($struct)\n        );\n\n        // Save the pointer as variable so that\n        // it is not cleaned up by the GC\n        $pointer = \\FFI::addr($struct);\n\n        $this->assertDumpEquals(<<<'OUTPUT'\n            FFI\\CData<struct <anonymous>**> size 8 align 8 {\n              cdata: FFI\\CData<struct <anonymous>*> size 8 align 8 {\n                cdata: FFI\\CData<struct <anonymous>> size 1 align 1 {\n                  int8_t a: 0\n                }\n              }\n            }\n            OUTPUT,\n            \\FFI::addr($pointer)\n        );\n\n        \\FFI::free($struct);\n    }\n\n    public function testCastComplexType()\n    {\n        $ffi = \\FFI::cdef(<<<'CPP'\n            typedef struct {\n                int x;\n                int y;\n            } Point;\n            typedef struct Example {\n                uint8_t a[32];\n                long b;\n                __extension__ union {\n                    __extension__ struct {\n                        short c;\n                        long d;\n                    };\n                    struct {\n                        Point point;\n                        float e;\n                    };\n                };\n                short f;\n                bool g;\n                int (*func)(\n                    struct __sub *h\n                );\n            } Example;\n            CPP\n        );\n\n        $var = $ffi->new('Example');\n        $var->func = (static fn (object $p) => 42);\n\n        $abi = \\PHP_OS_FAMILY === 'Windows' ? '[cdecl]' : '[fastcall]';\n        $longSize = \\FFI::cdef()->type('long')->getSize();\n        $longType = 8 === $longSize ? 'int64_t' : 'int32_t';\n        $structSize = 56 + $longSize * 2;\n\n        $this->assertDumpEquals(<<<OUTPUT\n            FFI\\CData<struct Example> size $structSize align 8 {\n              a: FFI\\CData<uint8_t[32]> size 32 align 1 {}\n              $longType b: 0\n              int16_t c: 0\n              $longType d: 0\n              point: FFI\\CData<struct <anonymous>> size 8 align 4 {\n                int32_t x: 0\n                int32_t y: 0\n              }\n              float e: 0.0\n              int16_t f: 0\n              bool g: false\n              func: $abi callable(struct __sub*): int32_t {\n                returnType: FFI\\CType<int32_t> size 4 align 4 {}\n              }\n            }\n            OUTPUT,\n            $var\n        );\n    }\n}\n"
  },
  {
    "path": "Tests/Caster/FiberCasterTest.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Tests\\Caster;\n\nuse PHPUnit\\Framework\\TestCase;\nuse Symfony\\Component\\VarDumper\\Test\\VarDumperTestTrait;\n\nclass FiberCasterTest extends TestCase\n{\n    use VarDumperTestTrait;\n\n    public function testCastFiberNotStarted()\n    {\n        $fiber = new \\Fiber(static fn () => true);\n\n        $expected = <<<EODUMP\n            Fiber {\n              status: \"not started\"\n            }\n            EODUMP;\n\n        $this->assertDumpEquals($expected, $fiber);\n    }\n\n    public function testCastFiberTerminated()\n    {\n        $fiber = new \\Fiber(static fn () => true);\n        $fiber->start();\n\n        $expected = <<<EODUMP\n            Fiber {\n              status: \"terminated\"\n            }\n            EODUMP;\n\n        $this->assertDumpEquals($expected, $fiber);\n    }\n\n    public function testCastFiberSuspended()\n    {\n        $fiber = new \\Fiber(\\Fiber::suspend(...));\n        $fiber->start();\n\n        $expected = <<<EODUMP\n            Fiber {\n              status: \"suspended\"\n            }\n            EODUMP;\n\n        $this->assertDumpEquals($expected, $fiber);\n    }\n\n    public function testCastFiberRunning()\n    {\n        $fiber = new \\Fiber(function () {\n            $expected = <<<EODUMP\n                Fiber {\n                  status: \"running\"\n                }\n                EODUMP;\n\n            $this->assertDumpEquals($expected, \\Fiber::getCurrent());\n        });\n\n        $fiber->start();\n    }\n}\n"
  },
  {
    "path": "Tests/Caster/GmpCasterTest.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Tests\\Caster;\n\nuse PHPUnit\\Framework\\Attributes\\RequiresPhpExtension;\nuse PHPUnit\\Framework\\TestCase;\nuse Symfony\\Component\\VarDumper\\Caster\\GmpCaster;\nuse Symfony\\Component\\VarDumper\\Cloner\\Stub;\nuse Symfony\\Component\\VarDumper\\Test\\VarDumperTestTrait;\n\nclass GmpCasterTest extends TestCase\n{\n    use VarDumperTestTrait;\n\n    #[RequiresPhpExtension('gmp')]\n    public function testCastGmp()\n    {\n        $gmpString = gmp_init('1234');\n        $gmpOctal = gmp_init(0o10);\n        $gmp = gmp_init('01101');\n        $gmpDump = <<<EODUMP\n            array:1 [\n              \"\\\\x00~\\\\x00value\" => %s\n            ]\n            EODUMP;\n        $this->assertDumpEquals(\\sprintf($gmpDump, $gmpString), GmpCaster::castGmp($gmpString, [], new Stub(), false, 0));\n        $this->assertDumpEquals(\\sprintf($gmpDump, $gmpOctal), GmpCaster::castGmp($gmpOctal, [], new Stub(), false, 0));\n        $this->assertDumpEquals(\\sprintf($gmpDump, $gmp), GmpCaster::castGmp($gmp, [], new Stub(), false, 0));\n\n        $dump = <<<EODUMP\n            GMP {\n              value: 577\n            }\n            EODUMP;\n\n        $this->assertDumpEquals($dump, $gmp);\n    }\n}\n"
  },
  {
    "path": "Tests/Caster/IntlCasterTest.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Tests\\Caster;\n\nuse PHPUnit\\Framework\\Attributes\\RequiresPhpExtension;\nuse PHPUnit\\Framework\\TestCase;\nuse Symfony\\Component\\VarDumper\\Test\\VarDumperTestTrait;\n\n#[RequiresPhpExtension('intl')]\nclass IntlCasterTest extends TestCase\n{\n    use VarDumperTestTrait;\n\n    public function testMessageFormatter()\n    {\n        $var = new \\MessageFormatter('en', 'Hello {name}');\n\n        $expected = <<<EOTXT\n            MessageFormatter {\n              locale: \"en\"\n              pattern: \"Hello {name}\"\n            }\n            EOTXT;\n        $this->assertDumpEquals($expected, $var);\n    }\n\n    public function testCastNumberFormatter()\n    {\n        $var = new \\NumberFormatter('en', \\NumberFormatter::DECIMAL);\n\n        $expectedLocale = $var->getLocale();\n        $expectedPattern = $var->getPattern();\n\n        $expectedAttribute1 = $var->getAttribute(\\NumberFormatter::PARSE_INT_ONLY);\n        $expectedAttribute2 = $var->getAttribute(\\NumberFormatter::GROUPING_USED);\n        $expectedAttribute3 = $var->getAttribute(\\NumberFormatter::DECIMAL_ALWAYS_SHOWN);\n        $expectedAttribute4 = $var->getAttribute(\\NumberFormatter::MAX_INTEGER_DIGITS);\n        $expectedAttribute5 = $var->getAttribute(\\NumberFormatter::MIN_INTEGER_DIGITS);\n        $expectedAttribute6 = $var->getAttribute(\\NumberFormatter::INTEGER_DIGITS);\n        $expectedAttribute7 = $var->getAttribute(\\NumberFormatter::MAX_FRACTION_DIGITS);\n        $expectedAttribute8 = $var->getAttribute(\\NumberFormatter::MIN_FRACTION_DIGITS);\n        $expectedAttribute9 = $var->getAttribute(\\NumberFormatter::FRACTION_DIGITS);\n        $expectedAttribute10 = $var->getAttribute(\\NumberFormatter::MULTIPLIER);\n        $expectedAttribute11 = $var->getAttribute(\\NumberFormatter::GROUPING_SIZE);\n        $expectedAttribute12 = $var->getAttribute(\\NumberFormatter::ROUNDING_MODE);\n        $expectedAttribute13 = number_format($var->getAttribute(\\NumberFormatter::ROUNDING_INCREMENT), 1);\n        $expectedAttribute14 = $this->getDump($var->getAttribute(\\NumberFormatter::FORMAT_WIDTH));\n        $expectedAttribute15 = $var->getAttribute(\\NumberFormatter::PADDING_POSITION);\n        $expectedAttribute16 = $var->getAttribute(\\NumberFormatter::SECONDARY_GROUPING_SIZE);\n        $expectedAttribute17 = $var->getAttribute(\\NumberFormatter::SIGNIFICANT_DIGITS_USED);\n        $expectedAttribute18 = $this->getDump($var->getAttribute(\\NumberFormatter::MIN_SIGNIFICANT_DIGITS));\n        $expectedAttribute19 = $this->getDump($var->getAttribute(\\NumberFormatter::MAX_SIGNIFICANT_DIGITS));\n        $expectedAttribute20 = $var->getAttribute(\\NumberFormatter::LENIENT_PARSE);\n\n        $expectedTextAttribute1 = $var->getTextAttribute(\\NumberFormatter::POSITIVE_PREFIX);\n        $expectedTextAttribute2 = $var->getTextAttribute(\\NumberFormatter::POSITIVE_SUFFIX);\n        $expectedTextAttribute3 = $var->getTextAttribute(\\NumberFormatter::NEGATIVE_PREFIX);\n        $expectedTextAttribute4 = $var->getTextAttribute(\\NumberFormatter::NEGATIVE_SUFFIX);\n        $expectedTextAttribute5 = $var->getTextAttribute(\\NumberFormatter::PADDING_CHARACTER);\n        $expectedTextAttribute6 = $var->getTextAttribute(\\NumberFormatter::CURRENCY_CODE);\n        $expectedTextAttribute7 = $var->getTextAttribute(\\NumberFormatter::DEFAULT_RULESET) ? 'true' : 'false';\n        $expectedTextAttribute8 = $var->getTextAttribute(\\NumberFormatter::PUBLIC_RULESETS) ? 'true' : 'false';\n\n        $expectedSymbol1 = $var->getSymbol(\\NumberFormatter::DECIMAL_SEPARATOR_SYMBOL);\n        $expectedSymbol2 = $var->getSymbol(\\NumberFormatter::GROUPING_SEPARATOR_SYMBOL);\n        $expectedSymbol3 = $var->getSymbol(\\NumberFormatter::PATTERN_SEPARATOR_SYMBOL);\n        $expectedSymbol4 = $var->getSymbol(\\NumberFormatter::PERCENT_SYMBOL);\n        $expectedSymbol5 = $var->getSymbol(\\NumberFormatter::ZERO_DIGIT_SYMBOL);\n        $expectedSymbol6 = $var->getSymbol(\\NumberFormatter::DIGIT_SYMBOL);\n        $expectedSymbol7 = $var->getSymbol(\\NumberFormatter::MINUS_SIGN_SYMBOL);\n        $expectedSymbol8 = $var->getSymbol(\\NumberFormatter::PLUS_SIGN_SYMBOL);\n        $expectedSymbol9 = $var->getSymbol(\\NumberFormatter::CURRENCY_SYMBOL);\n        $expectedSymbol10 = $var->getSymbol(\\NumberFormatter::INTL_CURRENCY_SYMBOL);\n        $expectedSymbol11 = $var->getSymbol(\\NumberFormatter::MONETARY_SEPARATOR_SYMBOL);\n        $expectedSymbol12 = $var->getSymbol(\\NumberFormatter::EXPONENTIAL_SYMBOL);\n        $expectedSymbol13 = $var->getSymbol(\\NumberFormatter::PERMILL_SYMBOL);\n        $expectedSymbol14 = $var->getSymbol(\\NumberFormatter::PAD_ESCAPE_SYMBOL);\n        $expectedSymbol15 = $var->getSymbol(\\NumberFormatter::INFINITY_SYMBOL);\n        $expectedSymbol16 = $var->getSymbol(\\NumberFormatter::NAN_SYMBOL);\n        $expectedSymbol17 = $var->getSymbol(\\NumberFormatter::SIGNIFICANT_DIGIT_SYMBOL);\n        $expectedSymbol18 = $var->getSymbol(\\NumberFormatter::MONETARY_GROUPING_SEPARATOR_SYMBOL);\n\n        $expected = <<<EOTXT\n            NumberFormatter {\n              locale: \"$expectedLocale\"\n              pattern: \"$expectedPattern\"\n              attributes: {\n                PARSE_INT_ONLY: $expectedAttribute1\n                GROUPING_USED: $expectedAttribute2\n                DECIMAL_ALWAYS_SHOWN: $expectedAttribute3\n                MAX_INTEGER_DIGITS: $expectedAttribute4\n                MIN_INTEGER_DIGITS: $expectedAttribute5\n                INTEGER_DIGITS: $expectedAttribute6\n                MAX_FRACTION_DIGITS: $expectedAttribute7\n                MIN_FRACTION_DIGITS: $expectedAttribute8\n                FRACTION_DIGITS: $expectedAttribute9\n                MULTIPLIER: $expectedAttribute10\n                GROUPING_SIZE: $expectedAttribute11\n                ROUNDING_MODE: $expectedAttribute12\n                ROUNDING_INCREMENT: $expectedAttribute13\n                FORMAT_WIDTH: $expectedAttribute14\n                PADDING_POSITION: $expectedAttribute15\n                SECONDARY_GROUPING_SIZE: $expectedAttribute16\n                SIGNIFICANT_DIGITS_USED: $expectedAttribute17\n                MIN_SIGNIFICANT_DIGITS: $expectedAttribute18\n                MAX_SIGNIFICANT_DIGITS: $expectedAttribute19\n                LENIENT_PARSE: $expectedAttribute20\n              }\n              text_attributes: {\n                POSITIVE_PREFIX: \"$expectedTextAttribute1\"\n                POSITIVE_SUFFIX: \"$expectedTextAttribute2\"\n                NEGATIVE_PREFIX: \"$expectedTextAttribute3\"\n                NEGATIVE_SUFFIX: \"$expectedTextAttribute4\"\n                PADDING_CHARACTER: \"$expectedTextAttribute5\"\n                CURRENCY_CODE: \"$expectedTextAttribute6\"\n                DEFAULT_RULESET: $expectedTextAttribute7\n                PUBLIC_RULESETS: $expectedTextAttribute8\n              }\n              symbols: {\n                DECIMAL_SEPARATOR_SYMBOL: \"$expectedSymbol1\"\n                GROUPING_SEPARATOR_SYMBOL: \"$expectedSymbol2\"\n                PATTERN_SEPARATOR_SYMBOL: \"$expectedSymbol3\"\n                PERCENT_SYMBOL: \"$expectedSymbol4\"\n                ZERO_DIGIT_SYMBOL: \"$expectedSymbol5\"\n                DIGIT_SYMBOL: \"$expectedSymbol6\"\n                MINUS_SIGN_SYMBOL: \"$expectedSymbol7\"\n                PLUS_SIGN_SYMBOL: \"$expectedSymbol8\"\n                CURRENCY_SYMBOL: \"$expectedSymbol9\"\n                INTL_CURRENCY_SYMBOL: \"$expectedSymbol10\"\n                MONETARY_SEPARATOR_SYMBOL: \"$expectedSymbol11\"\n                EXPONENTIAL_SYMBOL: \"$expectedSymbol12\"\n                PERMILL_SYMBOL: \"$expectedSymbol13\"\n                PAD_ESCAPE_SYMBOL: \"$expectedSymbol14\"\n                INFINITY_SYMBOL: \"$expectedSymbol15\"\n                NAN_SYMBOL: \"$expectedSymbol16\"\n                SIGNIFICANT_DIGIT_SYMBOL: \"$expectedSymbol17\"\n                MONETARY_GROUPING_SEPARATOR_SYMBOL: \"$expectedSymbol18\"\n              }\n            }\n            EOTXT;\n        $this->assertDumpEquals($expected, $var);\n    }\n\n    public function testCastIntlTimeZoneWithDST()\n    {\n        $var = \\IntlTimeZone::createTimeZone('America/Los_Angeles');\n\n        $expectedDisplayName = $var->getDisplayName();\n        $expectedDSTSavings = $var->getDSTSavings();\n        $expectedID = $var->getID();\n        $expectedRawOffset = $var->getRawOffset();\n\n        $expected = <<<EOTXT\n            IntlTimeZone {\n              display_name: \"$expectedDisplayName\"\n              id: \"$expectedID\"\n              raw_offset: $expectedRawOffset\n              dst_savings: $expectedDSTSavings\n            }\n            EOTXT;\n        $this->assertDumpEquals($expected, $var);\n    }\n\n    public function testCastIntlTimeZoneWithoutDST()\n    {\n        $var = \\IntlTimeZone::createTimeZone('Asia/Bangkok');\n\n        $expectedDisplayName = $var->getDisplayName();\n        $expectedID = $var->getID();\n        $expectedRawOffset = $var->getRawOffset();\n\n        $expected = <<<EOTXT\n            IntlTimeZone {\n              display_name: \"$expectedDisplayName\"\n              id: \"$expectedID\"\n              raw_offset: $expectedRawOffset\n            }\n            EOTXT;\n        $this->assertDumpEquals($expected, $var);\n    }\n\n    public function testCastIntlCalendar()\n    {\n        $var = \\IntlCalendar::createInstance('America/Los_Angeles', 'en');\n\n        $expectedType = $var->getType();\n        $expectedFirstDayOfWeek = $var->getFirstDayOfWeek();\n        $expectedMinimalDaysInFirstWeek = $var->getMinimalDaysInFirstWeek();\n        $expectedRepeatedWallTimeOption = $var->getRepeatedWallTimeOption();\n        $expectedSkippedWallTimeOption = $var->getSkippedWallTimeOption();\n        $expectedTime = $var->getTime().'.0';\n        $expectedInDaylightTime = $var->inDaylightTime() ? 'true' : 'false';\n        $expectedIsLenient = $var->isLenient() ? 'true' : 'false';\n\n        $expectedTimeZone = $var->getTimeZone();\n        $expectedTimeZoneDisplayName = $expectedTimeZone->getDisplayName();\n        $expectedTimeZoneID = $expectedTimeZone->getID();\n        $expectedTimeZoneRawOffset = $expectedTimeZone->getRawOffset();\n        $expectedTimeZoneDSTSavings = $expectedTimeZone->getDSTSavings();\n\n        $expected = <<<EOTXT\n            IntlGregorianCalendar {\n              type: \"$expectedType\"\n              first_day_of_week: $expectedFirstDayOfWeek\n              minimal_days_in_first_week: $expectedMinimalDaysInFirstWeek\n              repeated_wall_time_option: $expectedRepeatedWallTimeOption\n              skipped_wall_time_option: $expectedSkippedWallTimeOption\n              time: $expectedTime\n              in_daylight_time: $expectedInDaylightTime\n              is_lenient: $expectedIsLenient\n              time_zone: IntlTimeZone {\n                display_name: \"$expectedTimeZoneDisplayName\"\n                id: \"$expectedTimeZoneID\"\n                raw_offset: $expectedTimeZoneRawOffset\n                dst_savings: $expectedTimeZoneDSTSavings\n              }\n            }\n            EOTXT;\n        $this->assertDumpEquals($expected, $var);\n    }\n\n    public function testCastDateFormatter()\n    {\n        $var = new \\IntlDateFormatter('en', \\IntlDateFormatter::TRADITIONAL, \\IntlDateFormatter::TRADITIONAL);\n\n        $expectedLocale = $var->getLocale();\n        $expectedPattern = $this->normalizeNarrowNoBreakSpaceCharacter($var->getPattern());\n        $expectedCalendar = $var->getCalendar();\n        $expectedTimeZoneId = $var->getTimeZoneId();\n        $expectedTimeType = $var->getTimeType();\n        $expectedDateType = $var->getDateType();\n\n        $expectedTimeZone = $var->getTimeZone();\n        $expectedTimeZoneDisplayName = $expectedTimeZone->getDisplayName();\n        $expectedTimeZoneID = $expectedTimeZone->getID();\n        $expectedTimeZoneRawOffset = $expectedTimeZone->getRawOffset();\n        $expectedTimeZoneDSTSavings = $expectedTimeZone->useDaylightTime() ? \"\\n    dst_savings: \".$expectedTimeZone->getDSTSavings() : '';\n\n        $expectedCalendarObject = $var->getCalendarObject();\n        $expectedCalendarObjectType = $expectedCalendarObject->getType();\n        $expectedCalendarObjectFirstDayOfWeek = $expectedCalendarObject->getFirstDayOfWeek();\n        $expectedCalendarObjectMinimalDaysInFirstWeek = $expectedCalendarObject->getMinimalDaysInFirstWeek();\n        $expectedCalendarObjectRepeatedWallTimeOption = $expectedCalendarObject->getRepeatedWallTimeOption();\n        $expectedCalendarObjectSkippedWallTimeOption = $expectedCalendarObject->getSkippedWallTimeOption();\n        $expectedCalendarObjectTime = $expectedCalendarObject->getTime().'.0';\n        $expectedCalendarObjectInDaylightTime = $expectedCalendarObject->inDaylightTime() ? 'true' : 'false';\n        $expectedCalendarObjectIsLenient = $expectedCalendarObject->isLenient() ? 'true' : 'false';\n\n        $expectedCalendarObjectTimeZone = $expectedCalendarObject->getTimeZone();\n        $expectedCalendarObjectTimeZoneDisplayName = $expectedCalendarObjectTimeZone->getDisplayName();\n        $expectedCalendarObjectTimeZoneID = $expectedCalendarObjectTimeZone->getID();\n        $expectedCalendarObjectTimeZoneRawOffset = $expectedCalendarObjectTimeZone->getRawOffset();\n        $expectedCalendarObjectTimeZoneDSTSavings = $expectedTimeZone->useDaylightTime() ? \"\\n      dst_savings: \".$expectedCalendarObjectTimeZone->getDSTSavings() : '';\n\n        $expected = <<<EOTXT\n            IntlDateFormatter {\n              locale: \"$expectedLocale\"\n              pattern: \"$expectedPattern\"\n              calendar: $expectedCalendar\n              time_zone_id: \"$expectedTimeZoneId\"\n              time_type: $expectedTimeType\n              date_type: $expectedDateType\n              calendar_object: IntlGregorianCalendar {\n                type: \"$expectedCalendarObjectType\"\n                first_day_of_week: $expectedCalendarObjectFirstDayOfWeek\n                minimal_days_in_first_week: $expectedCalendarObjectMinimalDaysInFirstWeek\n                repeated_wall_time_option: $expectedCalendarObjectRepeatedWallTimeOption\n                skipped_wall_time_option: $expectedCalendarObjectSkippedWallTimeOption\n                time: $expectedCalendarObjectTime\n                in_daylight_time: $expectedCalendarObjectInDaylightTime\n                is_lenient: $expectedCalendarObjectIsLenient\n                time_zone: IntlTimeZone {\n                  display_name: \"$expectedCalendarObjectTimeZoneDisplayName\"\n                  id: \"$expectedCalendarObjectTimeZoneID\"\n                  raw_offset: $expectedCalendarObjectTimeZoneRawOffset$expectedCalendarObjectTimeZoneDSTSavings\n                }\n              }\n              time_zone: IntlTimeZone {\n                display_name: \"$expectedTimeZoneDisplayName\"\n                id: \"$expectedTimeZoneID\"\n                raw_offset: $expectedTimeZoneRawOffset$expectedTimeZoneDSTSavings\n              }\n            }\n            EOTXT;\n        $this->assertDumpEquals($expected, $var);\n    }\n\n    private function normalizeNarrowNoBreakSpaceCharacter(string $input): string\n    {\n        return str_replace(\"\\u{202F}\", '\\\\u{202F}', $input);\n    }\n}\n"
  },
  {
    "path": "Tests/Caster/MemcachedCasterTest.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Tests\\Caster;\n\nuse PHPUnit\\Framework\\TestCase;\nuse Symfony\\Component\\VarDumper\\Test\\VarDumperTestTrait;\n\n/**\n * @author Jan Schädlich <jan.schaedlich@sensiolabs.de>\n */\nclass MemcachedCasterTest extends TestCase\n{\n    use VarDumperTestTrait;\n\n    public function testCastMemcachedWithDefaultOptions()\n    {\n        if (!class_exists(\\Memcached::class)) {\n            $this->markTestSkipped('Memcached not available');\n        }\n\n        $var = new \\Memcached();\n        $var->addServer('127.0.0.1', 11211);\n        $var->addServer('127.0.0.2', 11212);\n\n        $expected = <<<EOTXT\n            Memcached {\n              servers: array:2 [\n                0 => array:3 [\n                  \"host\" => \"127.0.0.1\"\n                  \"port\" => 11211\n                  \"type\" => \"TCP\"\n                ]\n                1 => array:3 [\n                  \"host\" => \"127.0.0.2\"\n                  \"port\" => 11212\n                  \"type\" => \"TCP\"\n                ]\n              ]\n              options: {}\n            }\n            EOTXT;\n        $this->assertDumpEquals($expected, $var);\n    }\n\n    public function testCastMemcachedWithCustomOptions()\n    {\n        if (!class_exists(\\Memcached::class)) {\n            $this->markTestSkipped('Memcached not available');\n        }\n\n        $var = new \\Memcached();\n        $var->addServer('127.0.0.1', 11211);\n        $var->addServer('127.0.0.2', 11212);\n\n        // set a subset of non default options to test boolean, string and integer output\n        $var->setOption(\\Memcached::OPT_COMPRESSION, false);\n        $var->setOption(\\Memcached::OPT_PREFIX_KEY, 'pre');\n        $var->setOption(\\Memcached::OPT_DISTRIBUTION, \\Memcached::DISTRIBUTION_CONSISTENT);\n\n        $expected = <<<'EOTXT'\n            Memcached {\n              servers: array:2 [\n                0 => array:3 [\n                  \"host\" => \"127.0.0.1\"\n                  \"port\" => 11211\n                  \"type\" => \"TCP\"\n                ]\n                1 => array:3 [\n                  \"host\" => \"127.0.0.2\"\n                  \"port\" => 11212\n                  \"type\" => \"TCP\"\n                ]\n              ]\n              options: {\n                OPT_COMPRESSION: false\n                OPT_PREFIX_KEY: \"pre\"\n                OPT_DISTRIBUTION: 1\n              }\n            }\n            EOTXT;\n\n        $this->assertDumpEquals($expected, $var);\n    }\n}\n"
  },
  {
    "path": "Tests/Caster/MysqliCasterTest.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Tests\\Caster;\n\nuse PHPUnit\\Framework\\Attributes\\Group;\nuse PHPUnit\\Framework\\Attributes\\RequiresPhpExtension;\nuse PHPUnit\\Framework\\TestCase;\nuse Symfony\\Component\\VarDumper\\Test\\VarDumperTestTrait;\n\n#[RequiresPhpExtension('mysqli')]\n#[Group('integration')]\nclass MysqliCasterTest extends TestCase\n{\n    use VarDumperTestTrait;\n\n    public function testNotConnected()\n    {\n        $driver = new \\mysqli_driver();\n        $driver->report_mode = 3;\n\n        $xCast = <<<EODUMP\n            mysqli_driver {%A\n              +report_mode: 3\n            }\n            EODUMP;\n\n        $this->assertDumpMatchesFormat($xCast, $driver);\n    }\n}\n"
  },
  {
    "path": "Tests/Caster/OpenSSLCasterTest.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Tests\\Caster;\n\nuse PHPUnit\\Framework\\Attributes\\RequiresPhpExtension;\nuse PHPUnit\\Framework\\TestCase;\nuse Symfony\\Component\\VarDumper\\Test\\VarDumperTestTrait;\n\n#[RequiresPhpExtension('openssl')]\nclass OpenSSLCasterTest extends TestCase\n{\n    use VarDumperTestTrait;\n\n    public function testAsymmetricKey()\n    {\n        $key = openssl_pkey_new([\n            'private_key_bits' => 1024,\n            'private_key_type' => \\OPENSSL_KEYTYPE_RSA,\n        ]);\n\n        if (false === $key) {\n            $this->markTestSkipped('Unable to generate a key pair');\n        }\n\n        $this->assertDumpMatchesFormat(\n            <<<'EODUMP'\n                OpenSSLAsymmetricKey {\n                  bits: 1024\n                  key: \"\"\"\n                    -----BEGIN PUBLIC KEY-----\\n\n                    %A\n                    %A\n                    %A\n                    %A\n                    -----END PUBLIC KEY-----\\n\n                    \"\"\"\n                  type: 0\n                }\n                EODUMP,\n            $key\n        );\n    }\n\n    public function testOpensslCsr()\n    {\n        $dn = [\n            'countryName' => 'FR',\n            'stateOrProvinceName' => 'Ile-de-France',\n            'localityName' => 'Paris',\n            'organizationName' => 'Symfony',\n            'organizationalUnitName' => 'Security',\n            'commonName' => 'symfony.com',\n            'emailAddress' => 'test@symfony.com',\n        ];\n        $privkey = openssl_pkey_new();\n        $csr = openssl_csr_new($dn, $privkey);\n\n        if (false === $csr) {\n            $this->markTestSkipped('Unable to generate a CSR');\n        }\n\n        $this->assertDumpMatchesFormat(\n            <<<'EODUMP'\n                OpenSSLCertificateSigningRequest {\n                  countryName: \"FR\"\n                  stateOrProvinceName: \"Ile-de-France\"\n                  localityName: \"Paris\"\n                  organizationName: \"Symfony\"\n                  organizationalUnitName: \"Security\"\n                  commonName: \"symfony.com\"\n                  emailAddress: \"test@symfony.com\"\n                }\n                EODUMP,\n            $csr\n        );\n    }\n}\n"
  },
  {
    "path": "Tests/Caster/PdoCasterTest.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Tests\\Caster;\n\nuse PHPUnit\\Framework\\Attributes\\RequiresPhpExtension;\nuse PHPUnit\\Framework\\TestCase;\nuse Symfony\\Component\\VarDumper\\Caster\\ConstStub;\nuse Symfony\\Component\\VarDumper\\Caster\\EnumStub;\nuse Symfony\\Component\\VarDumper\\Caster\\PdoCaster;\nuse Symfony\\Component\\VarDumper\\Cloner\\Stub;\nuse Symfony\\Component\\VarDumper\\Test\\VarDumperTestTrait;\n\n/**\n * @author Nicolas Grekas <p@tchwork.com>\n */\nclass PdoCasterTest extends TestCase\n{\n    use VarDumperTestTrait;\n\n    #[RequiresPhpExtension('pdo_sqlite')]\n    public function testCastPdo()\n    {\n        $pdo = new \\PDO('sqlite::memory:');\n        $pdo->setAttribute(\\PDO::ATTR_STATEMENT_CLASS, ['PDOStatement', [$pdo]]);\n        $pdo->setAttribute(\\PDO::ATTR_ERRMODE, \\PDO::ERRMODE_EXCEPTION);\n\n        $cast = PdoCaster::castPdo($pdo, [], new Stub(), false);\n\n        $this->assertInstanceOf(EnumStub::class, $cast[\"\\0~\\0attributes\"]);\n\n        $attr = $cast[\"\\0~\\0attributes\"] = $cast[\"\\0~\\0attributes\"]->value;\n        $this->assertInstanceOf(ConstStub::class, $attr['CASE']);\n        $this->assertSame('NATURAL', $attr['CASE']->class);\n        $this->assertSame('BOTH', $attr['DEFAULT_FETCH_MODE']->class);\n\n        $xDump = <<<'EODUMP'\n            array:2 [\n              \"\\x00~\\x00inTransaction\" => false\n              \"\\x00~\\x00attributes\" => array:10 [\n                \"CASE\" => NATURAL\n                \"ERRMODE\" => EXCEPTION\n                \"PERSISTENT\" => false\n                \"DRIVER_NAME\" => \"sqlite\"\n                \"ORACLE_NULLS\" => NATURAL\n                \"CLIENT_VERSION\" => \"%s\"\n                \"SERVER_VERSION\" => \"%s\"\n                \"STATEMENT_CLASS\" => array:%d [\n                  0 => \"PDOStatement\"%A\n                ]\n                \"STRINGIFY_FETCHES\" => false\n                \"DEFAULT_FETCH_MODE\" => BOTH\n              ]\n            ]\n            EODUMP;\n\n        $this->assertDumpMatchesFormat($xDump, $cast);\n    }\n}\n"
  },
  {
    "path": "Tests/Caster/RdKafkaCasterTest.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Tests\\Caster;\n\nuse PHPUnit\\Framework\\Attributes\\Group;\nuse PHPUnit\\Framework\\Attributes\\RequiresPhpExtension;\nuse PHPUnit\\Framework\\TestCase;\nuse RdKafka\\Conf;\nuse RdKafka\\KafkaConsumer;\nuse RdKafka\\Producer;\nuse RdKafka\\TopicConf;\nuse Symfony\\Component\\VarDumper\\Test\\VarDumperTestTrait;\n\n#[RequiresPhpExtension('rdkafka')]\n#[Group('integration')]\nclass RdKafkaCasterTest extends TestCase\n{\n    use VarDumperTestTrait;\n\n    private const TOPIC = 'test-topic';\n    private const GROUP_ID = 'test-group-id';\n\n    private bool $hasBroker = false;\n    private string $broker;\n\n    protected function setUp(): void\n    {\n        if (!$this->hasBroker && getenv('KAFKA_BROKER')) {\n            $this->broker = getenv('KAFKA_BROKER');\n            $this->hasBroker = true;\n        }\n    }\n\n    public function testDumpConf()\n    {\n        $conf = new Conf();\n        $conf->setErrorCb(static function ($kafka, $err, $reason) {});\n        $conf->setDrMsgCb(static function () {});\n        $conf->setRebalanceCb(static function () {});\n\n        // BC with earlier version of extension rdkafka\n        foreach (['setLogCb', 'setOffsetCommitCb', 'setStatsCb', 'setConsumeCb'] as $method) {\n            if (method_exists($conf, $method)) {\n                $conf->{$method}(static function () {});\n            }\n        }\n\n        $expectedDump = <<<EODUMP\n            RdKafka\\Conf {\n              builtin.features: \"gzip,snappy,ssl,sasl,regex,lz4,sasl_gssapi,sasl_plain,sasl_scram,plugins%S\"\n              client.id: \"rdkafka\"\n            %A\n              dr_msg_cb: \"0x%x\"\n            %A\n            }\n            EODUMP;\n\n        $this->assertDumpMatchesFormat($expectedDump, $conf);\n    }\n\n    public function testDumpProducer()\n    {\n        if (!$this->hasBroker) {\n            $this->markTestSkipped('Test requires an active broker');\n        }\n\n        $producer = new Producer(new Conf());\n        $producer->addBrokers($this->broker);\n\n        $expectedDump = <<<EODUMP\n            RdKafka\\Producer {\n            %Aout_q_len: %d\n              orig_broker_id: 1001\n              orig_broker_name: \"$this->broker/1001\"\n              brokers: RdKafka\\Metadata\\Collection {\n                +0: RdKafka\\Metadata\\Broker {\n                  id: 1001\n                  host: \"%s\"\n                  port: %d\n                }\n              }\n              topics: RdKafka\\Metadata\\Collection {\n                +0: RdKafka\\Metadata\\Topic {\n                  name: \"%s\"\n                  partitions: RdKafka\\Metadata\\Collection {\n                    +0: RdKafka\\Metadata\\Partition {\n                      id: 0\n                      err: 0\n                      leader: 1001\n                    }%A\n                  }\n                }%A\n              }\n            }\n            EODUMP;\n\n        $this->assertDumpMatchesFormat($expectedDump, $producer);\n    }\n\n    public function testDumpTopicConf()\n    {\n        $topicConf = new TopicConf();\n        $topicConf->set('auto.offset.reset', 'smallest');\n\n        $expectedDump = <<<EODUMP\n            RdKafka\\TopicConf {\n              request.required.acks: \"%i\"\n              request.timeout.ms: \"%d\"\n              message.timeout.ms: \"300000\"\n            %A\n              auto.commit.enable: \"true\"\n              auto.commit.interval.ms: \"60000\"\n              auto.offset.reset: \"smallest\"\n              offset.store.path: \".\"\n              offset.store.sync.interval.ms: \"-1\"\n              offset.store.method: \"broker\"\n              consume.callback.max.messages: \"0\"\n            }\n            EODUMP;\n\n        $this->assertDumpMatchesFormat($expectedDump, $topicConf);\n    }\n\n    public function testDumpKafkaConsumer()\n    {\n        if (!$this->hasBroker) {\n            $this->markTestSkipped('Test requires an active broker');\n        }\n\n        $conf = new Conf();\n        $conf->set('metadata.broker.list', $this->broker);\n        $conf->set('group.id', self::GROUP_ID);\n\n        $consumer = new KafkaConsumer($conf);\n        $consumer->subscribe([self::TOPIC]);\n\n        $expectedDump = <<<EODUMP\n            RdKafka\\KafkaConsumer {\n            %Asubscription: array:1 [\n                0 => \"test-topic\"\n              ]\n              assignment: []\n              orig_broker_id: %i\n              orig_broker_name: \"$this->broker/%s\"\n              brokers: RdKafka\\Metadata\\Collection {\n                +0: RdKafka\\Metadata\\Broker {\n                  id: 1001\n                  host: \"%s\"\n                  port: %d\n                }\n              }\n              topics: RdKafka\\Metadata\\Collection {\n                +0: RdKafka\\Metadata\\Topic {\n                  name: \"%s\"\n                  partitions: RdKafka\\Metadata\\Collection {\n                    +0: RdKafka\\Metadata\\Partition {\n                      id: 0\n                      err: 0\n                      leader: 1001\n                    }%A\n                  }\n                }%A\n              }\n            }\n            EODUMP;\n\n        $this->assertDumpMatchesFormat($expectedDump, $consumer);\n    }\n\n    public function testDumpProducerTopic()\n    {\n        $producer = new Producer(new Conf());\n        $producer->addBrokers($this->broker);\n\n        $topic = $producer->newTopic('test');\n        $topic->produce(\\RD_KAFKA_PARTITION_UA, 0, '{}');\n\n        $expectedDump = <<<EODUMP\n            RdKafka\\ProducerTopic {\n              name: \"test\"\n            }\n            EODUMP;\n\n        $this->assertDumpMatchesFormat($expectedDump, $topic);\n    }\n\n    public function testDumpMessage()\n    {\n        $conf = new Conf();\n        $conf->set('metadata.broker.list', $this->broker);\n        $conf->set('group.id', self::GROUP_ID);\n\n        $consumer = new KafkaConsumer($conf);\n        $consumer->subscribe([self::TOPIC]);\n\n        // Force timeout\n        $message = $consumer->consume(0);\n\n        $expectedDump = <<<EODUMP\n            RdKafka\\Message {\n              +err: -185\n              +topic_name: null\n              +timestamp: null\n              +partition: 0\n              +payload: null\n              +len: null\n              +key: null\n              +offset: 0%A\n              errstr: \"Local: Timed out\"\n            }\n            EODUMP;\n\n        $this->assertDumpMatchesFormat($expectedDump, $message);\n    }\n}\n"
  },
  {
    "path": "Tests/Caster/RedisCasterTest.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Tests\\Caster;\n\nuse PHPUnit\\Framework\\Attributes\\Group;\nuse PHPUnit\\Framework\\Attributes\\RequiresPhpExtension;\nuse PHPUnit\\Framework\\Attributes\\TestWith;\nuse PHPUnit\\Framework\\TestCase;\nuse Relay\\Relay;\nuse Symfony\\Component\\VarDumper\\Test\\VarDumperTestTrait;\n\n/**\n * @author Nicolas Grekas <p@tchwork.com>\n */\n#[Group('integration')]\nclass RedisCasterTest extends TestCase\n{\n    use VarDumperTestTrait;\n\n    #[RequiresPhpExtension('redis')]\n    public function testNotConnected()\n    {\n        $redis = new \\Redis();\n\n        $xCast = <<<'EODUMP'\n            Redis {\n              isConnected: false\n            }\n            EODUMP;\n\n        $this->assertDumpMatchesFormat($xCast, $redis);\n    }\n\n    #[TestWith([\\Redis::class])]\n    #[TestWith([Relay::class])]\n    public function testConnected(string $class)\n    {\n        if (!class_exists($class)) {\n            self::markTestSkipped(\\sprintf('\"%s\" class required', $class));\n        }\n\n        $redisHost = explode(':', getenv('REDIS_HOST')) + [1 => 6379];\n        $redis = new $class();\n        try {\n            $redis->connect(...$redisHost);\n        } catch (\\Exception $e) {\n            self::markTestSkipped($e->getMessage());\n        }\n\n        $xCast = <<<EODUMP\n            %a {%A\n              isConnected: true\n              host: \"{$redisHost[0]}\"\n              port: {$redisHost[1]}\n              auth: null\n              mode: ATOMIC\n              dbNum: 0\n              timeout: 0.0\n              lastError: null\n              persistentId: %a\n              options: {\n                TCP_KEEPALIVE: %a\n                READ_TIMEOUT: 0.0\n                COMPRESSION: NONE\n                SERIALIZER: NONE\n                PREFIX: null\n                SCAN: NORETRY\n              }\n            }\n            EODUMP;\n\n        $this->assertDumpMatchesFormat($xCast, $redis);\n    }\n}\n"
  },
  {
    "path": "Tests/Caster/ReflectionCasterTest.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Tests\\Caster;\n\nuse PHPUnit\\Framework\\TestCase;\nuse Symfony\\Component\\VarDumper\\Caster\\Caster;\nuse Symfony\\Component\\VarDumper\\Test\\VarDumperTestTrait;\nuse Symfony\\Component\\VarDumper\\Tests\\Fixtures\\ExtendsReflectionTypeFixture;\nuse Symfony\\Component\\VarDumper\\Tests\\Fixtures\\GeneratorDemo;\nuse Symfony\\Component\\VarDumper\\Tests\\Fixtures\\LotsOfAttributes;\nuse Symfony\\Component\\VarDumper\\Tests\\Fixtures\\NotLoadableClass;\nuse Symfony\\Component\\VarDumper\\Tests\\Fixtures\\Php82NullStandaloneReturnType;\nuse Symfony\\Component\\VarDumper\\Tests\\Fixtures\\ReflectionIntersectionTypeFixture;\nuse Symfony\\Component\\VarDumper\\Tests\\Fixtures\\ReflectionNamedTypeFixture;\nuse Symfony\\Component\\VarDumper\\Tests\\Fixtures\\ReflectionUnionTypeFixture;\nuse Symfony\\Component\\VarDumper\\Tests\\Fixtures\\ReflectionUnionTypeWithIntersectionFixture;\n\n/**\n * @author Nicolas Grekas <p@tchwork.com>\n */\nclass ReflectionCasterTest extends TestCase\n{\n    use VarDumperTestTrait;\n\n    public function testReflectionCaster()\n    {\n        $var = new \\ReflectionClass(\\ReflectionClass::class);\n\n        $this->assertDumpMatchesFormat(\n            <<<'EOTXT'\n                ReflectionClass {\n                  +name: \"ReflectionClass\"\n                %Aimplements: array:%d [\n                %A]\n                  constants: array:%d [\n                    0 => ReflectionClassConstant {\n                      +name: \"IS_IMPLICIT_ABSTRACT\"\n                      +class: \"ReflectionClass\"\n                      modifiers: \"public\"\n                      value: 16\n                    }\n                    1 => ReflectionClassConstant {\n                      +name: \"IS_EXPLICIT_ABSTRACT\"\n                      +class: \"ReflectionClass\"\n                      modifiers: \"public\"\n                      value: %d\n                    }\n                    2 => ReflectionClassConstant {\n                      +name: \"IS_FINAL\"\n                      +class: \"ReflectionClass\"\n                      modifiers: \"public\"\n                      value: %d\n                    }\n                %A]\n                  properties: array:%d [\n                    \"name\" => ReflectionProperty {\n                %A    +name: \"name\"\n                      +class: \"ReflectionClass\"\n                %A    modifiers: \"public\"\n                    }\n                %A]\n                  methods: array:%d [\n                %A\n                    \"__construct\" => ReflectionMethod {\n                      +name: \"__construct\"\n                      +class: \"ReflectionClass\"\n                %A    parameters: {\n                        $%s: ReflectionParameter {\n                %A         position: 0\n                %A\n                }\n                EOTXT,\n            $var\n        );\n    }\n\n    public function testClosureCaster()\n    {\n        $a = $b = 123;\n        $var = static function ($x) use ($a, &$b) { var_dump($a, $b); };\n\n        $this->assertDumpMatchesFormat(\n            <<<'EOTXT'\n                Closure($x) {\n                %Ause: {\n                    $a: 123\n                    $b: & 123\n                  }\n                  file: \"%sReflectionCasterTest.php\"\n                  line: \"%s\"\n                }\n                EOTXT,\n            $var\n        );\n    }\n\n    public function testFromCallableClosureCaster()\n    {\n        $var = [\n            (new \\ReflectionMethod($this, __FUNCTION__))->getClosure($this),\n            (new \\ReflectionMethod(__CLASS__, 'stub'))->getClosure(),\n        ];\n\n        $this->assertDumpMatchesFormat(\n            <<<EOTXT\n                array:2 [\n                  0 => Symfony\\Component\\VarDumper\\Tests\\Caster\\ReflectionCasterTest::testFromCallableClosureCaster() {\n                    this: Symfony\\Component\\VarDumper\\Tests\\Caster\\ReflectionCasterTest { …}\n                    file: \"%sReflectionCasterTest.php\"\n                    line: \"%d to %d\"\n                  }\n                  1 => Symfony\\Component\\VarDumper\\Tests\\Caster\\ReflectionCasterTest::stub(): void {\n                    returnType: \"void\"\n                    file: \"%sReflectionCasterTest.php\"\n                    line: \"%d to %d\"\n                  }\n                ]\n                EOTXT,\n            $var\n        );\n    }\n\n    public function testClosureCasterExcludingVerbosity()\n    {\n        $var = function &($a = 123) {\n            \\assert(null !== $this);\n        };\n\n        $this->assertDumpEquals('Closure&($a = 123) { …5}', $var, Caster::EXCLUDE_VERBOSE);\n    }\n\n    public function testReflectionParameter()\n    {\n        $var = new \\ReflectionParameter(reflectionParameterFixture::class, 0);\n\n        $this->assertDumpMatchesFormat(\n            <<<'EOTXT'\n                ReflectionParameter {\n                  +name: \"arg1\"\n                  position: 0\n                  allowsNull: true\n                  typeHint: \"Symfony\\Component\\VarDumper\\Tests\\Fixtures\\NotLoadableClass\"\n                }\n                EOTXT,\n            $var\n        );\n    }\n\n    public function testReflectionParameterScalar()\n    {\n        $f = static function (int $a) {};\n        $var = new \\ReflectionParameter($f, 0);\n\n        $this->assertDumpMatchesFormat(\n            <<<'EOTXT'\n                ReflectionParameter {\n                  +name: \"a\"\n                  position: 0\n                  typeHint: \"int\"\n                }\n                EOTXT,\n            $var\n        );\n    }\n\n    public function testReflectionParameterMixed()\n    {\n        $f = static function (mixed $a) {};\n        $var = new \\ReflectionParameter($f, 0);\n\n        $this->assertDumpMatchesFormat(\n            <<<'EOTXT'\n                ReflectionParameter {\n                  +name: \"a\"\n                  position: 0\n                  allowsNull: true\n                  typeHint: \"mixed\"\n                }\n                EOTXT,\n            $var\n        );\n    }\n\n    public function testReflectionParameterUnion()\n    {\n        $f = static function (int|float $a) {};\n        $var = new \\ReflectionParameter($f, 0);\n\n        $this->assertDumpMatchesFormat(\n            <<<'EOTXT'\n                ReflectionParameter {\n                  +name: \"a\"\n                  position: 0\n                  typeHint: \"int|float\"\n                }\n                EOTXT,\n            $var\n        );\n    }\n\n    public function testReflectionParameterNullableUnion()\n    {\n        $f = static function (int|float|null $a) {};\n        $var = new \\ReflectionParameter($f, 0);\n\n        $this->assertDumpMatchesFormat(\n            <<<'EOTXT'\n                ReflectionParameter {\n                  +name: \"a\"\n                  position: 0\n                  allowsNull: true\n                  typeHint: \"int|float|null\"\n                }\n                EOTXT,\n            $var\n        );\n    }\n\n    public function testReflectionParameterIntersection()\n    {\n        $f = static function (\\Traversable&\\Countable $a) {};\n        $var = new \\ReflectionParameter($f, 0);\n\n        $this->assertDumpMatchesFormat(\n            <<<'EOTXT'\n                ReflectionParameter {\n                  +name: \"a\"\n                  position: 0\n                  typeHint: \"Traversable&Countable\"\n                }\n                EOTXT,\n            $var\n        );\n    }\n\n    public function testReflectionPropertyScalar()\n    {\n        $var = new \\ReflectionProperty(ReflectionNamedTypeFixture::class, 'a');\n        $this->assertDumpMatchesFormat(\n            <<<'EOTXT'\n                ReflectionProperty {\n                  +name: \"a\"\n                  +class: \"Symfony\\Component\\VarDumper\\Tests\\Fixtures\\ReflectionNamedTypeFixture\"\n                  modifiers: \"public\"\n                }\n                EOTXT,\n            $var\n        );\n    }\n\n    public function testReflectionNamedType()\n    {\n        $var = (new \\ReflectionProperty(ReflectionNamedTypeFixture::class, 'a'))->getType();\n        $this->assertDumpMatchesFormat(\n            <<<'EOTXT'\n                ReflectionNamedType {\n                  name: \"int\"\n                  allowsNull: false\n                  isBuiltin: true\n                }\n                EOTXT,\n            $var\n        );\n    }\n\n    public function testReflectionUnionType()\n    {\n        $var = (new \\ReflectionProperty(ReflectionUnionTypeFixture::class, 'a'))->getType();\n        $this->assertDumpMatchesFormat(\n            <<<'EOTXT'\n                ReflectionUnionType {\n                  allowsNull: false\n                  types: array:2 [\n                    0 => ReflectionNamedType {\n                      name: \"string\"\n                      allowsNull: false\n                      isBuiltin: true\n                    }\n                    1 => ReflectionNamedType {\n                      name: \"int\"\n                      allowsNull: false\n                      isBuiltin: true\n                    }\n                  ]\n                }\n                EOTXT,\n            $var\n        );\n    }\n\n    public function testReflectionIntersectionType()\n    {\n        $var = (new \\ReflectionProperty(ReflectionIntersectionTypeFixture::class, 'a'))->getType();\n        $this->assertDumpMatchesFormat(\n            <<<'EOTXT'\n                ReflectionIntersectionType {\n                  allowsNull: false\n                  types: array:2 [\n                    0 => ReflectionNamedType {\n                      name: \"Traversable\"\n                      allowsNull: false\n                      isBuiltin: false\n                    }\n                    1 => ReflectionNamedType {\n                      name: \"Countable\"\n                      allowsNull: false\n                      isBuiltin: false\n                    }\n                  ]\n                }\n                EOTXT,\n            $var\n        );\n    }\n\n    public function testReflectionUnionTypeWithIntersection()\n    {\n        $var = (new \\ReflectionProperty(ReflectionUnionTypeWithIntersectionFixture::class, 'a'))->getType();\n        $this->assertDumpMatchesFormat(\n            <<<'EOTXT'\n                ReflectionUnionType {\n                  allowsNull: true\n                  types: array:2 [\n                    0 => ReflectionIntersectionType {\n                      allowsNull: false\n                      types: array:2 [\n                        0 => ReflectionNamedType {\n                          name: \"Traversable\"\n                          allowsNull: false\n                          isBuiltin: false\n                        }\n                        1 => ReflectionNamedType {\n                          name: \"Countable\"\n                          allowsNull: false\n                          isBuiltin: false\n                        }\n                      ]\n                    }\n                    1 => ReflectionNamedType {\n                      name: \"null\"\n                      allowsNull: true\n                      isBuiltin: true\n                    }\n                  ]\n                }\n                EOTXT,\n            $var\n        );\n    }\n\n    public function testExtendsReflectionType()\n    {\n        $var = new ExtendsReflectionTypeFixture();\n        $this->assertDumpMatchesFormat(\n            <<<'EOTXT'\n                Symfony\\Component\\VarDumper\\Tests\\Fixtures\\ExtendsReflectionTypeFixture {\n                  allowsNull: false\n                }\n                EOTXT,\n            $var\n        );\n    }\n\n    public function testReturnType()\n    {\n        $f = function (): int {\n            \\assert(null !== $this);\n        };\n\n        $this->assertDumpMatchesFormat(\n            <<<EOTXT\n                Closure(): int {\n                  returnType: \"int\"\n                  class: \"Symfony\\Component\\VarDumper\\Tests\\Caster\\ReflectionCasterTest\"\n                  this: Symfony\\Component\\VarDumper\\Tests\\Caster\\ReflectionCasterTest { …}\n                  file: \"%s\"\n                  line: \"%s\"\n                }\n                EOTXT,\n            $f\n        );\n    }\n\n    public function testMixedReturnType()\n    {\n        $f = function (): mixed {\n            \\assert(null !== $this);\n        };\n\n        $this->assertDumpMatchesFormat(\n            <<<EOTXT\n                Closure(): mixed {\n                  returnType: \"mixed\"\n                  class: \"Symfony\\Component\\VarDumper\\Tests\\Caster\\ReflectionCasterTest\"\n                  this: Symfony\\Component\\VarDumper\\Tests\\Caster\\ReflectionCasterTest { …}\n                  file: \"%s\"\n                  line: \"%s\"\n                }\n                EOTXT,\n            $f\n        );\n    }\n\n    public function testNullReturnType()\n    {\n        $className = Php82NullStandaloneReturnType::class;\n\n        $this->assertDumpMatchesFormat(\n            <<<EOTXT\n                {$className}::foo(null \\$bar): null {\n                  returnType: \"null\"\n                  this: {$className} { …}\n                  file: \"%s\"\n                  line: \"%s\"\n                }\n                EOTXT,\n            (new Php82NullStandaloneReturnType())->foo(...)\n        );\n    }\n\n    public function testUnionReturnType()\n    {\n        $f = function (): int|float {\n            \\assert(null !== $this);\n        };\n\n        $this->assertDumpMatchesFormat(\n            <<<EOTXT\n                Closure(): int|float {\n                  returnType: \"int|float\"\n                  class: \"Symfony\\Component\\VarDumper\\Tests\\Caster\\ReflectionCasterTest\"\n                  this: Symfony\\Component\\VarDumper\\Tests\\Caster\\ReflectionCasterTest { …}\n                  file: \"%s\"\n                  line: \"%s\"\n                }\n                EOTXT,\n            $f\n        );\n    }\n\n    public function testNullableUnionReturnType()\n    {\n        $f = function (): int|float|null {\n            \\assert(null !== $this);\n        };\n\n        $this->assertDumpMatchesFormat(\n            <<<EOTXT\n                Closure(): int|float|null {\n                  returnType: \"int|float|null\"\n                  class: \"Symfony\\Component\\VarDumper\\Tests\\Caster\\ReflectionCasterTest\"\n                  this: Symfony\\Component\\VarDumper\\Tests\\Caster\\ReflectionCasterTest { …}\n                  file: \"%s\"\n                  line: \"%s\"\n                }\n                EOTXT,\n            $f\n        );\n    }\n\n    public function testGenerator()\n    {\n        if (\\extension_loaded('xdebug')) {\n            $this->markTestSkipped('xdebug is active');\n        }\n\n        $generator = new GeneratorDemo();\n        $generator = $generator->baz();\n\n        $expectedDump = <<<'EODUMP'\n            Generator {\n              function: \"Symfony\\Component\\VarDumper\\Tests\\Fixtures\\GeneratorDemo::baz\"\n              this: Symfony\\Component\\VarDumper\\Tests\\Fixtures\\GeneratorDemo { …}\n              %s: {\n                %sGeneratorDemo.php:12 {\n                  Symfony\\Component\\VarDumper\\Tests\\Fixtures\\GeneratorDemo->baz()\n                  › \n                  › public function baz()\n                  › {\n                }\n                Symfony\\Component\\VarDumper\\Tests\\Fixtures\\GeneratorDemo->baz() {}\n            %A}\n              closed: false\n            }\n            EODUMP;\n\n        $this->assertDumpMatchesFormat($expectedDump, $generator);\n\n        foreach ($generator as $v) {\n            break;\n        }\n\n        $expectedDump = <<<'EODUMP'\n            array:2 [\n              0 => ReflectionGenerator {\n                this: Symfony\\Component\\VarDumper\\Tests\\Fixtures\\GeneratorDemo { …}\n                %s: {\n                  %s%eTests%eFixtures%eGeneratorDemo.php:%d {\n                    Symfony\\Component\\VarDumper\\Tests\\Fixtures\\GeneratorDemo::foo()\n                    › {\n                    ›     yield 1;\n                    › }\n            %A    }\n                  %s%eTests%eFixtures%eGeneratorDemo.php:20 { …}\n                  %s%eTests%eFixtures%eGeneratorDemo.php:14 { …}\n            %A  }\n                closed: false\n              }\n              1 => Generator {\n                function: \"Symfony\\Component\\VarDumper\\Tests\\Fixtures\\GeneratorDemo::foo\"\n                %s: {\n                  %s%eTests%eFixtures%eGeneratorDemo.php:%d {\n                    Symfony\\Component\\VarDumper\\Tests\\Fixtures\\GeneratorDemo::foo()\n                    › {\n                    ›     yield 1;\n                    › }\n                  }\n            %A  }\n                closed: false\n              }\n            ]\n            EODUMP;\n\n        $r = new \\ReflectionGenerator($generator);\n        $this->assertDumpMatchesFormat($expectedDump, [$r, $r->getExecutingGenerator()]);\n\n        foreach ($generator as $v) {\n        }\n\n        $expectedDump = <<<'EODUMP'\n            Generator {\n              function: \"Symfony\\Component\\VarDumper\\Tests\\Fixtures\\GeneratorDemo::baz\"\n              closed: true\n            }\n            EODUMP;\n        $this->assertDumpMatchesFormat($expectedDump, $generator);\n    }\n\n    public function testNewInInitializer()\n    {\n        $f = function ($a = new \\stdClass()) {\n            \\assert(null !== $this);\n        };\n\n        $this->assertDumpMatchesFormat(\n            <<<EOTXT\n                Closure(\\$a = new stdClass) {\n                  class: \"Symfony\\Component\\VarDumper\\Tests\\Caster\\ReflectionCasterTest\"\n                  this: Symfony\\Component\\VarDumper\\Tests\\Caster\\ReflectionCasterTest { …}\n                  file: \"%s\"\n                  line: \"%s\"\n                }\n                EOTXT,\n            $f\n        );\n    }\n\n    public function testReflectionClassWithAttribute()\n    {\n        $var = new \\ReflectionClass(LotsOfAttributes::class);\n\n        $this->assertDumpMatchesFormat(<<<EOTXT\n            ReflectionClass {\n              +name: \"Symfony\\Component\\VarDumper\\Tests\\Fixtures\\LotsOfAttributes\"\n            %A  attributes: array:1 [\n                0 => ReflectionAttribute {\n                  +name: \"Symfony\\Component\\VarDumper\\Tests\\Fixtures\\MyAttribute\"\n                  arguments: []\n                }\n              ]\n            %A\n            }\n            EOTXT,\n            $var\n        );\n    }\n\n    public function testReflectionMethodWithAttribute()\n    {\n        $var = new \\ReflectionMethod(LotsOfAttributes::class, 'someMethod');\n\n        $this->assertDumpMatchesFormat(<<<EOTXT\n            ReflectionMethod {\n              +name: \"someMethod\"\n              +class: \"Symfony\\Component\\VarDumper\\Tests\\Fixtures\\LotsOfAttributes\"\n            %A  attributes: array:1 [\n                0 => ReflectionAttribute {\n                  +name: \"Symfony\\Component\\VarDumper\\Tests\\Fixtures\\MyAttribute\"\n                  arguments: array:1 [\n                    0 => \"two\"\n                  ]\n                }\n              ]\n            %A\n            }\n            EOTXT,\n            $var\n        );\n    }\n\n    public function testReflectionPropertyWithAttribute()\n    {\n        $var = new \\ReflectionProperty(LotsOfAttributes::class, 'someProperty');\n\n        $this->assertDumpMatchesFormat(<<<EOTXT\n            ReflectionProperty {\n              +name: \"someProperty\"\n              +class: \"Symfony\\Component\\VarDumper\\Tests\\Fixtures\\LotsOfAttributes\"\n            %A  attributes: array:1 [\n                0 => ReflectionAttribute {\n                  +name: \"Symfony\\Component\\VarDumper\\Tests\\Fixtures\\MyAttribute\"\n                  arguments: array:2 [\n                    0 => \"one\"\n                    \"extra\" => \"hello\"\n                  ]\n                }\n              ]\n            }\n            EOTXT,\n            $var\n        );\n    }\n\n    public function testReflectionClassConstantWithAttribute()\n    {\n        $var = new \\ReflectionClassConstant(LotsOfAttributes::class, 'SOME_CONSTANT');\n\n        $this->assertDumpMatchesFormat(<<<EOTXT\n            ReflectionClassConstant {\n              +name: \"SOME_CONSTANT\"\n              +class: \"Symfony\\Component\\VarDumper\\Tests\\Fixtures\\LotsOfAttributes\"\n              modifiers: \"public\"\n              value: \"some value\"\n              attributes: array:2 [\n                0 => ReflectionAttribute {\n                  +name: \"Symfony\\Component\\VarDumper\\Tests\\Fixtures\\RepeatableAttribute\"\n                  arguments: array:1 [\n                    0 => \"one\"\n                  ]\n                }\n                1 => ReflectionAttribute {\n                  +name: \"Symfony\\Component\\VarDumper\\Tests\\Fixtures\\RepeatableAttribute\"\n                  arguments: array:1 [\n                    0 => \"two\"\n                  ]\n                }\n              ]\n            }\n            EOTXT,\n            $var\n        );\n    }\n\n    public function testReflectionParameterWithAttribute()\n    {\n        $var = new \\ReflectionParameter([LotsOfAttributes::class, 'someMethod'], 'someParameter');\n\n        $this->assertDumpMatchesFormat(<<<EOTXT\n            ReflectionParameter {\n              +name: \"someParameter\"\n              position: 0\n              attributes: array:1 [\n                0 => ReflectionAttribute {\n                  +name: \"Symfony\\Component\\VarDumper\\Tests\\Fixtures\\MyAttribute\"\n                  arguments: array:1 [\n                    0 => \"three\"\n                  ]\n                }\n              ]\n            %A\n            }\n            EOTXT,\n            $var\n        );\n    }\n\n    public static function stub(): void\n    {\n    }\n}\n\nfunction reflectionParameterFixture(?NotLoadableClass $arg1, $arg2)\n{\n}\n"
  },
  {
    "path": "Tests/Caster/ResourceCasterTest.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Tests\\Caster;\n\nuse PHPUnit\\Framework\\Attributes\\RequiresPhpExtension;\nuse PHPUnit\\Framework\\TestCase;\nuse Symfony\\Component\\VarDumper\\Test\\VarDumperTestTrait;\n\nclass ResourceCasterTest extends TestCase\n{\n    use VarDumperTestTrait;\n\n    #[RequiresPhpExtension('dba')]\n    public function testCastDba()\n    {\n        $dba = dba_open(sys_get_temp_dir().'/test.db', 'c');\n\n        $this->assertDumpMatchesFormat(\n            <<<'EODUMP'\n                Dba\\Connection {\n                  +file: %s\n                }\n                EODUMP,\n            $dba\n        );\n    }\n\n    #[RequiresPhpExtension('dba')]\n    public function testCastDbaOnBuggyPhp84()\n    {\n        if (\\PHP_VERSION_ID >= 80402) {\n            $this->markTestSkipped('The test can only be run on PHP 8.4.0 and 8.4.1, see https://github.com/php/php-src/issues/16990');\n        }\n\n        $dba = dba_open(sys_get_temp_dir().'/test.db', 'c');\n\n        $this->assertDumpMatchesFormat(\n            <<<'EODUMP'\n                Dba\\Connection {\n                }\n                EODUMP,\n            $dba\n        );\n    }\n}\n"
  },
  {
    "path": "Tests/Caster/SocketCasterTest.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Tests\\Caster;\n\nuse PHPUnit\\Framework\\Attributes\\RequiresPhpExtension;\nuse PHPUnit\\Framework\\TestCase;\nuse Symfony\\Component\\VarDumper\\Test\\VarDumperTestTrait;\n\n#[RequiresPhpExtension('sockets')]\nclass SocketCasterTest extends TestCase\n{\n    use VarDumperTestTrait;\n\n    public function testCastSocket()\n    {\n        $socket = socket_create(\\AF_INET, \\SOCK_DGRAM, \\SOL_UDP);\n        @socket_connect($socket, '127.0.0.1', 80);\n\n        $this->assertDumpMatchesFormat(\n            <<<'EODUMP'\n                Socket {\n                  uri: \"udp://127.0.0.1:%d\"\n                  timed_out: false\n                  blocked: true%A\n                }\n                EODUMP,\n            $socket\n        );\n    }\n\n    public function testCastSocketIpV6()\n    {\n        $socket = socket_create(\\AF_INET6, \\SOCK_STREAM, \\SOL_TCP);\n        @socket_connect($socket, '::1', 80);\n\n        $this->assertDumpMatchesFormat(\n            <<<'EODUMP'\n                Socket {\n                  uri: \"tcp://[%A]:%d\"\n                  timed_out: false\n                  blocked: true\n                  last_error: SOCKET_ECONNREFUSED\n                }\n                EODUMP,\n            $socket\n        );\n    }\n\n    public function testCastUnixSocket()\n    {\n        $socket = socket_create(\\AF_UNIX, \\SOCK_STREAM, 0);\n        @socket_connect($socket, '/tmp/socket.sock');\n\n        $this->assertDumpMatchesFormat(\n            <<<'EODUMP'\n                Socket {\n                  uri: \"unix://\"\n                  timed_out: false\n                  blocked: true\n                  last_error: SOCKET_ENOENT\n                }\n                EODUMP,\n            $socket\n        );\n    }\n}\n"
  },
  {
    "path": "Tests/Caster/SplCasterTest.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Tests\\Caster;\n\nuse PHPUnit\\Framework\\Attributes\\DataProvider;\nuse PHPUnit\\Framework\\TestCase;\nuse Symfony\\Component\\VarDumper\\Test\\VarDumperTestTrait;\n\n/**\n * @author Grégoire Pineau <lyrixx@lyrixx.info>\n */\nclass SplCasterTest extends TestCase\n{\n    use VarDumperTestTrait;\n\n    public static function getCastFileInfoTests()\n    {\n        return [\n            [__FILE__, <<<'EOTXT'\n                SplFileInfo {\n                %Apath: \"%sCaster\"\n                  filename: \"SplCasterTest.php\"\n                  basename: \"SplCasterTest.php\"\n                  pathname: \"%sSplCasterTest.php\"\n                  extension: \"php\"\n                  realPath: \"%sSplCasterTest.php\"\n                  aTime: %s-%s-%d %d:%d:%d\n                  mTime: %s-%s-%d %d:%d:%d\n                  cTime: %s-%s-%d %d:%d:%d\n                  inode: %i\n                  size: %d\n                  perms: 0%d\n                  owner: %d\n                  group: %d\n                  type: \"file\"\n                  writable: true\n                  readable: true\n                  executable: false\n                  file: true\n                  dir: false\n                  link: false\n                %A}\n                EOTXT\n            ],\n            ['http://example.com/about', <<<'EOTXT'\n                SplFileInfo {\n                %Apath: \"http://example.com\"\n                  filename: \"about\"\n                  basename: \"about\"\n                  pathname: \"http://example.com/about\"\n                  extension: \"\"\n                  realPath: false\n                %A}\n                EOTXT\n            ],\n        ];\n    }\n\n    #[DataProvider('getCastFileInfoTests')]\n    public function testCastFileInfo($file, $dump)\n    {\n        $this->assertDumpMatchesFormat($dump, new \\SplFileInfo($file));\n    }\n\n    public function testCastFileObject()\n    {\n        $var = new \\SplFileObject(__FILE__);\n        $var->setFlags(\\SplFileObject::DROP_NEW_LINE | \\SplFileObject::SKIP_EMPTY);\n        $dump = <<<'EOTXT'\n            SplFileObject {\n            %Apath: \"%sCaster\"\n              filename: \"SplCasterTest.php\"\n              basename: \"SplCasterTest.php\"\n              pathname: \"%sSplCasterTest.php\"\n              extension: \"php\"\n              realPath: \"%sSplCasterTest.php\"\n              aTime: %s-%s-%d %d:%d:%d\n              mTime: %s-%s-%d %d:%d:%d\n              cTime: %s-%s-%d %d:%d:%d\n              inode: %i\n              size: %d\n              perms: 0%d\n              owner: %d\n              group: %d\n              type: \"file\"\n              writable: true\n              readable: true\n              executable: false\n              file: true\n              dir: false\n              link: false\n            %AcsvControl: array:%d [\n                0 => \",\"\n                1 => \"\"\"\n            %A]\n              flags: DROP_NEW_LINE|SKIP_EMPTY\n              maxLineLen: 0\n              fstat: array:26 [\n                \"dev\" => %i\n                \"ino\" => %i\n                \"nlink\" => %d\n                \"rdev\" => 0\n                \"blksize\" => %i\n                \"blocks\" => %i\n                 …20\n              ]\n              eof: false\n              key: 0\n            }\n            EOTXT;\n        $this->assertDumpMatchesFormat($dump, $var);\n    }\n\n    #[DataProvider('provideCastSplDoublyLinkedList')]\n    public function testCastSplDoublyLinkedList($modeValue, $modeDump)\n    {\n        $var = new \\SplDoublyLinkedList();\n        $var->setIteratorMode($modeValue);\n        $dump = <<<EOTXT\n            SplDoublyLinkedList {\n            %Amode: $modeDump\n              dllist: []\n            }\n            EOTXT;\n        $this->assertDumpMatchesFormat($dump, $var);\n    }\n\n    public static function provideCastSplDoublyLinkedList()\n    {\n        return [\n            [\\SplDoublyLinkedList::IT_MODE_FIFO, 'IT_MODE_FIFO | IT_MODE_KEEP'],\n            [\\SplDoublyLinkedList::IT_MODE_LIFO, 'IT_MODE_LIFO | IT_MODE_KEEP'],\n            [\\SplDoublyLinkedList::IT_MODE_FIFO | \\SplDoublyLinkedList::IT_MODE_DELETE, 'IT_MODE_FIFO | IT_MODE_DELETE'],\n            [\\SplDoublyLinkedList::IT_MODE_LIFO | \\SplDoublyLinkedList::IT_MODE_DELETE, 'IT_MODE_LIFO | IT_MODE_DELETE'],\n        ];\n    }\n\n    public function testCastObjectStorageIsntModified()\n    {\n        $var = new \\SplObjectStorage();\n        $var[new \\stdClass()] = null;\n        $var->rewind();\n        $current = $var->current();\n\n        $this->assertDumpMatchesFormat('%A', $var);\n        $this->assertSame($current, $var->current());\n    }\n\n    public function testCastObjectStorageDumpsInfo()\n    {\n        $var = new \\SplObjectStorage();\n        $var[new \\stdClass()] = new \\DateTimeImmutable();\n\n        $this->assertDumpMatchesFormat('%ADateTimeImmutable%A', $var);\n    }\n\n    public function testCastArrayObject()\n    {\n        $var = new\n            #[\\AllowDynamicProperties]\n            class([123]) extends \\ArrayObject {};\n        $var->foo = 234;\n\n        $expected = <<<EOTXT\n            ArrayObject@anonymous {\n              +\"foo\": 234\n              storage: array:1 [\n                0 => 123\n              ]\n              flag::STD_PROP_LIST: false\n              flag::ARRAY_AS_PROPS: false\n              iteratorClass: \"ArrayIterator\"\n            }\n            EOTXT;\n        $this->assertDumpEquals($expected, $var);\n    }\n\n    public function testArrayIterator()\n    {\n        $var = new MyArrayIterator([234]);\n\n        $expected = <<<EOTXT\n            Symfony\\Component\\VarDumper\\Tests\\Caster\\MyArrayIterator {\n              -foo: 123\n              storage: array:1 [\n                0 => 234\n              ]\n              flag::STD_PROP_LIST: false\n              flag::ARRAY_AS_PROPS: false\n            }\n            EOTXT;\n        $this->assertDumpEquals($expected, $var);\n    }\n\n    public function testBadSplFileInfo()\n    {\n        $var = new BadSplFileInfo();\n\n        $expected = <<<EOTXT\n            Symfony\\Component\\VarDumper\\Tests\\Caster\\BadSplFileInfo {\n              ⚠: \"The parent constructor was not called: the object is in an invalid state\"\n            }\n            EOTXT;\n        $this->assertDumpEquals($expected, $var);\n    }\n\n    public function testWeakMap()\n    {\n        $var = new \\WeakMap();\n        $obj = new \\stdClass();\n        $var[$obj] = 123;\n\n        $expected = <<<EOTXT\n            WeakMap {\n              map: array:1 [\n                0 => {\n                  object: {}\n                  data: 123\n                }\n              ]\n            }\n            EOTXT;\n\n        $this->assertDumpEquals($expected, $var);\n    }\n}\n\nclass MyArrayIterator extends \\ArrayIterator\n{\n    private $foo = 123;\n}\n\nclass BadSplFileInfo extends \\SplFileInfo\n{\n    public function __construct()\n    {\n    }\n}\n"
  },
  {
    "path": "Tests/Caster/SqliteCasterTest.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Tests\\Caster;\n\nuse PHPUnit\\Framework\\Attributes\\RequiresPhpExtension;\nuse PHPUnit\\Framework\\TestCase;\nuse Symfony\\Component\\VarDumper\\Test\\VarDumperTestTrait;\n\n#[RequiresPhpExtension('sqlite3')]\nclass SqliteCasterTest extends TestCase\n{\n    use VarDumperTestTrait;\n\n    public function testSqlite3Result()\n    {\n        $db = new \\SQLite3(':memory:');\n        $db->exec('CREATE TABLE foo (id INTEGER PRIMARY KEY, bar TEXT)');\n        $db->exec('INSERT INTO foo (bar) VALUES (\"baz\")');\n        $stmt = $db->prepare('SELECT id, bar FROM foo');\n        $result = $stmt->execute();\n\n        $this->assertDumpMatchesFormat(\n            <<<'EODUMP'\n                SQLite3Result {\n                  columnNames: array:2 [\n                    0 => \"id\"\n                    1 => \"bar\"\n                  ]\n                }\n                EODUMP,\n            $result\n        );\n    }\n}\n"
  },
  {
    "path": "Tests/Caster/StubCasterTest.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Tests\\Caster;\n\nuse PHPUnit\\Framework\\TestCase;\nuse Symfony\\Component\\VarDumper\\Caster\\ArgsStub;\nuse Symfony\\Component\\VarDumper\\Caster\\ClassStub;\nuse Symfony\\Component\\VarDumper\\Caster\\LinkStub;\nuse Symfony\\Component\\VarDumper\\Caster\\ScalarStub;\nuse Symfony\\Component\\VarDumper\\Caster\\VirtualStub;\nuse Symfony\\Component\\VarDumper\\Cloner\\VarCloner;\nuse Symfony\\Component\\VarDumper\\Dumper\\HtmlDumper;\nuse Symfony\\Component\\VarDumper\\Test\\VarDumperTestTrait;\nuse Symfony\\Component\\VarDumper\\Tests\\Fixtures\\FooInterface;\nuse Symfony\\Component\\VarDumper\\Tests\\Fixtures\\VirtualProperty;\n\nclass StubCasterTest extends TestCase\n{\n    use VarDumperTestTrait;\n\n    public function testArgsStubWithDefaults($foo = 234, $bar = 456)\n    {\n        $args = [new ArgsStub([123], __FUNCTION__, __CLASS__)];\n\n        $expectedDump = <<<'EODUMP'\n            array:1 [\n              0 => {\n                $foo: 123\n              }\n            ]\n            EODUMP;\n\n        $this->assertDumpMatchesFormat($expectedDump, $args);\n    }\n\n    public function testArgsStubWithExtraArgs($foo = 234)\n    {\n        $args = [new ArgsStub([123, 456], __FUNCTION__, __CLASS__)];\n\n        $expectedDump = <<<'EODUMP'\n            array:1 [\n              0 => {\n                $foo: 123\n                ...: {\n                  456\n                }\n              }\n            ]\n            EODUMP;\n\n        $this->assertDumpMatchesFormat($expectedDump, $args);\n    }\n\n    public function testArgsStubNoParamWithExtraArgs()\n    {\n        $args = [new ArgsStub([123], __FUNCTION__, __CLASS__)];\n\n        $expectedDump = <<<'EODUMP'\n            array:1 [\n              0 => {\n                123\n              }\n            ]\n            EODUMP;\n\n        $this->assertDumpMatchesFormat($expectedDump, $args);\n    }\n\n    public function testArgsStubWithClosure()\n    {\n        $args = [new ArgsStub([123], '{closure}', null)];\n\n        $expectedDump = <<<'EODUMP'\n            array:1 [\n              0 => {\n                123\n              }\n            ]\n            EODUMP;\n\n        $this->assertDumpMatchesFormat($expectedDump, $args);\n    }\n\n    public function testEmptyStub()\n    {\n        $args = [new ScalarStub('🐛')];\n\n        $expectedDump = <<<'EODUMP'\n            array:1 [\n              0 => 🐛\n            ]\n            EODUMP;\n\n        $this->assertDumpMatchesFormat($expectedDump, $args);\n    }\n\n    public function testVirtualPropertyStub()\n    {\n        $class = new \\ReflectionClass(VirtualProperty::class);\n        $args = [new VirtualStub($class->getProperty('fullName'))];\n\n        $expectedDump = <<<'EODUMP'\n            array:1 [\n              0 => ~ string\n            ]\n            EODUMP;\n\n        $this->assertDumpMatchesFormat($expectedDump, $args);\n    }\n\n    public function testVirtualPropertyWithoutTypeStub()\n    {\n        $class = new \\ReflectionClass(VirtualProperty::class);\n        $args = [new VirtualStub($class->getProperty('noType'))];\n\n        $expectedDump = <<<'EODUMP'\n            array:1 [\n              0 => ~\n            ]\n            EODUMP;\n\n        $this->assertDumpMatchesFormat($expectedDump, $args);\n    }\n\n    public function testLinkStub()\n    {\n        $var = [new LinkStub(__CLASS__, 0, __FILE__)];\n\n        $cloner = new VarCloner();\n        $dumper = new HtmlDumper();\n        $dumper->setDumpHeader('<foo></foo>');\n        $dumper->setDumpBoundaries('<bar>', '</bar>');\n        $dumper->setDisplayOptions(['fileLinkFormat' => '%f:%l']);\n        $dump = $dumper->dump($cloner->cloneVar($var), true);\n\n        $expectedDump = <<<'EODUMP'\n            <foo></foo><bar><span class=sf-dump-note>array:1</span> [<samp data-depth=1 class=sf-dump-expanded>\n              <span class=sf-dump-index>0</span> => \"<a href=\"%sStubCasterTest.php:0\" rel=\"noopener noreferrer\"><span class=sf-dump-str title=\"55 characters\">Symfony\\Component\\VarDumper\\Tests\\Caster\\StubCasterTest</span></a>\"\n            </samp>]\n            </bar>\n            EODUMP;\n\n        $this->assertStringMatchesFormat($expectedDump, $dump);\n    }\n\n    public function testLinkStubWithNoFileLink()\n    {\n        $var = [new LinkStub('example.com', 0, 'http://example.com')];\n\n        $cloner = new VarCloner();\n        $dumper = new HtmlDumper();\n        $dumper->setDumpHeader('<foo></foo>');\n        $dumper->setDumpBoundaries('<bar>', '</bar>');\n        $dumper->setDisplayOptions(['fileLinkFormat' => '%f:%l']);\n        $dump = $dumper->dump($cloner->cloneVar($var), true);\n\n        $expectedDump = <<<'EODUMP'\n            <foo></foo><bar><span class=sf-dump-note>array:1</span> [<samp data-depth=1 class=sf-dump-expanded>\n              <span class=sf-dump-index>0</span> => \"<a href=\"http://example.com\" target=\"_blank\" rel=\"noopener noreferrer\"><span class=sf-dump-str title=\"11 characters\">example.com</span></a>\"\n            </samp>]\n            </bar>\n            EODUMP;\n\n        $this->assertStringMatchesFormat($expectedDump, $dump);\n    }\n\n    public function testClassStub()\n    {\n        $var = [new ClassStub('hello', [FooInterface::class, 'foo'])];\n\n        $cloner = new VarCloner();\n        $dumper = new HtmlDumper();\n        $dumper->setDumpHeader('<foo></foo>');\n        $dumper->setDumpBoundaries('<bar>', '</bar>');\n        $dump = $dumper->dump($cloner->cloneVar($var), true, ['fileLinkFormat' => '%f:%l']);\n\n        $expectedDump = <<<'EODUMP'\n            <foo></foo><bar><span class=sf-dump-note>array:1</span> [<samp data-depth=1 class=sf-dump-expanded>\n              <span class=sf-dump-index>0</span> => \"<a href=\"%sFooInterface.php:10\" rel=\"noopener noreferrer\"><span class=sf-dump-str title=\"40 characters\">hello(?stdClass $a, ?stdClass $b = null)</span></a>\"\n            </samp>]\n            </bar>\n            EODUMP;\n\n        $this->assertStringMatchesFormat($expectedDump, $dump);\n    }\n\n    public function testClassStubWithNotExistingClass()\n    {\n        $var = [new ClassStub(NotExisting::class)];\n\n        $cloner = new VarCloner();\n        $dumper = new HtmlDumper();\n        $dumper->setDumpHeader('<foo></foo>');\n        $dumper->setDumpBoundaries('<bar>', '</bar>');\n        $dump = $dumper->dump($cloner->cloneVar($var), true);\n\n        $expectedDump = <<<'EODUMP'\n            <foo></foo><bar><span class=sf-dump-note>array:1</span> [<samp data-depth=1 class=sf-dump-expanded>\n              <span class=sf-dump-index>0</span> => \"<span class=\"sf-dump-str sf-dump-ellipsization\" title=\"Symfony\\Component\\VarDumper\\Tests\\Caster\\NotExisting\n            52 characters\"><span class=\"sf-dump-ellipsis sf-dump-ellipsis-class\">Symfony\\Component\\VarDumper\\Tests\\Caster</span><span class=\"sf-dump-ellipsis sf-dump-ellipsis-class\">\\</span><span class=\"sf-dump-ellipsis-tail\">NotExisting</span></span>\"\n            </samp>]\n            </bar>\n            EODUMP;\n\n        $this->assertStringMatchesFormat($expectedDump, $dump);\n    }\n\n    public function testClassStubWithNotExistingMethod()\n    {\n        $var = [new ClassStub('hello', [FooInterface::class, 'missing'])];\n\n        $cloner = new VarCloner();\n        $dumper = new HtmlDumper();\n        $dumper->setDumpHeader('<foo></foo>');\n        $dumper->setDumpBoundaries('<bar>', '</bar>');\n        $dump = $dumper->dump($cloner->cloneVar($var), true, ['fileLinkFormat' => '%f:%l']);\n\n        $expectedDump = <<<'EODUMP'\n            <foo></foo><bar><span class=sf-dump-note>array:1</span> [<samp data-depth=1 class=sf-dump-expanded>\n              <span class=sf-dump-index>0</span> => \"<a href=\"%sFooInterface.php:5\" rel=\"noopener noreferrer\"><span class=sf-dump-str title=\"5 characters\">hello</span></a>\"\n            </samp>]\n            </bar>\n            EODUMP;\n\n        $this->assertStringMatchesFormat($expectedDump, $dump);\n    }\n\n    public function testClassStubWithAnonymousClass()\n    {\n        $var = [new ClassStub((new class extends \\Exception {\n        })::class)];\n\n        $cloner = new VarCloner();\n        $dumper = new HtmlDumper();\n        $dumper->setDumpHeader('<foo></foo>');\n        $dumper->setDumpBoundaries('<bar>', '</bar>');\n        $dump = $dumper->dump($cloner->cloneVar($var), true, ['fileLinkFormat' => '%f:%l']);\n\n        $expectedDump = <<<'EODUMP'\n            <foo></foo><bar><span class=sf-dump-note>array:1</span> [<samp data-depth=1 class=sf-dump-expanded>\n              <span class=sf-dump-index>0</span> => \"<a href=\"%sStubCasterTest.php:239\" rel=\"noopener noreferrer\"><span class=sf-dump-str title=\"19 characters\">Exception@anonymous</span></a>\"\n            </samp>]\n            </bar>\n            EODUMP;\n\n        $this->assertStringMatchesFormat($expectedDump, $dump);\n    }\n}\n"
  },
  {
    "path": "Tests/Caster/SymfonyCasterTest.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Tests\\Caster;\n\nuse PHPUnit\\Framework\\TestCase;\nuse Symfony\\Component\\Uid\\Ulid;\nuse Symfony\\Component\\Uid\\UuidV4;\nuse Symfony\\Component\\Uid\\UuidV6;\nuse Symfony\\Component\\VarDumper\\Test\\VarDumperTestTrait;\n\nfinal class SymfonyCasterTest extends TestCase\n{\n    use VarDumperTestTrait;\n\n    public function testCastUuid()\n    {\n        $uuid = new UuidV4('83a9db35-3c8c-4040-b3c1-02eccc00b419');\n        $expectedDump = <<<EODUMP\n            Symfony\\Component\\Uid\\UuidV4 {\n              #uid: \"83a9db35-3c8c-4040-b3c1-02eccc00b419\"\n              toBase58: \"HFzAAuYvev42cCjwqpnKqz\"\n              toBase32: \"43N7DKAF4C810B7G82XK601D0S\"\n            }\n            EODUMP;\n        $this->assertDumpEquals($expectedDump, $uuid);\n\n        $uuid = new UuidV6('1ebc50e9-8a23-6704-ad6f-59afd5cda7e5');\n        $expectedDump = <<<EODUMP\n            Symfony\\Component\\Uid\\UuidV6 {\n              #uid: \"1ebc50e9-8a23-6704-ad6f-59afd5cda7e5\"\n              toBase58: \"4o8c5m6v4L8h5teww36JDa\"\n              toBase32: \"0YQH8EK2H3CW2ATVTSNZAWV9Z5\"\n              time: \"2021-06-04 08:26:44.591386 UTC\"\n            }\n            EODUMP;\n\n        $this->assertDumpEquals($expectedDump, $uuid);\n    }\n\n    public function testCastUlid()\n    {\n        $ulid = new Ulid('01F7B252SZQGTSQGYSGACASAW6');\n        $expectedDump = <<<EODUMP\n            Symfony\\Component\\Uid\\Ulid {\n              #uid: \"01F7B252SZQGTSQGYSGACASAW6\"\n              toBase58: \"1Ba6pJPFWDwghSKFVvfQ1B\"\n              toRfc4122: \"0179d622-8b3f-bc35-9bc3-d98298acab86\"\n              time: \"2021-06-04 08:27:38.687 UTC\"\n            }\n            EODUMP;\n\n        $this->assertDumpEquals($expectedDump, $ulid);\n    }\n}\n"
  },
  {
    "path": "Tests/Caster/XmlReaderCasterTest.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Tests\\Caster;\n\nuse PHPUnit\\Framework\\TestCase;\nuse Symfony\\Component\\VarDumper\\Test\\VarDumperTestTrait;\n\n/**\n * @author Baptiste Clavié <clavie.b@gmail.com>\n */\nclass XmlReaderCasterTest extends TestCase\n{\n    use VarDumperTestTrait;\n\n    private \\XMLReader $reader;\n\n    protected function setUp(): void\n    {\n        $this->reader = new \\XMLReader();\n        $this->reader->open(__DIR__.'/../Fixtures/xml_reader.xml');\n    }\n\n    protected function tearDown(): void\n    {\n        $this->reader->close();\n    }\n\n    public function testParserProperty()\n    {\n        $this->reader->setParserProperty(\\XMLReader::SUBST_ENTITIES, true);\n\n        $expectedDump = <<<'EODUMP'\n            XMLReader {%A\n              +nodeType: ~ int\n            %A\n              parserProperties: {\n                SUBST_ENTITIES: true\n                 …3\n              }\n               …12\n            }\n            EODUMP;\n\n        $this->assertDumpMatchesFormat($expectedDump, $this->reader);\n    }\n\n    public static function provideNodes()\n    {\n        return [\n            [0, <<<'EODUMP'\n                XMLReader {\n                  +nodeType: NONE\n                   …13\n                }\n                EODUMP\n            ],\n            [1, <<<'EODUMP'\n                XMLReader {\n                  +localName: \"foo\"\n                  +nodeType: ELEMENT\n                  +baseURI: \"%sxml_reader.xml\"\n                   …11\n                }\n                EODUMP\n            ],\n            [2, <<<'EODUMP'\n                XMLReader {\n                  +localName: \"#text\"\n                  +nodeType: SIGNIFICANT_WHITESPACE\n                  +depth: 1\n                  +value: \"\"\"\n                    \\n\n                        \n                    \"\"\"\n                  +baseURI: \"%sxml_reader.xml\"\n                   …9\n                }\n                EODUMP\n            ],\n            [3, <<<'EODUMP'\n                XMLReader {\n                  +localName: \"bar\"\n                  +nodeType: ELEMENT\n                  +depth: 1\n                  +baseURI: \"%sxml_reader.xml\"\n                   …10\n                }\n                EODUMP\n            ],\n            [4, <<<'EODUMP'\n                XMLReader {\n                  +localName: \"bar\"\n                  +nodeType: END_ELEMENT\n                  +depth: 1\n                  +baseURI: \"%sxml_reader.xml\"\n                   …10\n                }\n                EODUMP\n            ],\n            [6, <<<'EODUMP'\n                XMLReader {\n                  +localName: \"bar\"\n                  +nodeType: ELEMENT\n                  +depth: 1\n                  +isEmptyElement: true\n                  +baseURI: \"%sxml_reader.xml\"\n                   …9\n                }\n                EODUMP\n            ],\n            [9, <<<'EODUMP'\n                XMLReader {\n                  +localName: \"#text\"\n                  +nodeType: TEXT\n                  +depth: 2\n                  +value: \"With text\"\n                  +baseURI: \"%sxml_reader.xml\"\n                   …9\n                }\n                EODUMP\n            ],\n            [12, <<<'EODUMP'\n                XMLReader {\n                  +localName: \"bar\"\n                  +nodeType: ELEMENT\n                  +depth: 1\n                  +attributeCount: 2\n                  +baseURI: \"%sxml_reader.xml\"\n                   …9\n                }\n                EODUMP\n            ],\n            [13, <<<'EODUMP'\n                XMLReader {\n                  +localName: \"bar\"\n                  +nodeType: END_ELEMENT\n                  +depth: 1\n                  +baseURI: \"%sxml_reader.xml\"\n                   …10\n                }\n                EODUMP\n            ],\n            [15, <<<'EODUMP'\n                XMLReader {\n                  +localName: \"bar\"\n                  +nodeType: ELEMENT\n                  +depth: 1\n                  +attributeCount: 1\n                  +baseURI: \"%sxml_reader.xml\"\n                   …9\n                }\n                EODUMP\n            ],\n            [16, <<<'EODUMP'\n                XMLReader {\n                  +localName: \"#text\"\n                  +nodeType: SIGNIFICANT_WHITESPACE\n                  +depth: 2\n                  +value: \"\"\"\n                    \\n\n                            \n                    \"\"\"\n                  +baseURI: \"%sxml_reader.xml\"\n                   …9\n                }\n                EODUMP\n            ],\n            [17, <<<'EODUMP'\n                XMLReader {\n                  +localName: \"baz\"\n                  +prefix: \"baz\"\n                  +nodeType: ELEMENT\n                  +depth: 2\n                  +namespaceURI: \"http://symfony.com\"\n                  +baseURI: \"%sxml_reader.xml\"\n                   …8\n                }\n                EODUMP\n            ],\n            [18, <<<'EODUMP'\n                XMLReader {\n                  +localName: \"baz\"\n                  +prefix: \"baz\"\n                  +nodeType: END_ELEMENT\n                  +depth: 2\n                  +namespaceURI: \"http://symfony.com\"\n                  +baseURI: \"%sxml_reader.xml\"\n                   …8\n                }\n                EODUMP\n            ],\n            [19, <<<'EODUMP'\n                XMLReader {\n                  +localName: \"#text\"\n                  +nodeType: SIGNIFICANT_WHITESPACE\n                  +depth: 2\n                  +value: \"\"\"\n                    \\n\n                        \n                    \"\"\"\n                  +baseURI: \"%sxml_reader.xml\"\n                   …9\n                }\n                EODUMP\n            ],\n            [21, <<<'EODUMP'\n                XMLReader {\n                  +localName: \"#text\"\n                  +nodeType: SIGNIFICANT_WHITESPACE\n                  +depth: 1\n                  +value: \"\\n\"\n                  +baseURI: \"%sxml_reader.xml\"\n                   …9\n                }\n                EODUMP\n            ],\n            [22, <<<'EODUMP'\n                XMLReader {\n                  +localName: \"foo\"\n                  +nodeType: END_ELEMENT\n                  +baseURI: \"%sxml_reader.xml\"\n                   …11\n                }\n                EODUMP\n            ],\n        ];\n    }\n\n    public function testWithUninitializedXMLReader()\n    {\n        $this->reader = new \\XMLReader();\n\n        $expectedDump = <<<'EODUMP'\n            XMLReader {%A\n              +nodeType: ~ int\n            %A\n               …13\n            }\n            EODUMP;\n\n        $this->assertDumpMatchesFormat($expectedDump, $this->reader);\n    }\n}\n"
  },
  {
    "path": "Tests/Cloner/DataTest.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Tests\\Cloner;\n\nuse PHPUnit\\Framework\\TestCase;\nuse Symfony\\Component\\VarDumper\\Caster\\Caster;\nuse Symfony\\Component\\VarDumper\\Caster\\ClassStub;\nuse Symfony\\Component\\VarDumper\\Cloner\\Data;\nuse Symfony\\Component\\VarDumper\\Cloner\\VarCloner;\n\nclass DataTest extends TestCase\n{\n    public function testBasicData()\n    {\n        $values = [1 => 123, 4.5, 'abc', null, false];\n        $data = $this->cloneVar($values);\n        $clonedValues = [];\n\n        $this->assertInstanceOf(Data::class, $data);\n        $this->assertCount(\\count($values), $data);\n        $this->assertFalse(isset($data->{0}));\n        $this->assertFalse(isset($data[0]));\n\n        foreach ($data as $k => $v) {\n            $this->assertTrue(isset($data->{$k}));\n            $this->assertTrue(isset($data[$k]));\n            $this->assertSame(\\gettype($values[$k]), $data->seek($k)->getType());\n            $this->assertSame($values[$k], $data->seek($k)->getValue());\n            $this->assertSame($values[$k], $data->{$k});\n            $this->assertSame($values[$k], $data[$k]);\n            $this->assertSame((string) $values[$k], (string) $data->seek($k));\n\n            $clonedValues[$k] = $v->getValue();\n        }\n\n        $this->assertSame($values, $clonedValues);\n    }\n\n    public function testObject()\n    {\n        $data = $this->cloneVar(new \\Exception('foo'));\n\n        $this->assertSame('Exception', $data->getType());\n\n        $this->assertSame('foo', $data->message);\n        $this->assertSame('foo', $data->{Caster::PREFIX_PROTECTED.'message'});\n\n        $this->assertSame('foo', $data['message']);\n        $this->assertSame('foo', $data[Caster::PREFIX_PROTECTED.'message']);\n\n        $this->assertStringMatchesFormat('Exception (count=%d)', (string) $data);\n    }\n\n    public function testArray()\n    {\n        $values = [[], [123]];\n        $data = $this->cloneVar($values);\n\n        $this->assertSame($values, $data->getValue(true));\n\n        $children = $data->getValue();\n\n        $this->assertIsArray($children);\n\n        $this->assertInstanceOf(Data::class, $children[0]);\n        $this->assertInstanceOf(Data::class, $children[1]);\n\n        $this->assertEquals($children[0], $data[0]);\n        $this->assertEquals($children[1], $data[1]);\n\n        $this->assertSame($values[0], $children[0]->getValue(true));\n        $this->assertSame($values[1], $children[1]->getValue(true));\n    }\n\n    public function testStub()\n    {\n        $data = $this->cloneVar([new ClassStub('stdClass')]);\n        $data = $data[0];\n\n        $this->assertSame('string', $data->getType());\n        $this->assertSame('stdClass', $data->getValue());\n        $this->assertSame('stdClass', (string) $data);\n    }\n\n    public function testHardRefs()\n    {\n        $values = [[]];\n        $values[1] = &$values[0];\n        $values[2][0] = &$values[2];\n\n        $data = $this->cloneVar($values);\n\n        $this->assertSame([], $data[0]->getValue());\n        $this->assertSame([], $data[1]->getValue());\n        $this->assertEquals([$data[2]->getValue()], $data[2]->getValue(true));\n\n        $this->assertSame('array (count=3)', (string) $data);\n    }\n\n    private function cloneVar($value)\n    {\n        $cloner = new VarCloner();\n\n        return $cloner->cloneVar($value);\n    }\n}\n"
  },
  {
    "path": "Tests/Cloner/StubTest.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Tests\\Cloner;\n\nuse PHPUnit\\Framework\\TestCase;\nuse Symfony\\Component\\VarDumper\\Cloner\\Stub;\n\nfinal class StubTest extends TestCase\n{\n    public function testUnserializeNullValue()\n    {\n        $stub = new Stub();\n        $stub->value = null;\n\n        $stub = unserialize(serialize($stub));\n\n        self::assertNull($stub->value);\n    }\n\n    public function testUnserializeNullInTypedProperty()\n    {\n        $stub = new MyStub();\n        $stub->myProp = null;\n\n        $stub = unserialize(serialize($stub));\n\n        self::assertNull($stub->myProp);\n    }\n\n    public function testUninitializedStubPropertiesAreLeftUninitialized()\n    {\n        $stub = new MyStub();\n\n        $stub = unserialize(serialize($stub));\n\n        $r = new \\ReflectionProperty(MyStub::class, 'myProp');\n        self::assertFalse($r->isInitialized($stub));\n    }\n}\n\nfinal class MyStub extends Stub\n{\n    public mixed $myProp;\n}\n"
  },
  {
    "path": "Tests/Cloner/VarClonerTest.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Tests\\Cloner;\n\nuse PHPUnit\\Framework\\TestCase;\nuse Symfony\\Component\\VarDumper\\Caster\\DateCaster;\nuse Symfony\\Component\\VarDumper\\Cloner\\AbstractCloner;\nuse Symfony\\Component\\VarDumper\\Cloner\\Stub;\nuse Symfony\\Component\\VarDumper\\Cloner\\VarCloner;\nuse Symfony\\Component\\VarDumper\\Dumper\\CliDumper;\nuse Symfony\\Component\\VarDumper\\Tests\\Fixtures\\Php74;\nuse Symfony\\Component\\VarDumper\\Tests\\Fixtures\\Php81Enums;\n\n/**\n * @author Nicolas Grekas <p@tchwork.com>\n */\nclass VarClonerTest extends TestCase\n{\n    public function testAddCaster()\n    {\n        $o1 = new class {\n            public string $p1 = 'p1';\n        };\n        $o2 = new class {\n            public string $p2 = 'p2';\n        };\n\n        AbstractCloner::addDefaultCasters([\n            $o1::class => static function ($obj, $array) {\n                $array['p1'] = 123;\n\n                return $array;\n            },\n            // Test we can override the default casters\n            \\DateTimeInterface::class => static function (\\DateTimeInterface $obj, $array, Stub $stub, bool $isNested, int $filter) {\n                $array = DateCaster::castDateTime($obj, $array, $stub, $isNested, $filter);\n                $array['foo'] = 'bar';\n\n                return $array;\n            },\n        ]);\n        $cloner = new VarCloner();\n        $cloner->addCasters([\n            $o2::class => static function ($obj, $array) {\n                $array['p2'] = 456;\n\n                return $array;\n            },\n        ]);\n\n        $dumper = new CliDumper('php://output');\n        $dumper->setColors(false);\n\n        ob_start();\n        $dumper->dump($cloner->cloneVar([$o1, $o2, new \\DateTime('Mon Jan 4 15:26:20 2010 +0100')]));\n        $out = ob_get_clean();\n        $out = preg_replace('/[ \\t]+$/m', '', $out);\n        $this->assertStringMatchesFormat(\n            <<<EOTXT\n                array:3 [\n                  0 => class@anonymous {#%d\n                    +p1: 123\n                  }\n                  1 => class@anonymous {#%d\n                    +p2: 456\n                  }\n                  2 => DateTime @1262615180 {#%d\n                    date: 2010-01-04 15:26:20.0 +01:00\n                    +foo: \"bar\"\n                  }\n                ]\n                EOTXT,\n            $out\n        );\n    }\n\n    public function testMaxIntBoundary()\n    {\n        $data = [\\PHP_INT_MAX => 123];\n\n        $cloner = new VarCloner();\n        $clone = $cloner->cloneVar($data);\n\n        $expected = <<<EOTXT\n            Symfony\\Component\\VarDumper\\Cloner\\Data Object\n            (\n                [data:Symfony\\Component\\VarDumper\\Cloner\\Data:private] => Array\n                    (\n                        [0] => Array\n                            (\n                                [0] => Array\n                                    (\n                                        [1] => 1\n                                    )\n\n                            )\n\n                        [1] => Array\n                            (\n                                [%s] => 123\n                            )\n\n                    )\n\n                [position:Symfony\\Component\\VarDumper\\Cloner\\Data:private] => 0\n                [key:Symfony\\Component\\VarDumper\\Cloner\\Data:private] => 0\n                [maxDepth:Symfony\\Component\\VarDumper\\Cloner\\Data:private] => 20\n                [maxItemsPerDepth:Symfony\\Component\\VarDumper\\Cloner\\Data:private] => -1\n                [useRefHandles:Symfony\\Component\\VarDumper\\Cloner\\Data:private] => -1\n                [context:Symfony\\Component\\VarDumper\\Cloner\\Data:private] => Array\n                    (\n                    )\n\n            )\n\n            EOTXT;\n        $this->assertSame(\\sprintf($expected, \\PHP_INT_MAX), print_r($clone, true));\n    }\n\n    public function testClone()\n    {\n        $json = json_decode('{\"1\":{\"var\":\"val\"},\"2\":{\"var\":\"val\"}}');\n\n        $cloner = new VarCloner();\n        $clone = $cloner->cloneVar($json);\n\n        $expected = <<<EOTXT\n            Symfony\\Component\\VarDumper\\Cloner\\Data Object\n            (\n                [data:Symfony\\Component\\VarDumper\\Cloner\\Data:private] => Array\n                    (\n                        [0] => Array\n                            (\n                                [0] => Symfony\\Component\\VarDumper\\Cloner\\Stub Object\n                                    (\n                                        [type] => 4\n                                        [class] => stdClass\n                                        [value] => \n                                        [cut] => 0\n                                        [handle] => %i\n                                        [refCount] => 0\n                                        [position] => 1\n                                        [attr] => Array\n                                            (\n                                            )\n\n                                    )\n\n                            )\n\n                        [1] => Array\n                            (\n                                [\\000+\\0001] => Symfony\\Component\\VarDumper\\Cloner\\Stub Object\n                                    (\n                                        [type] => 4\n                                        [class] => stdClass\n                                        [value] => \n                                        [cut] => 0\n                                        [handle] => %i\n                                        [refCount] => 0\n                                        [position] => 2\n                                        [attr] => Array\n                                            (\n                                            )\n\n                                    )\n\n                                [\\000+\\0002] => Symfony\\Component\\VarDumper\\Cloner\\Stub Object\n                                    (\n                                        [type] => 4\n                                        [class] => stdClass\n                                        [value] => \n                                        [cut] => 0\n                                        [handle] => %i\n                                        [refCount] => 0\n                                        [position] => 3\n                                        [attr] => Array\n                                            (\n                                            )\n\n                                    )\n\n                            )\n\n                        [2] => Array\n                            (\n                                [\\000+\\000var] => val\n                            )\n\n                        [3] => Array\n                            (\n                                [\\000+\\000var] => val\n                            )\n\n                    )\n\n                [position:Symfony\\Component\\VarDumper\\Cloner\\Data:private] => 0\n                [key:Symfony\\Component\\VarDumper\\Cloner\\Data:private] => 0\n                [maxDepth:Symfony\\Component\\VarDumper\\Cloner\\Data:private] => 20\n                [maxItemsPerDepth:Symfony\\Component\\VarDumper\\Cloner\\Data:private] => -1\n                [useRefHandles:Symfony\\Component\\VarDumper\\Cloner\\Data:private] => -1\n                [context:Symfony\\Component\\VarDumper\\Cloner\\Data:private] => Array\n                    (\n                    )\n\n            )\n\n            EOTXT;\n        $this->assertStringMatchesFormat($expected, print_r($clone, true));\n    }\n\n    public function testLimits()\n    {\n        // Level 0:\n        $data = [\n            // Level 1:\n            [\n                // Level 2:\n                [\n                    // Level 3:\n                    'Level 3 Item 0',\n                    'Level 3 Item 1',\n                    'Level 3 Item 2',\n                    'Level 3 Item 3',\n                ],\n                [\n                    999 => 'Level 3 Item 4',\n                    'Level 3 Item 5',\n                    'Level 3 Item 6',\n                ],\n                [\n                    'Level 3 Item 7',\n                ],\n            ],\n            [\n                [\n                    'Level 3 Item 8',\n                ],\n                'Level 2 Item 0',\n            ],\n            [\n                'Level 2 Item 1',\n            ],\n            'Level 1 Item 0',\n            [\n                // Test setMaxString:\n                'ABCDEFGHIJKLMNOPQRSTUVWXYZ',\n                'SHORT',\n            ],\n        ];\n\n        $cloner = new VarCloner();\n        $cloner->setMinDepth(2);\n        $cloner->setMaxItems(5);\n        $cloner->setMaxString(20);\n        $clone = $cloner->cloneVar($data);\n\n        $expected = <<<EOTXT\n            Symfony\\Component\\VarDumper\\Cloner\\Data Object\n            (\n                [data:Symfony\\Component\\VarDumper\\Cloner\\Data:private] => Array\n                    (\n                        [0] => Array\n                            (\n                                [0] => Array\n                                    (\n                                        [2] => 1\n                                    )\n\n                            )\n\n                        [1] => Array\n                            (\n                                [0] => Array\n                                    (\n                                        [2] => 2\n                                    )\n\n                                [1] => Array\n                                    (\n                                        [2] => 3\n                                    )\n\n                                [2] => Array\n                                    (\n                                        [2] => 4\n                                    )\n\n                                [3] => Level 1 Item 0\n                                [4] => Array\n                                    (\n                                        [2] => 5\n                                    )\n\n                            )\n\n                        [2] => Array\n                            (\n                                [0] => Array\n                                    (\n                                        [2] => 6\n                                    )\n\n                                [1] => Array\n                                    (\n                                        [0] => 2\n                                        [1] => 7\n                                    )\n\n                                [2] => Array\n                                    (\n                                        [0] => 1\n                                        [2] => 0\n                                    )\n\n                            )\n\n                        [3] => Array\n                            (\n                                [0] => Array\n                                    (\n                                        [0] => 1\n                                        [2] => 0\n                                    )\n\n                                [1] => Level 2 Item 0\n                            )\n\n                        [4] => Array\n                            (\n                                [0] => Level 2 Item 1\n                            )\n\n                        [5] => Array\n                            (\n                                [0] => Symfony\\Component\\VarDumper\\Cloner\\Stub Object\n                                    (\n                                        [type] => 2\n                                        [class] => 2\n                                        [value] => ABCDEFGHIJKLMNOPQRST\n                                        [cut] => 6\n                                        [handle] => 0\n                                        [refCount] => 0\n                                        [position] => 0\n                                        [attr] => Array\n                                            (\n                                            )\n\n                                    )\n\n                                [1] => SHORT\n                            )\n\n                        [6] => Array\n                            (\n                                [0] => Level 3 Item 0\n                                [1] => Level 3 Item 1\n                                [2] => Level 3 Item 2\n                                [3] => Level 3 Item 3\n                            )\n\n                        [7] => Array\n                            (\n                                [999] => Level 3 Item 4\n                            )\n\n                    )\n\n                [position:Symfony\\Component\\VarDumper\\Cloner\\Data:private] => 0\n                [key:Symfony\\Component\\VarDumper\\Cloner\\Data:private] => 0\n                [maxDepth:Symfony\\Component\\VarDumper\\Cloner\\Data:private] => 20\n                [maxItemsPerDepth:Symfony\\Component\\VarDumper\\Cloner\\Data:private] => -1\n                [useRefHandles:Symfony\\Component\\VarDumper\\Cloner\\Data:private] => -1\n                [context:Symfony\\Component\\VarDumper\\Cloner\\Data:private] => Array\n                    (\n                    )\n\n            )\n\n            EOTXT;\n        $this->assertStringMatchesFormat($expected, print_r($clone, true));\n    }\n\n    public function testJsonCast()\n    {\n        if (2 == \\ini_get('xdebug.overload_var_dump')) {\n            $this->markTestSkipped('xdebug is active');\n        }\n\n        $data = (array) json_decode('{\"1\":{}}');\n\n        $cloner = new VarCloner();\n        $clone = $cloner->cloneVar($data);\n\n        $expected = <<<'EOTXT'\n            object(Symfony\\Component\\VarDumper\\Cloner\\Data)#%d (7) {\n              [\"data\":\"Symfony\\Component\\VarDumper\\Cloner\\Data\":private]=>\n              array(2) {\n                [0]=>\n                array(1) {\n                  [0]=>\n                  array(1) {\n                    [1]=>\n                    int(1)\n                  }\n                }\n                [1]=>\n                array(1) {\n                  [\"1\"]=>\n                  object(Symfony\\Component\\VarDumper\\Cloner\\Stub)#%i (8) {\n                    [\"type\"]=>\n                    int(4)\n                    [\"class\"]=>\n                    string(8) \"stdClass\"\n                    [\"value\"]=>\n                    NULL\n                    [\"cut\"]=>\n                    int(0)\n                    [\"handle\"]=>\n                    int(%i)\n                    [\"refCount\"]=>\n                    int(0)\n                    [\"position\"]=>\n                    int(0)\n                    [\"attr\"]=>\n                    array(0) {\n                    }\n                  }\n                }\n              }\n              [\"position\":\"Symfony\\Component\\VarDumper\\Cloner\\Data\":private]=>\n              int(0)\n              [\"key\":\"Symfony\\Component\\VarDumper\\Cloner\\Data\":private]=>\n              int(0)\n              [\"maxDepth\":\"Symfony\\Component\\VarDumper\\Cloner\\Data\":private]=>\n              int(20)\n              [\"maxItemsPerDepth\":\"Symfony\\Component\\VarDumper\\Cloner\\Data\":private]=>\n              int(-1)\n              [\"useRefHandles\":\"Symfony\\Component\\VarDumper\\Cloner\\Data\":private]=>\n              int(-1)\n              [\"context\":\"Symfony\\Component\\VarDumper\\Cloner\\Data\":private]=>\n              array(0) {\n              }\n            }\n\n            EOTXT;\n        ob_start();\n        var_dump($clone);\n        $this->assertStringMatchesFormat(str_replace('\"1\"', '1', $expected), ob_get_clean());\n    }\n\n    public function testCaster()\n    {\n        $cloner = new VarCloner([\n            '*' => static fn ($obj, $array) => ['foo' => 123],\n            __CLASS__ => static function ($obj, $array) {\n                ++$array['foo'];\n\n                return $array;\n            },\n        ]);\n        $clone = $cloner->cloneVar($this);\n\n        $expected = <<<EOTXT\n            Symfony\\Component\\VarDumper\\Cloner\\Data Object\n            (\n                [data:Symfony\\Component\\VarDumper\\Cloner\\Data:private] => Array\n                    (\n                        [0] => Array\n                            (\n                                [0] => Symfony\\Component\\VarDumper\\Cloner\\Stub Object\n                                    (\n                                        [type] => 4\n                                        [class] => %s\n                                        [value] => \n                                        [cut] => 0\n                                        [handle] => %i\n                                        [refCount] => 0\n                                        [position] => 1\n                                        [attr] => Array\n                                            (\n                                                [file] => %a%eVarClonerTest.php\n                                                [line] => 26\n                                            )\n\n                                    )\n\n                            )\n\n                        [1] => Array\n                            (\n                                [foo] => 124\n                            )\n\n                    )\n\n                [position:Symfony\\Component\\VarDumper\\Cloner\\Data:private] => 0\n                [key:Symfony\\Component\\VarDumper\\Cloner\\Data:private] => 0\n                [maxDepth:Symfony\\Component\\VarDumper\\Cloner\\Data:private] => 20\n                [maxItemsPerDepth:Symfony\\Component\\VarDumper\\Cloner\\Data:private] => -1\n                [useRefHandles:Symfony\\Component\\VarDumper\\Cloner\\Data:private] => -1\n                [context:Symfony\\Component\\VarDumper\\Cloner\\Data:private] => Array\n                    (\n                    )\n\n            )\n\n            EOTXT;\n        $this->assertStringMatchesFormat($expected, print_r($clone, true));\n    }\n\n    public function testPhp74()\n    {\n        $data = new Php74();\n\n        $cloner = new VarCloner();\n        $clone = $cloner->cloneVar($data);\n\n        $expected = <<<'EOTXT'\n            Symfony\\Component\\VarDumper\\Cloner\\Data Object\n            (\n                [data:Symfony\\Component\\VarDumper\\Cloner\\Data:private] => Array\n                    (\n                        [0] => Array\n                            (\n                                [0] => Symfony\\Component\\VarDumper\\Cloner\\Stub Object\n                                    (\n                                        [type] => 4\n                                        [class] => Symfony\\Component\\VarDumper\\Tests\\Fixtures\\Php74\n                                        [value] => \n                                        [cut] => 0\n                                        [handle] => %i\n                                        [refCount] => 0\n                                        [position] => 1\n                                        [attr] => Array\n                                            (\n                                                [file] => %s\n                                                [line] => 5\n                                            )\n\n                                    )\n\n                            )\n\n                        [1] => Array\n                            (\n                                [p1] => 123\n                                [p2] => Symfony\\Component\\VarDumper\\Cloner\\Stub Object\n                                    (\n                                        [type] => 1\n                                        [class] => \n                                        [value] => Symfony\\Component\\VarDumper\\Cloner\\Stub Object\n                                            (\n                                                [type] => 4\n                                                [class] => stdClass\n                                                [value] => \n                                                [cut] => 0\n                                                [handle] => %i\n                                                [refCount] => 1\n                                                [position] => 0\n                                                [attr] => Array\n                                                    (\n                                                    )\n\n                                            )\n\n                                        [cut] => 0\n                                        [handle] => 1\n                                        [refCount] => 1\n                                        [position] => 0\n                                        [attr] => Array\n                                            (\n                                            )\n\n                                    )\n\n                                [p3] => Symfony\\Component\\VarDumper\\Cloner\\Stub Object\n                                    (\n                                        [type] => 1\n                                        [class] => \n                                        [value] => Symfony\\Component\\VarDumper\\Cloner\\Stub Object\n                                            (\n                                                [type] => 4\n                                                [class] => stdClass\n                                                [value] => \n                                                [cut] => 0\n                                                [handle] => %i\n                                                [refCount] => 1\n                                                [position] => 0\n                                                [attr] => Array\n                                                    (\n                                                    )\n\n                                            )\n\n                                        [cut] => 0\n                                        [handle] => 1\n                                        [refCount] => 1\n                                        [position] => 0\n                                        [attr] => Array\n                                            (\n                                            )\n\n                                    )\n\n                            )\n\n                    )\n\n                [position:Symfony\\Component\\VarDumper\\Cloner\\Data:private] => 0\n                [key:Symfony\\Component\\VarDumper\\Cloner\\Data:private] => 0\n                [maxDepth:Symfony\\Component\\VarDumper\\Cloner\\Data:private] => 20\n                [maxItemsPerDepth:Symfony\\Component\\VarDumper\\Cloner\\Data:private] => -1\n                [useRefHandles:Symfony\\Component\\VarDumper\\Cloner\\Data:private] => -1\n                [context:Symfony\\Component\\VarDumper\\Cloner\\Data:private] => Array\n                    (\n                    )\n\n            )\n\n            EOTXT;\n        $this->assertStringMatchesFormat($expected, print_r($clone, true));\n    }\n\n    public function testPhp81Enums()\n    {\n        $data = new Php81Enums();\n\n        $cloner = new VarCloner();\n        $clone = $cloner->cloneVar($data);\n\n        $expected = <<<'EOTXT'\n            Symfony\\Component\\VarDumper\\Cloner\\Data Object\n            (\n                [data:Symfony\\Component\\VarDumper\\Cloner\\Data:private] => Array\n                    (\n                        [0] => Array\n                            (\n                                [0] => Symfony\\Component\\VarDumper\\Cloner\\Stub Object\n                                    (\n                                        [type] => 4\n                                        [class] => Symfony\\Component\\VarDumper\\Tests\\Fixtures\\Php81Enums\n                                        [value] => \n                                        [cut] => 0\n                                        [handle] => %i\n                                        [refCount] => 0\n                                        [position] => 1\n                                        [attr] => Array\n                                            (\n                                                [file] => %s\n                                                [line] => 5\n                                            )\n\n                                    )\n\n                            )\n\n                        [1] => Array\n                            (\n                                [e1] => Symfony\\Component\\VarDumper\\Cloner\\Stub Object\n                                    (\n                                        [type] => 4\n                                        [class] => Symfony\\Component\\VarDumper\\Tests\\Fixtures\\UnitEnumFixture\n                                        [value] => \n                                        [cut] => 0\n                                        [handle] => %i\n                                        [refCount] => 0\n                                        [position] => 2\n                                        [attr] => Array\n                                            (\n                                                [file] => %s\n                                                [line] => 5\n                                            )\n\n                                    )\n\n                                [e2] => Symfony\\Component\\VarDumper\\Cloner\\Stub Object\n                                    (\n                                        [type] => 4\n                                        [class] => Symfony\\Component\\VarDumper\\Tests\\Fixtures\\BackedEnumFixture\n                                        [value] => \n                                        [cut] => 0\n                                        [handle] => %i\n                                        [refCount] => 0\n                                        [position] => 3\n                                        [attr] => Array\n                                            (\n                                                [file] => %s\n                                                [line] => 5\n                                            )\n\n                                    )\n\n                            )\n\n                        [2] => Array\n                            (\n                                [name] => Hearts\n                            )\n\n                        [3] => Array\n                            (\n                                [name] => Diamonds\n                                [value] => D\n                            )\n\n                    )\n\n                [position:Symfony\\Component\\VarDumper\\Cloner\\Data:private] => 0\n                [key:Symfony\\Component\\VarDumper\\Cloner\\Data:private] => 0\n                [maxDepth:Symfony\\Component\\VarDumper\\Cloner\\Data:private] => 20\n                [maxItemsPerDepth:Symfony\\Component\\VarDumper\\Cloner\\Data:private] => -1\n                [useRefHandles:Symfony\\Component\\VarDumper\\Cloner\\Data:private] => -1\n                [context:Symfony\\Component\\VarDumper\\Cloner\\Data:private] => Array\n                    (\n                    )\n\n            )\n\n            EOTXT;\n        $this->assertStringMatchesFormat($expected, print_r($clone, true));\n    }\n}\n"
  },
  {
    "path": "Tests/Command/Descriptor/CliDescriptorTest.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Tests\\Command\\Descriptor;\n\nuse PHPUnit\\Framework\\Attributes\\DataProvider;\nuse PHPUnit\\Framework\\TestCase;\nuse Symfony\\Component\\Console\\Output\\BufferedOutput;\nuse Symfony\\Component\\VarDumper\\Cloner\\Data;\nuse Symfony\\Component\\VarDumper\\Command\\Descriptor\\CliDescriptor;\nuse Symfony\\Component\\VarDumper\\Dumper\\CliDumper;\n\nclass CliDescriptorTest extends TestCase\n{\n    private static string $timezone;\n    private static string|false $prevTerminalEmulator;\n\n    public static function setUpBeforeClass(): void\n    {\n        self::$timezone = date_default_timezone_get();\n        date_default_timezone_set('UTC');\n\n        self::$prevTerminalEmulator = getenv('TERMINAL_EMULATOR');\n        putenv('TERMINAL_EMULATOR');\n    }\n\n    public static function tearDownAfterClass(): void\n    {\n        date_default_timezone_set(self::$timezone);\n        putenv('TERMINAL_EMULATOR'.(self::$prevTerminalEmulator ? '='.self::$prevTerminalEmulator : ''));\n    }\n\n    #[DataProvider('provideContext')]\n    public function testDescribe(array $context, string $expectedOutput, bool $decorated = false)\n    {\n        $output = new BufferedOutput();\n        $output->setDecorated($decorated);\n        $descriptor = new CliDescriptor(new CliDumper(static fn ($s) => $s));\n\n        $descriptor->describe($output, new Data([[123]]), $context + ['timestamp' => 1544804268.3668], 1);\n\n        $this->assertStringMatchesFormat(trim($expectedOutput), str_replace(\\PHP_EOL, \"\\n\", trim($output->fetch())));\n    }\n\n    public static function provideContext()\n    {\n        yield 'source' => [\n            [\n                'source' => [\n                    'name' => 'CliDescriptorTest.php',\n                    'line' => 30,\n                    'file' => '/Users/ogi/symfony/src/Symfony/Component/VarDumper/Tests/Command/Descriptor/CliDescriptorTest.php',\n                ],\n            ],\n            <<<TXT\n                Received from client #1\n                -----------------------\n\n                 -------- --------------------------------------------------------------------------------------------------- \n                  date     Fri, 14 Dec 2018 16:17:48 +0000                                                                    \n                  source   CliDescriptorTest.php on line 30                                                                   \n                  file     /Users/ogi/symfony/src/Symfony/Component/VarDumper/Tests/Command/Descriptor/CliDescriptorTest.php  \n                 -------- ---------------------------------------------------------------------------------------------------\n                TXT,\n        ];\n\n        yield 'source full' => [\n            [\n                'source' => [\n                    'name' => 'CliDescriptorTest.php',\n                    'line' => 30,\n                    'file_relative' => 'src/Symfony/Component/VarDumper/Tests/Command/Descriptor/CliDescriptorTest.php',\n                    'file' => '/Users/ogi/symfony/src/Symfony/Component/VarDumper/Tests/Command/Descriptor/CliDescriptorTest.php',\n                    'file_link' => 'phpstorm://open?file=/Users/ogi/symfony/src/Symfony/Component/VarDumper/Tests/Command/Descriptor/CliDescriptorTest.php&line=30',\n                ],\n            ],\n            <<<TXT\n                Received from client #1\n                -----------------------\n\n                 -------- -------------------------------------------------------------------------------- \n                  date     Fri, 14 Dec 2018 16:17:48 +0000                                                 \n                  source   CliDescriptorTest.php on line 30                                                \n                  file     src/Symfony/Component/VarDumper/Tests/Command/Descriptor/CliDescriptorTest.php  \n                 -------- -------------------------------------------------------------------------------- \n\n                TXT,\n        ];\n\n        yield 'source with hyperlink' => [\n            [\n                'source' => [\n                    'name' => 'CliDescriptorTest.php',\n                    'line' => 30,\n                    'file_relative' => 'src/Symfony/Component/VarDumper/Tests/Command/Descriptor/CliDescriptorTest.php',\n                    'file_link' => 'phpstorm://open?file=/Users/ogi/symfony/src/Symfony/Component/VarDumper/Tests/Command/Descriptor/CliDescriptorTest.php&line=30',\n                ],\n            ],\n            <<<TXT\n                %A\n                  source   \\033]8;;phpstorm://open?file=/Users/ogi/symfony/src/Symfony/Component/VarDumper/Tests/Command/Descriptor/CliDescriptorTest.php&line=30\\033\\CliDescriptorTest.php on line 30\\033]8;;\\033%A\n                %A\n                TXT,\n            true,\n        ];\n\n        yield 'cli' => [\n            [\n                'cli' => [\n                    'identifier' => 'd8bece1c',\n                    'command_line' => 'bin/phpunit',\n                ],\n            ],\n            <<<TXT\n                $ bin/phpunit\n                -------------\n\n                 ------ --------------------------------- \n                  date   Fri, 14 Dec 2018 16:17:48 +0000  \n                 ------ ---------------------------------\n                TXT,\n        ];\n\n        yield 'request' => [\n            [\n                'request' => [\n                    'identifier' => 'd8bece1c',\n                    'controller' => new Data([['FooController.php']]),\n                    'method' => 'GET',\n                    'uri' => 'http://localhost/foo',\n                ],\n            ],\n            <<<TXT\n                GET http://localhost/foo\n                ------------------------\n\n                 ------------ --------------------------------- \n                  date         Fri, 14 Dec 2018 16:17:48 +0000  \n                  controller   \"FooController.php\"              \n                 ------------ --------------------------------- \n                TXT,\n        ];\n    }\n}\n"
  },
  {
    "path": "Tests/Command/Descriptor/HtmlDescriptorTest.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Tests\\Command\\Descriptor;\n\nuse PHPUnit\\Framework\\Attributes\\DataProvider;\nuse PHPUnit\\Framework\\TestCase;\nuse Symfony\\Component\\Console\\Output\\BufferedOutput;\nuse Symfony\\Component\\VarDumper\\Cloner\\Data;\nuse Symfony\\Component\\VarDumper\\Command\\Descriptor\\HtmlDescriptor;\nuse Symfony\\Component\\VarDumper\\Dumper\\HtmlDumper;\n\nclass HtmlDescriptorTest extends TestCase\n{\n    private static string $timezone;\n\n    public static function setUpBeforeClass(): void\n    {\n        self::$timezone = date_default_timezone_get();\n        date_default_timezone_set('UTC');\n    }\n\n    public static function tearDownAfterClass(): void\n    {\n        date_default_timezone_set(self::$timezone);\n    }\n\n    public function testItOutputsStylesAndScriptsOnFirstDescribeCall()\n    {\n        $output = new BufferedOutput();\n        $dumper = $this->createStub(HtmlDumper::class);\n        $dumper->method('dump')->willReturn('[DUMPED]');\n        $descriptor = new HtmlDescriptor($dumper);\n\n        $descriptor->describe($output, new Data([[123]]), ['timestamp' => 1544804268.3668], 1);\n\n        $this->assertStringMatchesFormat('<style>%A</style><script>%A</script>%A', $output->fetch(), 'styles & scripts are output');\n\n        $descriptor->describe($output, new Data([[123]]), ['timestamp' => 1544804268.3668], 1);\n\n        $this->assertDoesNotMatchRegularExpression('#<style>(.*?)</style><script>(.*?)</script>(.*)#', $output->fetch(), 'styles & scripts are output only once');\n    }\n\n    #[DataProvider('provideContext')]\n    public function testDescribe(array $context, string $expectedOutput)\n    {\n        $output = new BufferedOutput();\n        $dumper = $this->createStub(HtmlDumper::class);\n        $dumper->method('dump')->willReturn('[DUMPED]');\n        $descriptor = new HtmlDescriptor($dumper);\n\n        $descriptor->describe($output, new Data([[123]]), $context + ['timestamp' => 1544804268.3668], 1);\n\n        $this->assertStringMatchesFormat(trim($expectedOutput), trim(preg_replace('@<style>.*</style><script>.*</script>@s', '', $output->fetch())));\n    }\n\n    public static function provideContext()\n    {\n        yield 'source' => [\n            [\n                'source' => [\n                    'name' => 'CliDescriptorTest.php',\n                    'line' => 30,\n                    'file' => '/Users/ogi/symfony/src/Symfony/Component/VarDumper/Tests/Command/Descriptor/CliDescriptorTest.php',\n                ],\n            ],\n            <<<TXT\n                <article data-dedup-id=\"%s\">\n                    <header>\n                        <div class=\"row\">\n                            <h2 class=\"col\">-</h2>\n                            <time class=\"col text-small\" title=\"2018-12-14T16:17:48+00:00\" datetime=\"2018-12-14T16:17:48+00:00\">\n                                Fri, 14 Dec 2018 16:17:48 +0000\n                            </time>\n                        </div>\n                        \n                    </header>\n                    <section class=\"body\">\n                        <p class=\"text-small\">\n                            CliDescriptorTest.php on line 30\n                        </p>\n                        [DUMPED]\n                    </section>\n                </article>\n                TXT,\n        ];\n\n        yield 'source full' => [\n            [\n                'source' => [\n                    'name' => 'CliDescriptorTest.php',\n                    'project_dir' => 'src/Symfony/',\n                    'line' => 30,\n                    'file_relative' => 'src/Symfony/Component/VarDumper/Tests/Command/Descriptor/CliDescriptorTest.php',\n                    'file' => '/Users/ogi/symfony/src/Symfony/Component/VarDumper/Tests/Command/Descriptor/CliDescriptorTest.php',\n                    'file_link' => 'phpstorm://open?file=/Users/ogi/symfony/src/Symfony/Component/VarDumper/Tests/Command/Descriptor/CliDescriptorTest.php&line=30',\n                ],\n            ],\n            <<<TXT\n                <article data-dedup-id=\"%s\">\n                    <header>\n                        <div class=\"row\">\n                            <h2 class=\"col\">-</h2>\n                            <time class=\"col text-small\" title=\"2018-12-14T16:17:48+00:00\" datetime=\"2018-12-14T16:17:48+00:00\">\n                                Fri, 14 Dec 2018 16:17:48 +0000\n                            </time>\n                        </div>\n                        <div class=\"row\">\n                    <ul class=\"tags\">\n                        <li><span class=\"badge\">project dir</span>src/Symfony/</li>\n                    </ul>\n                </div>\n                    </header>\n                    <section class=\"body\">\n                        <p class=\"text-small\">\n                            <a href=\"phpstorm://open?file=/Users/ogi/symfony/src/Symfony/Component/VarDumper/Tests/Command/Descriptor/CliDescriptorTest.php&line=30\">CliDescriptorTest.php on line 30</a>\n                        </p>\n                        [DUMPED]\n                    </section>\n                </article>\n                TXT,\n        ];\n\n        yield 'cli' => [\n            [\n                'cli' => [\n                    'identifier' => 'd8bece1c',\n                    'command_line' => 'bin/phpunit',\n                ],\n            ],\n            <<<TXT\n                <article data-dedup-id=\"d8bece1c\">\n                    <header>\n                        <div class=\"row\">\n                            <h2 class=\"col\"><code>$ </code>bin/phpunit</h2>\n                            <time class=\"col text-small\" title=\"2018-12-14T16:17:48+00:00\" datetime=\"2018-12-14T16:17:48+00:00\">\n                                Fri, 14 Dec 2018 16:17:48 +0000\n                            </time>\n                        </div>\n                        \n                    </header>\n                    <section class=\"body\">\n                        <p class=\"text-small\">\n                            \n                        </p>\n                        [DUMPED]\n                    </section>\n                </article>\n                TXT,\n        ];\n\n        yield 'request' => [\n            [\n                'request' => [\n                    'identifier' => 'd8bece1c',\n                    'controller' => new Data([['FooController.php']]),\n                    'method' => 'GET',\n                    'uri' => 'http://localhost/foo',\n                ],\n            ],\n            <<<TXT\n                <article data-dedup-id=\"d8bece1c\">\n                    <header>\n                        <div class=\"row\">\n                            <h2 class=\"col\"><code>GET</code> <a href=\"http://localhost/foo\">http://localhost/foo</a></h2>\n                            <time class=\"col text-small\" title=\"2018-12-14T16:17:48+00:00\" datetime=\"2018-12-14T16:17:48+00:00\">\n                                Fri, 14 Dec 2018 16:17:48 +0000\n                            </time>\n                        </div>\n                        <div class=\"row\">\n                    <ul class=\"tags\">\n                        <li><span class=\"badge\">controller</span><span class='dumped-tag'>[DUMPED]</span></li>\n                    </ul>\n                </div>\n                    </header>\n                    <section class=\"body\">\n                        <p class=\"text-small\">\n                            \n                        </p>\n                        [DUMPED]\n                    </section>\n                </article>\n                TXT,\n        ];\n    }\n}\n"
  },
  {
    "path": "Tests/Command/ServerDumpCommandTest.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Tests\\Command;\n\nuse PHPUnit\\Framework\\Attributes\\DataProvider;\nuse PHPUnit\\Framework\\TestCase;\nuse Symfony\\Component\\Console\\Tester\\CommandCompletionTester;\nuse Symfony\\Component\\VarDumper\\Command\\ServerDumpCommand;\nuse Symfony\\Component\\VarDumper\\Server\\DumpServer;\n\nclass ServerDumpCommandTest extends TestCase\n{\n    #[DataProvider('provideCompletionSuggestions')]\n    public function testComplete(array $input, array $expectedSuggestions)\n    {\n        $tester = new CommandCompletionTester($this->createCommand());\n\n        $this->assertSame($expectedSuggestions, $tester->complete($input));\n    }\n\n    public static function provideCompletionSuggestions()\n    {\n        yield 'option --format' => [\n            ['--format', ''],\n            ['cli', 'html'],\n        ];\n    }\n\n    private function createCommand(): ServerDumpCommand\n    {\n        return new ServerDumpCommand($this->createStub(DumpServer::class));\n    }\n}\n"
  },
  {
    "path": "Tests/Dumper/CliDumperTest.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Tests\\Dumper;\n\nuse PHPUnit\\Framework\\Attributes\\DataProvider;\nuse PHPUnit\\Framework\\TestCase;\nuse Symfony\\Component\\VarDumper\\Caster\\ClassStub;\nuse Symfony\\Component\\VarDumper\\Caster\\CutStub;\nuse Symfony\\Component\\VarDumper\\Cloner\\Data;\nuse Symfony\\Component\\VarDumper\\Cloner\\Stub;\nuse Symfony\\Component\\VarDumper\\Cloner\\VarCloner;\nuse Symfony\\Component\\VarDumper\\Dumper\\AbstractDumper;\nuse Symfony\\Component\\VarDumper\\Dumper\\CliDumper;\nuse Symfony\\Component\\VarDumper\\Test\\VarDumperTestTrait;\nuse Symfony\\Component\\VarDumper\\Tests\\Fixtures\\VirtualProperty;\nuse Twig\\Environment;\nuse Twig\\Loader\\FilesystemLoader;\n\n/**\n * @author Nicolas Grekas <p@tchwork.com>\n */\nclass CliDumperTest extends TestCase\n{\n    use VarDumperTestTrait;\n\n    public function testGet()\n    {\n        require __DIR__.'/../Fixtures/dumb-var.php';\n\n        $dumper = new CliDumper('php://output');\n        $dumper->setColors(false);\n        $cloner = new VarCloner();\n        $cloner->addCasters([\n            ':stream' => static function ($res, $a) {\n                unset($a['uri'], $a['wrapper_data']);\n\n                return $a;\n            },\n            'Symfony\\Component\\VarDumper\\Tests\\Fixture\\DumbFoo' => static function ($foo, $a) {\n                $a['foo'] = new CutStub($a['foo']);\n\n                return $a;\n            },\n        ]);\n        $data = $cloner->cloneVar($var);\n\n        ob_start();\n        $dumper->dump($data);\n        $out = ob_get_clean();\n        $out = preg_replace('/[ \\t]+$/m', '', $out);\n        $intMax = \\PHP_INT_MAX;\n        $res = (int) $var['res'];\n\n        $this->assertStringMatchesFormat(\n            <<<EOTXT\n                array:25 [\n                  \"number\" => 1\n                  0 => &1 null\n                  \"const\" => 1.1\n                  1 => true\n                  2 => false\n                  3 => NAN\n                  4 => INF\n                  5 => -INF\n                  6 => {$intMax}\n                  \"str\" => \"déjà\\\\n\"\n                  7 => b\"\"\"\n                    é\\\\x01test\\\\t\\\\n\n                    ing\n                    \"\"\"\n                  \"bo\\\\u{FEFF}m\" => \"te\\\\u{FEFF}st\"\n                  \"[]\" => []\n                  \"res\" => stream resource {@{$res}\n                %A  wrapper_type: \"plainfile\"\n                    stream_type: \"STDIO\"\n                    mode: \"r\"\n                    unread_bytes: 0\n                    seekable: true\n                %A  options: []\n                  }\n                  \"obj\" => Symfony\\Component\\VarDumper\\Tests\\Fixture\\DumbFoo {#%d\n                    +foo: \"\"…3\n                    +\"bar\": \"bar\"\n                  }\n                  \"closure\" => Closure(\\$a, ?PDO &\\$b = null) {#%d\n                    class: \"Symfony\\Component\\VarDumper\\Tests\\Dumper\\CliDumperTest\"\n                    this: Symfony\\Component\\VarDumper\\Tests\\Dumper\\CliDumperTest {#%d …}\n                    file: \"%s%eTests%eFixtures%edumb-var.php\"\n                    line: \"{$var['line']} to {$var['line']}\"\n                  }\n                  \"line\" => {$var['line']}\n                  \"nobj\" => array:1 [\n                    0 => &3 {#%d}\n                  ]\n                  \"recurs\" => &4 array:1 [\n                    0 => &4 array:1 [&4]\n                  ]\n                  8 => &1 null\n                  \"sobj\" => Symfony\\Component\\VarDumper\\Tests\\Fixture\\DumbFoo {#%d}\n                  \"snobj\" => &3 {#%d}\n                  \"snobj2\" => {#%d}\n                  \"file\" => \"{$var['file']}\"\n                  b\"bin-key-é\" => \"\"\n                ]\n\n                EOTXT,\n            $out\n        );\n    }\n\n    #[DataProvider('provideDumpWithCommaFlagTests')]\n    public function testDumpWithCommaFlag($expected, $flags)\n    {\n        $dumper = new CliDumper(null, null, $flags);\n        $dumper->setColors(false);\n        $cloner = new VarCloner();\n\n        $var = [\n            'array' => ['a', 'b'],\n            'string' => 'hello',\n            'multiline string' => \"this\\nis\\na\\multiline\\nstring\",\n        ];\n\n        $dump = $dumper->dump($cloner->cloneVar($var), true);\n\n        $this->assertSame($expected, $dump);\n    }\n\n    public function testDumpWithCommaFlagsAndExceptionCodeExcerpt()\n    {\n        $dumper = new CliDumper(null, null, CliDumper::DUMP_TRAILING_COMMA);\n        $dumper->setColors(false);\n        $cloner = new VarCloner();\n\n        $ex = new \\RuntimeException('foo');\n\n        $dump = $dumper->dump($cloner->cloneVar($ex)->withRefHandles(false), true);\n\n        $this->assertStringMatchesFormat(<<<'EOTXT'\n            RuntimeException {\n              #message: \"foo\"\n              #code: 0\n              #file: \"%ACliDumperTest.php\"\n              #line: %d\n              trace: {\n                %ACliDumperTest.php:%d {\n                  Symfony\\Component\\VarDumper\\Tests\\Dumper\\CliDumperTest->testDumpWithCommaFlagsAndExceptionCodeExcerpt()\n                  › \n                  › $ex = new \\RuntimeException('foo');\n                  › \n                }\n                %A\n              }\n            }\n\n            EOTXT,\n            $dump\n        );\n    }\n\n    public static function provideDumpWithCommaFlagTests()\n    {\n        $expected = <<<'EOTXT'\n            array:3 [\n              \"array\" => array:2 [\n                0 => \"a\",\n                1 => \"b\"\n              ],\n              \"string\" => \"hello\",\n              \"multiline string\" => \"\"\"\n                this\\n\n                is\\n\n                a\\multiline\\n\n                string\n                \"\"\"\n            ]\n\n            EOTXT;\n\n        yield [$expected, CliDumper::DUMP_COMMA_SEPARATOR];\n\n        $expected = <<<'EOTXT'\n            array:3 [\n              \"array\" => array:2 [\n                0 => \"a\",\n                1 => \"b\",\n              ],\n              \"string\" => \"hello\",\n              \"multiline string\" => \"\"\"\n                this\\n\n                is\\n\n                a\\multiline\\n\n                string\n                \"\"\",\n            ]\n\n            EOTXT;\n\n        yield [$expected, CliDumper::DUMP_TRAILING_COMMA];\n    }\n\n    public function testJsonCast()\n    {\n        $var = (array) json_decode('{\"0\":{},\"1\":null}');\n        foreach ($var as &$v) {\n        }\n        $var[] = &$v;\n        $var[''] = 2;\n\n        $this->assertDumpMatchesFormat(\n            <<<'EOTXT'\n                array:4 [\n                  0 => {}\n                  1 => &1 null\n                  2 => &1 null\n                  \"\" => 2\n                ]\n                EOTXT,\n            $var\n        );\n    }\n\n    public function testObjectCast()\n    {\n        $var = (object) [1 => 1];\n        $var->{1} = 2;\n\n        $this->assertDumpMatchesFormat(\n            <<<'EOTXT'\n                {\n                  +\"1\": 2\n                }\n                EOTXT,\n            $var\n        );\n    }\n\n    public function testClosedResource()\n    {\n        $var = fopen(__FILE__, 'r');\n        fclose($var);\n\n        $dumper = new CliDumper('php://output');\n        $dumper->setColors(false);\n        $cloner = new VarCloner();\n        $data = $cloner->cloneVar($var);\n\n        ob_start();\n        $dumper->dump($data);\n        $out = ob_get_clean();\n        $res = (int) $var;\n\n        $this->assertStringMatchesFormat(\n            <<<EOTXT\n                Closed resource @{$res}\n\n                EOTXT,\n            $out\n        );\n    }\n\n    public function testFlags()\n    {\n        putenv('DUMP_LIGHT_ARRAY=1');\n        putenv('DUMP_STRING_LENGTH=1');\n\n        $var = [\n            range(1, 3),\n            ['foo', 2 => 'bar'],\n        ];\n\n        $this->assertDumpEquals(\n            <<<EOTXT\n                [\n                  [\n                    1\n                    2\n                    3\n                  ]\n                  [\n                    0 => (3) \"foo\"\n                    2 => (3) \"bar\"\n                  ]\n                ]\n                EOTXT,\n            $var\n        );\n\n        putenv('DUMP_LIGHT_ARRAY=');\n        putenv('DUMP_STRING_LENGTH=');\n    }\n\n    public function testVirtualProperties()\n    {\n        $this->assertDumpEquals(<<<EODUMP\n            Symfony\\Component\\VarDumper\\Tests\\Fixtures\\VirtualProperty {\n              +firstName: \"John\"\n              +lastName: \"Doe\"\n              +fullName: ~ string\n              -noType: ~\n            }\n            EODUMP,\n            new VirtualProperty()\n        );\n    }\n\n    public function testThrowingCaster()\n    {\n        $out = fopen('php://memory', 'r+');\n\n        require_once __DIR__.'/../Fixtures/Twig.php';\n        $twig = new \\__TwigTemplate_VarDumperFixture_u75a09(new Environment(new FilesystemLoader()));\n\n        $dumper = new CliDumper();\n        $dumper->setColors(false);\n        $cloner = new VarCloner();\n        $cloner->addCasters([\n            ':stream' => static function ($res, $a) {\n                unset($a['wrapper_data']);\n\n                return $a;\n            },\n        ]);\n        $cloner->addCasters([\n            ':stream' => eval('return function () use ($twig) {\n                try {\n                    $twig->render([]);\n                } catch (\\Twig\\Error\\RuntimeError $e) {\n                    throw $e->getPrevious();\n                }\n            };'),\n        ]);\n        $ref = (int) $out;\n\n        $data = $cloner->cloneVar($out);\n        $dumper->dump($data, $out);\n        $out = stream_get_contents($out, -1, 0);\n\n        $this->assertStringMatchesFormat(\n            <<<EOTXT\n                stream resource {@{$ref}\n                  ⚠: Symfony\\Component\\VarDumper\\Exception\\ThrowingCasterException {#%d\n                    #message: \"Unexpected Exception thrown from a caster: Foobar\"\n                    trace: {\n                      %sTwig.php:2 {\n                        __TwigTemplate_VarDumperFixture_u75a09->doDisplay(array \\$context, array \\$blocks = []): array\n                        › foo bar\n                        ›   twig source\n                        › \n                      }\n                      %A%eTemplate.php:%d { …}\n                      %s%eTests%eDumper%eCliDumperTest.php:%d { …}\n                %A  }\n                  }\n                %Awrapper_type: \"PHP\"\n                  stream_type: \"MEMORY\"\n                  mode: \"%s+b\"\n                  unread_bytes: 0\n                  seekable: true\n                  uri: \"php://memory\"\n                %Aoptions: []\n                }\n\n                EOTXT,\n            $out\n        );\n    }\n\n    public function testRefsInProperties()\n    {\n        $var = (object) ['foo' => 'foo'];\n        $var->bar = &$var->foo;\n\n        $dumper = new CliDumper();\n        $dumper->setColors(false);\n        $cloner = new VarCloner();\n\n        $data = $cloner->cloneVar($var);\n        $out = $dumper->dump($data, true);\n\n        $this->assertStringMatchesFormat(\n            <<<EOTXT\n                {#%d\n                  +\"foo\": &1 \"foo\"\n                  +\"bar\": &1 \"foo\"\n                }\n\n                EOTXT,\n            $out\n        );\n    }\n\n    public function testIncompleteClass()\n    {\n        $unserializeCallbackHandler = ini_set('unserialize_callback_func', null);\n        $var = unserialize('O:8:\"Foo\\Buzz\":0:{}');\n        ini_set('unserialize_callback_func', $unserializeCallbackHandler);\n\n        $this->assertDumpMatchesFormat(\n            <<<EOTXT\n                __PHP_Incomplete_Class(Foo\\Buzz) {}\n                EOTXT,\n            $var\n        );\n    }\n\n    public static function provideDumpArrayWithColor()\n    {\n        yield [\n            ['foo' => 'bar'],\n            0,\n            <<<EOTXT\n                \\e[0;38;5;208m\\e[38;5;38marray:1\\e[0;38;5;208m [\\e[m\n                  \\e[0;38;5;208m\"\\e[38;5;113mfoo\\e[0;38;5;208m\" => \"\\e[1;38;5;113mbar\\e[0;38;5;208m\"\\e[m\n                \\e[0;38;5;208m]\\e[m\n\n                EOTXT,\n        ];\n\n        yield [[], AbstractDumper::DUMP_LIGHT_ARRAY, \"\\e[0;38;5;208m[]\\e[m\\n\"];\n\n        yield [\n            ['foo' => 'bar'],\n            AbstractDumper::DUMP_LIGHT_ARRAY,\n            <<<EOTXT\n                \\e[0;38;5;208m[\\e[m\n                  \\e[0;38;5;208m\"\\e[38;5;113mfoo\\e[0;38;5;208m\" => \"\\e[1;38;5;113mbar\\e[0;38;5;208m\"\\e[m\n                \\e[0;38;5;208m]\\e[m\n\n                EOTXT,\n        ];\n\n        yield [[], 0, \"\\e[0;38;5;208m[]\\e[m\\n\"];\n    }\n\n    #[DataProvider('provideDumpArrayWithColor')]\n    public function testDumpArrayWithColor($value, $flags, $expectedOut)\n    {\n        if ('\\\\' === \\DIRECTORY_SEPARATOR) {\n            $this->markTestSkipped('Windows console does not support coloration');\n        }\n\n        $out = '';\n        $dumper = new CliDumper(static function ($line, $depth) use (&$out) {\n            if ($depth >= 0) {\n                $out .= str_repeat('  ', $depth).$line.\"\\n\";\n            }\n        }, null, $flags);\n        $dumper->setColors(true);\n        $cloner = new VarCloner();\n        $dumper->dump($cloner->cloneVar($value));\n\n        $this->assertSame($expectedOut, $out);\n    }\n\n    public function testCollapse()\n    {\n        if ('\\\\' === \\DIRECTORY_SEPARATOR) {\n            $this->markTestSkipped('This test cannot be run on Windows.');\n        }\n\n        $stub = new Stub();\n        $stub->type = Stub::TYPE_OBJECT;\n        $stub->class = 'stdClass';\n        $stub->position = 1;\n\n        $data = new Data([\n            [\n                $stub,\n            ],\n            [\n                \"\\0~collapse=1\\0foo\" => 123,\n                \"\\0+\\0bar\" => [1 => 2],\n            ],\n            [\n                'bar' => 123,\n            ],\n        ]);\n\n        $dumper = new CliDumper();\n        $dump = $dumper->dump($data, true);\n\n        $this->assertSame(\n            <<<'EOTXT'\n                {\n                  foo: 123\n                  +\"bar\": array:1 [\n                    \"bar\" => 123\n                  ]\n                }\n\n                EOTXT,\n            $dump\n        );\n    }\n\n    public function testFileLinkFormat()\n    {\n        $data = new Data([\n            [\n                new ClassStub(self::class),\n            ],\n        ]);\n\n        $ide = $_ENV['SYMFONY_IDE'] ?? null;\n        $_ENV['SYMFONY_IDE'] = 'vscode';\n\n        try {\n            $dumper = new CliDumper();\n            $dumper->setColors(true);\n            $dump = $dumper->dump($data, true);\n\n            $this->assertStringMatchesFormat('%svscode:%sCliDumperTest%s', $dump);\n        } finally {\n            if (null === $ide) {\n                unset($_ENV['SYMFONY_IDE']);\n            } else {\n                $_ENV['SYMFONY_IDE'] = $ide;\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Tests/Dumper/ContextProvider/RequestContextProviderTest.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Dumper\\ContextProvider;\n\nuse PHPUnit\\Framework\\Attributes\\RequiresMethod;\nuse PHPUnit\\Framework\\TestCase;\nuse Symfony\\Component\\HttpFoundation\\Request;\nuse Symfony\\Component\\HttpFoundation\\RequestStack;\nuse Symfony\\Component\\VarDumper\\Cloner\\Data;\nuse Symfony\\Component\\VarDumper\\Dumper\\ContextProvider\\RequestContextProvider;\n\n#[RequiresMethod(RequestStack::class, '__construct')]\nclass RequestContextProviderTest extends TestCase\n{\n    public function testGetContextOnNullRequest()\n    {\n        $requestStack = new RequestStack();\n        $provider = new RequestContextProvider($requestStack);\n\n        $this->assertNull($provider->getContext());\n    }\n\n    public function testGetContextOnRequest()\n    {\n        $request = Request::create('https://example.org/', 'POST');\n        $request->attributes->set('_controller', 'MyControllerClass');\n\n        $requestStack = new RequestStack();\n        $requestStack->push($request);\n\n        $context = (new RequestContextProvider($requestStack))->getContext();\n        $this->assertSame('https://example.org/', $context['uri']);\n        $this->assertSame('POST', $context['method']);\n        $this->assertInstanceOf(Data::class, $context['controller']);\n        $this->assertSame('MyControllerClass', $context['controller']->getValue());\n        $this->assertSame('https://example.org/', $context['uri']);\n        $this->assertArrayHasKey('identifier', $context);\n    }\n}\n"
  },
  {
    "path": "Tests/Dumper/ContextualizedDumperTest.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Tests\\Dumper;\n\nuse PHPUnit\\Framework\\Attributes\\BackupGlobals;\nuse PHPUnit\\Framework\\TestCase;\nuse Symfony\\Component\\VarDumper\\Cloner\\VarCloner;\nuse Symfony\\Component\\VarDumper\\Dumper\\CliDumper;\nuse Symfony\\Component\\VarDumper\\Dumper\\ContextProvider\\SourceContextProvider;\nuse Symfony\\Component\\VarDumper\\Dumper\\ContextualizedDumper;\n\n/**\n * @author Kévin Thérage <therage.kevin@gmail.com>\n */\n#[BackupGlobals(true)]\nclass ContextualizedDumperTest extends TestCase\n{\n    public function testContextualizedCliDumper()\n    {\n        $_ENV['SYMFONY_IDE'] = $_SERVER['SYMFONY_IDE'] = '';\n        $wrappedDumper = new CliDumper('php://output');\n        $wrappedDumper->setColors(true);\n\n        $var = 'example';\n        $href = \\sprintf('file://%s#L%s', __FILE__, 40);\n        $dumper = new ContextualizedDumper($wrappedDumper, [new SourceContextProvider()]);\n        $cloner = new VarCloner();\n        $data = $cloner->cloneVar($var);\n\n        ob_start();\n        $dumper->dump($data);\n        $out = ob_get_clean();\n\n        $this->assertStringContainsString(\"\\e]8;;{$href}\\e\\\\^\\e]\", $out);\n        $this->assertStringContainsString(\"m{$var}\\e[\", $out);\n    }\n}\n"
  },
  {
    "path": "Tests/Dumper/FunctionsTest.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Tests\\Dumper;\n\nuse PHPUnit\\Framework\\TestCase;\nuse Symfony\\Component\\VarDumper\\Cloner\\VarCloner;\nuse Symfony\\Component\\VarDumper\\Dumper\\CliDumper;\nuse Symfony\\Component\\VarDumper\\VarDumper;\n\nclass FunctionsTest extends TestCase\n{\n    public function testDumpWithoutArg()\n    {\n        $this->setupVarDumper();\n\n        ob_start();\n        $return = dump();\n        ob_end_clean();\n\n        $this->assertNull($return);\n    }\n\n    public function testDumpReturnsFirstArg()\n    {\n        $this->setupVarDumper();\n\n        $var1 = 'a';\n\n        ob_start();\n        $return = dump($var1);\n        ob_end_clean();\n\n        $this->assertSame($var1, $return);\n    }\n\n    public function testDumpReturnsFirstNamedArgWithoutSectionName()\n    {\n        $this->setupVarDumper();\n\n        $var1 = 'a';\n\n        ob_start();\n        $return = dump(first: $var1);\n        ob_end_clean();\n\n        $this->assertSame($var1, $return);\n    }\n\n    public function testDumpReturnsAllArgsInArray()\n    {\n        $this->setupVarDumper();\n\n        $var1 = 'a';\n        $var2 = 'b';\n        $var3 = 'c';\n\n        ob_start();\n        $return = dump($var1, $var2, $var3);\n        ob_end_clean();\n\n        $this->assertSame([$var1, $var2, $var3], $return);\n    }\n\n    public function testDumpReturnsAllNamedArgsInArray()\n    {\n        $this->setupVarDumper();\n\n        $var1 = 'a';\n        $var2 = 'b';\n        $var3 = 'c';\n\n        ob_start();\n        $return = dump($var1, second: $var2, third: $var3);\n        ob_end_clean();\n\n        $this->assertSame([$var1, 'second' => $var2, 'third' => $var3], $return);\n    }\n\n    protected function setupVarDumper()\n    {\n        $cloner = new VarCloner();\n        $dumper = new CliDumper('php://output');\n        VarDumper::setHandler(static function ($var) use ($cloner, $dumper) {\n            $dumper->dump($cloner->cloneVar($var));\n        });\n    }\n}\n"
  },
  {
    "path": "Tests/Dumper/HtmlDumperTest.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Tests\\Dumper;\n\nuse PHPUnit\\Framework\\Attributes\\DataProvider;\nuse PHPUnit\\Framework\\TestCase;\nuse Symfony\\Component\\VarDumper\\Caster\\ImgStub;\nuse Symfony\\Component\\VarDumper\\Cloner\\VarCloner;\nuse Symfony\\Component\\VarDumper\\Dumper\\HtmlDumper;\nuse Symfony\\Component\\VarDumper\\Tests\\Fixtures\\VirtualProperty;\n\n/**\n * @author Nicolas Grekas <p@tchwork.com>\n */\nclass HtmlDumperTest extends TestCase\n{\n    public function testGet()\n    {\n        if (\\ini_get('xdebug.file_link_format') || get_cfg_var('xdebug.file_link_format')) {\n            $this->markTestSkipped('A custom file_link_format is defined.');\n        }\n\n        require __DIR__.'/../Fixtures/dumb-var.php';\n\n        $dumper = new HtmlDumper('php://output');\n        $dumper->setDumpHeader('<foo></foo>');\n        $dumper->setDumpBoundaries('<bar>', '</bar>');\n        $cloner = new VarCloner();\n        $cloner->addCasters([\n            ':stream' => static function ($res, $a) {\n                unset($a['uri'], $a['wrapper_data']);\n\n                return $a;\n            },\n        ]);\n        $data = $cloner->cloneVar($var);\n\n        ob_start();\n        $dumper->dump($data);\n        $out = ob_get_clean();\n        $out = preg_replace('/[ \\t]+$/m', '', $out);\n        $var['file'] = htmlspecialchars($var['file'], \\ENT_QUOTES, 'UTF-8');\n        $intMax = \\PHP_INT_MAX;\n        preg_match('/sf-dump-\\d+/', $out, $dumpId);\n        $dumpId = $dumpId[0];\n        $res = (int) $var['res'];\n\n        $this->assertStringMatchesFormat(\n            <<<EOTXT\n                <foo></foo><bar><span class=sf-dump-note>array:25</span> [<samp data-depth=1 class=sf-dump-expanded>\n                  \"<span class=sf-dump-key>number</span>\" => <span class=sf-dump-num>1</span>\n                  <span class=sf-dump-key>0</span> => <a class=sf-dump-ref href=#{$dumpId}-ref01 title=\"2 occurrences\">&amp;1</a> <span class=sf-dump-const>null</span>\n                  \"<span class=sf-dump-key>const</span>\" => <span class=sf-dump-num>1.1</span>\n                  <span class=sf-dump-key>1</span> => <span class=sf-dump-const>true</span>\n                  <span class=sf-dump-key>2</span> => <span class=sf-dump-const>false</span>\n                  <span class=sf-dump-key>3</span> => <span class=sf-dump-num>NAN</span>\n                  <span class=sf-dump-key>4</span> => <span class=sf-dump-num>INF</span>\n                  <span class=sf-dump-key>5</span> => <span class=sf-dump-num>-INF</span>\n                  <span class=sf-dump-key>6</span> => <span class=sf-dump-num>{$intMax}</span>\n                  \"<span class=sf-dump-key>str</span>\" => \"<span class=sf-dump-str title=\"5 characters\">d&%s;j&%s;<span class=\"sf-dump-default sf-dump-ns\">\\\\n</span></span>\"\n                  <span class=sf-dump-key>7</span> => b\"\"\"\n                    <span class=sf-dump-str title=\"11 binary or non-UTF-8 characters\">&#233;<span class=\"sf-dump-default\">\\\\x01</span>test<span class=\"sf-dump-default\">\\\\t</span><span class=\"sf-dump-default sf-dump-ns\">\\\\n</span></span>\n                    <span class=sf-dump-str title=\"11 binary or non-UTF-8 characters\">ing</span>\n                    \"\"\"\n                  \"<span class=sf-dump-key>bo<span class=sf-dump-default>\\\\u{FEFF}</span>m</span>\" => \"<span class=sf-dump-str title=\"5 characters\">te<span class=sf-dump-default>\\\\u{FEFF}</span>st</span>\"\n                  \"<span class=sf-dump-key>[]</span>\" => []\n                  \"<span class=sf-dump-key>res</span>\" => <span class=sf-dump-note>stream resource</span> <a class=sf-dump-ref>@{$res}</a><samp data-depth=2 class=sf-dump-compact>\n                %A  <span class=sf-dump-meta>wrapper_type</span>: \"<span class=sf-dump-str title=\"9 characters\">plainfile</span>\"\n                    <span class=sf-dump-meta>stream_type</span>: \"<span class=sf-dump-str title=\"5 characters\">STDIO</span>\"\n                    <span class=sf-dump-meta>mode</span>: \"<span class=sf-dump-str>r</span>\"\n                    <span class=sf-dump-meta>unread_bytes</span>: <span class=sf-dump-num>0</span>\n                    <span class=sf-dump-meta>seekable</span>: <span class=sf-dump-const>true</span>\n                %A  <span class=sf-dump-meta>options</span>: []\n                  </samp>}\n                  \"<span class=sf-dump-key>obj</span>\" => <span class=\"sf-dump-note sf-dump-ellipsization\" title=\"Symfony\\Component\\VarDumper\\Tests\\Fixture\\DumbFoo\n                \"><span class=\"sf-dump-ellipsis sf-dump-ellipsis-note\">Symfony\\Component\\VarDumper\\Tests\\Fixture</span><span class=\"sf-dump-ellipsis sf-dump-ellipsis-note\">\\</span><span class=\"sf-dump-ellipsis-tail\">DumbFoo</span></span> {<a class=sf-dump-ref href=#{$dumpId}-ref2%d title=\"2 occurrences\">#%d</a><samp data-depth=2 id={$dumpId}-ref2%d class=sf-dump-compact>\n                    +<span class=sf-dump-public title=\"Public property\">foo</span>: \"<span class=sf-dump-str title=\"3 characters\">foo</span>\"\n                    +\"<span class=sf-dump-public title=\"Runtime added dynamic property\">bar</span>\": \"<span class=sf-dump-str title=\"3 characters\">bar</span>\"\n                  </samp>}\n                  \"<span class=sf-dump-key>closure</span>\" => <span class=sf-dump-note>Closure(\\$a, ?PDO &amp;\\$b = null)</span> {<a class=sf-dump-ref>#%d</a><samp data-depth=2 class=sf-dump-compact>\n                    <span class=sf-dump-meta>class</span>: \"<span class=\"sf-dump-str sf-dump-ellipsization\" title=\"Symfony\\Component\\VarDumper\\Tests\\Dumper\\HtmlDumperTest\n                55 characters\"><span class=\"sf-dump-ellipsis sf-dump-ellipsis-class\">Symfony\\Component\\VarDumper\\Tests\\Dumper</span><span class=\"sf-dump-ellipsis sf-dump-ellipsis-class\">\\</span><span class=\"sf-dump-ellipsis-tail\">HtmlDumperTest</span></span>\"\n                    <span class=sf-dump-meta>this</span>: <span class=\"sf-dump-note sf-dump-ellipsization\" title=\"Symfony\\Component\\VarDumper\\Tests\\Dumper\\HtmlDumperTest\n                \"><span class=\"sf-dump-ellipsis sf-dump-ellipsis-note\">Symfony\\Component\\VarDumper\\Tests\\Dumper</span><span class=\"sf-dump-ellipsis sf-dump-ellipsis-note\">\\</span><span class=\"sf-dump-ellipsis-tail\">HtmlDumperTest</span></span> {<a class=sf-dump-ref>#%d</a> &%s;}\n                    <span class=sf-dump-meta>file</span>: \"<span class=\"sf-dump-str sf-dump-ellipsization\" title=\"{$var['file']}\n                %d characters\"><span class=\"sf-dump-ellipsis sf-dump-ellipsis-path\">%s%eVarDumper</span><span class=\"sf-dump-ellipsis sf-dump-ellipsis-path\">%e</span><span class=\"sf-dump-ellipsis-tail\">Tests%eFixtures%edumb-var.php</span></span>\"\n                    <span class=sf-dump-meta>line</span>: \"<span class=sf-dump-str title=\"%d characters\">{$var['line']} to {$var['line']}</span>\"\n                  </samp>}\n                  \"<span class=sf-dump-key>line</span>\" => <span class=sf-dump-num>{$var['line']}</span>\n                  \"<span class=sf-dump-key>nobj</span>\" => <span class=sf-dump-note>array:1</span> [<samp data-depth=2 class=sf-dump-compact>\n                    <span class=sf-dump-index>0</span> => <a class=sf-dump-ref href=#{$dumpId}-ref03 title=\"2 occurrences\">&amp;3</a> {<a class=sf-dump-ref href=#{$dumpId}-ref2%d title=\"3 occurrences\">#%d</a>}\n                  </samp>]\n                  \"<span class=sf-dump-key>recurs</span>\" => <a class=sf-dump-ref href=#{$dumpId}-ref04 title=\"2 occurrences\">&amp;4</a> <span class=sf-dump-note>array:1</span> [<samp data-depth=2 id={$dumpId}-ref04 class=sf-dump-compact>\n                    <span class=sf-dump-index>0</span> => <a class=sf-dump-ref href=#{$dumpId}-ref04 title=\"2 occurrences\">&amp;4</a> <span class=sf-dump-note>array:1</span> [<a class=sf-dump-ref href=#{$dumpId}-ref04 title=\"2 occurrences\">&amp;4</a>]\n                  </samp>]\n                  <span class=sf-dump-key>8</span> => <a class=sf-dump-ref href=#{$dumpId}-ref01 title=\"2 occurrences\">&amp;1</a> <span class=sf-dump-const>null</span>\n                  \"<span class=sf-dump-key>sobj</span>\" => <span class=\"sf-dump-note sf-dump-ellipsization\" title=\"Symfony\\Component\\VarDumper\\Tests\\Fixture\\DumbFoo\n                \"><span class=\"sf-dump-ellipsis sf-dump-ellipsis-note\">Symfony\\Component\\VarDumper\\Tests\\Fixture</span><span class=\"sf-dump-ellipsis sf-dump-ellipsis-note\">\\</span><span class=\"sf-dump-ellipsis-tail\">DumbFoo</span></span> {<a class=sf-dump-ref href=#{$dumpId}-ref2%d title=\"2 occurrences\">#%d</a>}\n                  \"<span class=sf-dump-key>snobj</span>\" => <a class=sf-dump-ref href=#{$dumpId}-ref03 title=\"2 occurrences\">&amp;3</a> {<a class=sf-dump-ref href=#{$dumpId}-ref2%d title=\"3 occurrences\">#%d</a>}\n                  \"<span class=sf-dump-key>snobj2</span>\" => {<a class=sf-dump-ref href=#{$dumpId}-ref2%d title=\"3 occurrences\">#%d</a>}\n                  \"<span class=sf-dump-key>file</span>\" => \"<span class=sf-dump-str title=\"%d characters\">{$var['file']}</span>\"\n                  b\"<span class=sf-dump-key>bin-key-&%s;</span>\" => \"\"\n                </samp>]\n                </bar>\n\n                EOTXT,\n\n            $out\n        );\n    }\n\n    public function testVirtualProperties()\n    {\n        $dumper = new HtmlDumper('php://output');\n        $dumper->setDumpHeader('<foo></foo>');\n        $dumper->setDumpBoundaries('<bar>', '</bar>');\n        $cloner = new VarCloner();\n\n        $data = $cloner->cloneVar(new VirtualProperty());\n        $out = $dumper->dump($data, true);\n\n        $this->assertStringMatchesFormat(<<<EODUMP\n            <foo></foo><bar><span class=sf-dump-note>Symfony\\Component\\VarDumper\\Tests\\Fixtures\\VirtualProperty</span> {<a class=sf-dump-ref>#%i</a><samp data-depth=1 class=sf-dump-expanded>\n              +<span class=sf-dump-public title=\"Public property\">firstName</span>: \"<span class=sf-dump-str title=\"4 characters\">John</span>\"\n              +<span class=sf-dump-public title=\"Public property\">lastName</span>: \"<span class=sf-dump-str title=\"3 characters\">Doe</span>\"\n              +<span class=sf-dump-virtual><span class=sf-dump-public title=\"Public property\">fullName</span></span>: <span class=sf-dump-virtual><span class=sf-dump-const title=\"Virtual property\">~ string</span></span>\n              -<span class=sf-dump-virtual><span class=sf-dump-private title=\"Private property defined in class:&#10;`Symfony\\Component\\VarDumper\\Tests\\Fixtures\\VirtualProperty`\">noType</span></span>: <span class=sf-dump-virtual><span class=sf-dump-const title=\"Virtual property\">~</span></span>\n            </samp>}\n            </bar>\n            EODUMP,\n            $out\n        );\n    }\n\n    public function testCharset()\n    {\n        $var = mb_convert_encoding('Словарь', 'CP1251', 'UTF-8');\n\n        $dumper = new HtmlDumper('php://output', 'CP1251');\n        $dumper->setDumpHeader('<foo></foo>');\n        $dumper->setDumpBoundaries('<bar>', '</bar>');\n        $cloner = new VarCloner();\n\n        $data = $cloner->cloneVar($var);\n        $out = $dumper->dump($data, true);\n\n        $this->assertStringMatchesFormat(\n            <<<'EOTXT'\n                <foo></foo><bar>b\"<span class=sf-dump-str title=\"7 binary or non-UTF-8 characters\">&#1057;&#1083;&#1086;&#1074;&#1072;&#1088;&#1100;</span>\"\n                </bar>\n\n                EOTXT,\n            $out\n        );\n    }\n\n    public function testAppend()\n    {\n        $out = fopen('php://memory', 'r+');\n\n        $dumper = new HtmlDumper();\n        $dumper->setDumpHeader('<foo></foo>');\n        $dumper->setDumpBoundaries('<bar>', '</bar>');\n        $cloner = new VarCloner();\n\n        $dumper->dump($cloner->cloneVar(123), $out);\n        $dumper->dump($cloner->cloneVar(456), $out);\n\n        $out = stream_get_contents($out, -1, 0);\n\n        $this->assertSame(<<<'EOTXT'\n            <foo></foo><bar><span class=sf-dump-num>123</span>\n            </bar>\n            <bar><span class=sf-dump-num>456</span>\n            </bar>\n\n            EOTXT,\n            $out\n        );\n    }\n\n    #[DataProvider('varToDumpProvider')]\n    public function testDumpString($var, $needle)\n    {\n        $dumper = new HtmlDumper();\n        $cloner = new VarCloner();\n\n        ob_start();\n        $dumper->dump($cloner->cloneVar($var));\n        $out = ob_get_clean();\n\n        $this->assertStringContainsString($needle, $out);\n    }\n\n    public static function varToDumpProvider()\n    {\n        return [\n            [['dummy' => new ImgStub('dummy', 'img/png', '100em')], '<img src=\"data:img/png;base64,ZHVtbXk=\" />'],\n            ['foo', '<span class=sf-dump-str title=\"3 characters\">foo</span>'],\n        ];\n    }\n}\n"
  },
  {
    "path": "Tests/Dumper/ServerDumperTest.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Tests\\Dumper;\n\nuse PHPUnit\\Framework\\TestCase;\nuse Symfony\\Component\\Process\\PhpProcess;\nuse Symfony\\Component\\Process\\Process;\nuse Symfony\\Component\\VarDumper\\Cloner\\VarCloner;\nuse Symfony\\Component\\VarDumper\\Dumper\\ContextProvider\\ContextProviderInterface;\nuse Symfony\\Component\\VarDumper\\Dumper\\DataDumperInterface;\nuse Symfony\\Component\\VarDumper\\Dumper\\ServerDumper;\n\nclass ServerDumperTest extends TestCase\n{\n    private const VAR_DUMPER_SERVER = 'tcp://127.0.0.1:9913';\n\n    public function testDumpForwardsToWrappedDumperWhenServerIsUnavailable()\n    {\n        $wrappedDumper = $this->createMock(DataDumperInterface::class);\n\n        $dumper = new ServerDumper(self::VAR_DUMPER_SERVER, $wrappedDumper);\n\n        $cloner = new VarCloner();\n        $data = $cloner->cloneVar('foo');\n\n        $wrappedDumper->expects($this->once())->method('dump')->with($data);\n\n        $dumper->dump($data);\n    }\n\n    public function testDump()\n    {\n        if ('\\\\' === \\DIRECTORY_SEPARATOR) {\n            $this->markTestSkipped('Skip transient test on Windows');\n        }\n\n        $wrappedDumper = $this->createMock(DataDumperInterface::class);\n        $wrappedDumper->expects($this->never())->method('dump'); // test wrapped dumper is not used\n\n        $cloner = new VarCloner();\n        $data = $cloner->cloneVar('foo');\n        $dumper = new ServerDumper(self::VAR_DUMPER_SERVER, $wrappedDumper, [\n            'foo_provider' => new class implements ContextProviderInterface {\n                public function getContext(): ?array\n                {\n                    return ['foo'];\n                }\n            },\n        ]);\n\n        $dumped = null;\n        $process = $this->getServerProcess();\n        $process->start(function ($type, $buffer) use ($process, &$dumped, $dumper, $data) {\n            if (Process::ERR === $type) {\n                $process->stop();\n                $this->fail();\n            } elseif (\"READY\\n\" === $buffer) {\n                $dumper->dump($data);\n            } else {\n                $dumped .= $buffer;\n            }\n        });\n\n        $process->wait();\n\n        $this->assertTrue($process->isSuccessful());\n        $this->assertStringMatchesFormat(<<<'DUMP'\n            (3) \"foo\"\n            [\n              \"timestamp\" => %d.%d\n              \"foo_provider\" => [\n                (3) \"foo\"\n              ]\n            ]\n            %d\n            DUMP,\n            $dumped\n        );\n    }\n\n    private function getServerProcess(): Process\n    {\n        $process = new PhpProcess(file_get_contents(__DIR__.'/../Fixtures/dump_server.php'), null, [\n            'COMPONENT_ROOT' => __DIR__.'/../../',\n            'VAR_DUMPER_SERVER' => self::VAR_DUMPER_SERVER,\n        ]);\n\n        return $process->setTimeout('\\\\' === \\DIRECTORY_SEPARATOR ? 19 : 9);\n    }\n}\n"
  },
  {
    "path": "Tests/Dumper/functions/dd_with_accept_header_json_array.phpt",
    "content": "--TEST--\nTest dd() with \"Accept: application/json\" uses CliDumper with php://output\n--FILE--\n<?php\nputenv('NO_COLOR=1');\n\n$vendor = __DIR__;\nwhile (!file_exists($vendor.'/vendor')) {\n    $vendor = \\dirname($vendor);\n}\nrequire $vendor.'/vendor/autoload.php';\n\n$_SERVER['HTTP_ACCEPT'] = 'application/json';\ndd(['foo1', 'foo2']);\n--EXPECTF--\narray:2 [\n  0 => \"foo1\"\n  1 => \"foo2\"\n]\n"
  },
  {
    "path": "Tests/Dumper/functions/dd_with_multiple_args.phpt",
    "content": "--TEST--\nTest dd() with multiple args shows line number\n--FILE--\n<?php\nputenv('NO_COLOR=1');\n\n$vendor = __DIR__;\nwhile (!file_exists($vendor.'/vendor')) {\n    $vendor = \\dirname($vendor);\n}\nrequire $vendor.'/vendor/autoload.php';\n\ndd(null, 1, 'foo');\n\n--EXPECT--\n1 null\n2 1\n3 \"foo\"\n"
  },
  {
    "path": "Tests/Dumper/functions/dd_with_named_args.phpt",
    "content": "--TEST--\nTest dd() with named args show label\n--FILE--\n<?php\nputenv('NO_COLOR=1');\n\n$vendor = __DIR__;\nwhile (!file_exists($vendor.'/vendor')) {\n    $vendor = \\dirname($vendor);\n}\nrequire $vendor.'/vendor/autoload.php';\n\ndd(label2: \"dd() with label\");\n\n--EXPECT--\nlabel2 \"dd() with label\"\n"
  },
  {
    "path": "Tests/Dumper/functions/dd_with_null.phpt",
    "content": "--TEST--\nTest dd() with null doesn't show line number\n--FILE--\n<?php\nputenv('NO_COLOR=1');\n\n$vendor = __DIR__;\nwhile (!file_exists($vendor.'/vendor')) {\n    $vendor = \\dirname($vendor);\n}\nrequire $vendor.'/vendor/autoload.php';\n\ndd(null);\n\n--EXPECT--\nnull\n"
  },
  {
    "path": "Tests/Dumper/functions/dd_with_single_arg.phpt",
    "content": "--TEST--\nTest dd() with one arg doesn't show line number\n--FILE--\n<?php\nputenv('NO_COLOR=1');\n\n$vendor = __DIR__;\nwhile (!file_exists($vendor.'/vendor')) {\n    $vendor = \\dirname($vendor);\n}\nrequire $vendor.'/vendor/autoload.php';\n\ndd('foo');\n\n--EXPECT--\n\"foo\"\n"
  },
  {
    "path": "Tests/Dumper/functions/dump_data_collector_with_spl_array.phpt",
    "content": "--TEST--\nTest integration with Symfony's DumpDataCollector\n--FILE--\n<?php\nputenv('NO_COLOR=1');\n\n$vendor = __DIR__;\nwhile (!file_exists($vendor.'/vendor')) {\n    $vendor = dirname($vendor);\n}\nrequire $vendor.'/vendor/autoload.php';\n\nuse Symfony\\Component\\HttpKernel\\DataCollector\\DumpDataCollector;\nuse Symfony\\Component\\VarDumper\\Cloner\\VarCloner;\nuse Symfony\\Component\\VarDumper\\VarDumper;\n\nVarDumper::setHandler(function ($var, ?string $label = null) {\n    $dumper = new DumpDataCollector();\n    $cloner = new VarCloner();\n    $handler = function ($var, ?string $label = null) use ($dumper, $cloner) {\n        $var = $cloner->cloneVar($var);\n        if (null !== $label) {\n            $var = $var->withContext(['label' => $label]);\n        }\n\n        $dumper->dump($var);\n    };\n    VarDumper::setHandler($handler);\n    $handler($var, $label);\n});\n\n$arrayObject = new \\ArrayObject();\ndump($arrayObject);\n$arrayObject['X'] = 'A';\n$arrayObject['Y'] = new \\ArrayObject(['type' => 'object']);\n$arrayObject['Y']['Z'] = 'B';\n\n$arrayIterator = new \\ArrayIterator();\ndump($arrayIterator);\n$arrayIterator['X'] = 'A';\n$arrayIterator['Y'] = new \\ArrayIterator(['type' => 'object']);\n$arrayIterator['Y']['Z'] = 'B';\n\n$recursiveArrayIterator = new \\RecursiveArrayIterator();\ndump($recursiveArrayIterator);\n$recursiveArrayIterator['X'] = 'A';\n$recursiveArrayIterator['Y'] = new \\RecursiveArrayIterator(['type' => 'object']);\n$recursiveArrayIterator['Y']['Z'] = 'B';\n\n--EXPECTF--\n%s on line %d:\nArrayObject {#%d\n  storage: []\n  flag::STD_PROP_LIST: false\n  flag::ARRAY_AS_PROPS: false\n  iteratorClass: \"ArrayIterator\"\n}\n%s on line %d:\nArrayIterator {#%d\n  storage: []\n  flag::STD_PROP_LIST: false\n  flag::ARRAY_AS_PROPS: false\n}\n%s on line %d:\nRecursiveArrayIterator {#%d\n  storage: []\n  flag::STD_PROP_LIST: false\n  flag::ARRAY_AS_PROPS: false\n}\n"
  },
  {
    "path": "Tests/Dumper/functions/dump_with_accept_header_html.phpt",
    "content": "--TEST--\nTest dump() with \"Accept: text/html\" uses HTML dumper\n--FILE--\n<?php\nputenv('NO_COLOR=1');\n\n$vendor = __DIR__;\nwhile (!file_exists($vendor.'/vendor')) {\n    $vendor = \\dirname($vendor);\n}\nrequire $vendor.'/vendor/autoload.php';\n\n$_SERVER['HTTP_ACCEPT'] = 'text/html';\ndump('Test with HTML');\n--EXPECTF--\n%a>Test with HTML</%a\n"
  },
  {
    "path": "Tests/Dumper/functions/dump_with_accept_header_json_array.phpt",
    "content": "--TEST--\nTest dump() with \"Accept: application/json\" uses CliDumper with php://output\n--FILE--\n<?php\nputenv('NO_COLOR=1');\n\n$vendor = __DIR__;\nwhile (!file_exists($vendor.'/vendor')) {\n    $vendor = \\dirname($vendor);\n}\nrequire $vendor.'/vendor/autoload.php';\n\n$_SERVER['HTTP_ACCEPT'] = 'application/json';\ndump(['foo1', 'foo2']);\n--EXPECTF--\narray:2 [\n  0 => \"foo1\"\n  1 => \"foo2\"\n]\n\n"
  },
  {
    "path": "Tests/Dumper/functions/dump_with_accept_header_json_multiple_args.phpt",
    "content": "--TEST--\nTest dump() with \"Accept: application/json\" uses CliDumper with php://output\n--FILE--\n<?php\nputenv('NO_COLOR=1');\n\n$vendor = __DIR__;\nwhile (!file_exists($vendor.'/vendor')) {\n    $vendor = \\dirname($vendor);\n}\nrequire $vendor.'/vendor/autoload.php';\n\n$_SERVER['HTTP_ACCEPT'] = 'application/json';\ndump(1, 'foo', ['foo1', 'foo2']);\n--EXPECTF--\n1 1\n2 \"foo\"\n3 array:2 [\n  0 => \"foo1\"\n  1 => \"foo2\"\n]\n"
  },
  {
    "path": "Tests/Dumper/functions/dump_with_accept_header_json_string.phpt",
    "content": "--TEST--\nTest dump() with \"Accept: application/json\" uses CliDumper with php://output\n--FILE--\n<?php\nputenv('NO_COLOR=1');\n\n$vendor = __DIR__;\nwhile (!file_exists($vendor.'/vendor')) {\n    $vendor = \\dirname($vendor);\n}\nrequire $vendor.'/vendor/autoload.php';\n\n$_SERVER['HTTP_ACCEPT'] = 'application/json';\ndump('Test with string');\n--EXPECTF--\n\"Test with string\"\n"
  },
  {
    "path": "Tests/Dumper/functions/dump_with_accept_header_wildcard.phpt",
    "content": "--TEST--\nTest dump() with \"Accept: */*\" uses HTML dumper\n--FILE--\n<?php\nputenv('NO_COLOR=1');\n\n$vendor = __DIR__;\nwhile (!file_exists($vendor.'/vendor')) {\n    $vendor = \\dirname($vendor);\n}\nrequire $vendor.'/vendor/autoload.php';\n\n$_SERVER['HTTP_ACCEPT'] = '*/*';\ndump('Test with wildcard');\n--EXPECTF--\n%a>Test with wildcard</%a\n"
  },
  {
    "path": "Tests/Dumper/functions/dump_with_multiple_args.phpt",
    "content": "--TEST--\nTest dump() with multiple args shows line number\n--FILE--\n<?php\nputenv('NO_COLOR=1');\n\n$vendor = __DIR__;\nwhile (!file_exists($vendor.'/vendor')) {\n    $vendor = \\dirname($vendor);\n}\nrequire $vendor.'/vendor/autoload.php';\n\ndump(null, 1, 'foo');\n\n--EXPECT--\n1 null\n2 1\n3 \"foo\"\n"
  },
  {
    "path": "Tests/Dumper/functions/dump_with_named_args.phpt",
    "content": "--TEST--\nTest dd() with named args show label\n--FILE--\n<?php\nputenv('NO_COLOR=1');\n\n$vendor = __DIR__;\nwhile (!file_exists($vendor.'/vendor')) {\n    $vendor = \\dirname($vendor);\n}\nrequire $vendor.'/vendor/autoload.php';\n\ndump(\"first dump\", label1: \"dump() with label\");\n\n--EXPECT--\n1 \"first dump\"\nlabel1 \"dump() with label\"\n"
  },
  {
    "path": "Tests/Dumper/functions/dump_with_null.phpt",
    "content": "--TEST--\nTest dump() with null doesn't show line number\n--FILE--\n<?php\nputenv('NO_COLOR=1');\n\n$vendor = __DIR__;\nwhile (!file_exists($vendor.'/vendor')) {\n    $vendor = \\dirname($vendor);\n}\nrequire $vendor.'/vendor/autoload.php';\n\ndump(null);\n\n--EXPECT--\nnull\n"
  },
  {
    "path": "Tests/Dumper/functions/dump_with_single_arg.phpt",
    "content": "--TEST--\nTest dump() with one arg doesn't show line number\n--FILE--\n<?php\nputenv('NO_COLOR=1');\n\n$vendor = __DIR__;\nwhile (!file_exists($vendor.'/vendor')) {\n    $vendor = \\dirname($vendor);\n}\nrequire $vendor.'/vendor/autoload.php';\n\ndump('foo');\n\n--EXPECT--\n\"foo\"\n"
  },
  {
    "path": "Tests/Dumper/functions/dump_without_args.phpt",
    "content": "--TEST--\nTest dd() without args displays debug hint\n--FILE--\n<?php\nputenv('NO_COLOR=1');\n\n$vendor = __DIR__;\nwhile (!file_exists($vendor.'/vendor')) {\n    $vendor = \\dirname($vendor);\n}\nrequire $vendor.'/vendor/autoload.php';\n\ndump();\n\n--EXPECT--\n🐛\n"
  },
  {
    "path": "Tests/Fixtures/BackedEnumFixture.php",
    "content": "<?php\n\nnamespace Symfony\\Component\\VarDumper\\Tests\\Fixtures;\n\nenum BackedEnumFixture: string {\n    case Hearts = 'H';\n    case Diamonds = 'D';\n    case Clubs = 'C';\n    case Spades = 'S';\n}\n"
  },
  {
    "path": "Tests/Fixtures/DateTimeChild.php",
    "content": "<?php\n\nnamespace Symfony\\Component\\VarDumper\\Tests\\Fixtures;\n\nclass DateTimeChild extends \\DateTimeImmutable\n{\n    private $addedProperty = 'foo';\n}\n"
  },
  {
    "path": "Tests/Fixtures/ExtendsReflectionTypeFixture.php",
    "content": "<?php\n\nnamespace Symfony\\Component\\VarDumper\\Tests\\Fixtures;\n\nclass ExtendsReflectionTypeFixture extends \\ReflectionType\n{\n    public function allowsNull(): bool\n    {\n        return false;\n    }\n\n    public function isBuiltin(): bool\n    {\n        return false;\n    }\n\n    public function __toString(): string\n    {\n        return 'fake';\n    }\n}\n"
  },
  {
    "path": "Tests/Fixtures/FooInterface.php",
    "content": "<?php\n\nnamespace Symfony\\Component\\VarDumper\\Tests\\Fixtures;\n\ninterface FooInterface\n{\n    /**\n     * Hello.\n     */\n    public function foo(?\\stdClass $a, ?\\stdClass $b = null);\n}\n"
  },
  {
    "path": "Tests/Fixtures/GeneratorDemo.php",
    "content": "<?php\n\nnamespace Symfony\\Component\\VarDumper\\Tests\\Fixtures;\n\nclass GeneratorDemo\n{\n    public static function foo()\n    {\n        yield 1;\n    }\n\n    public function baz()\n    {\n        yield from bar();\n    }\n}\n\nfunction bar()\n{\n    yield from GeneratorDemo::foo();\n}\n"
  },
  {
    "path": "Tests/Fixtures/LotsOfAttributes.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Tests\\Fixtures;\n\n#[MyAttribute]\nfinal class LotsOfAttributes\n{\n    #[RepeatableAttribute('one'), RepeatableAttribute('two')]\n    public const SOME_CONSTANT = 'some value';\n\n    #[MyAttribute('one', extra: 'hello')]\n    private string $someProperty;\n\n    #[MyAttribute('two')]\n    public function someMethod(\n        #[MyAttribute('three')] string $someParameter,\n    ): void {\n    }\n}\n"
  },
  {
    "path": "Tests/Fixtures/MyAttribute.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Tests\\Fixtures;\n\n#[\\Attribute]\nfinal class MyAttribute\n{\n    public function __construct(\n        private string $foo = 'default',\n        private ?string $extra = null,\n    ) {\n    }\n\n    public function getFoo(): string\n    {\n        return $this->foo;\n    }\n\n    public function getExtra(): ?string\n    {\n        return $this->extra;\n    }\n}\n"
  },
  {
    "path": "Tests/Fixtures/NotLoadableClass.php",
    "content": "<?php\n\nnamespace Symfony\\Component\\VarDumper\\Tests\\Fixtures;\n\nclass NotLoadableClass extends NotLoadableClass\n{\n}\n"
  },
  {
    "path": "Tests/Fixtures/Php74.php",
    "content": "<?php\n\nnamespace Symfony\\Component\\VarDumper\\Tests\\Fixtures;\n\nclass Php74\n{\n    public $p1 = 123;\n    public \\stdClass $p2;\n    public \\stdClass $p3;\n\n    public function __construct()\n    {\n        $this->p2 = new \\stdClass();\n        $this->p3 = &$this->p2;\n    }\n}\n"
  },
  {
    "path": "Tests/Fixtures/Php81Enums.php",
    "content": "<?php\n\nnamespace Symfony\\Component\\VarDumper\\Tests\\Fixtures;\n\nclass Php81Enums\n{\n    public UnitEnumFixture $e1;\n    public BackedEnumFixture $e2;\n\n    public function __construct()\n    {\n        $this->e1 = UnitEnumFixture::Hearts;\n        $this->e2 = BackedEnumFixture::Diamonds;\n    }\n}\n"
  },
  {
    "path": "Tests/Fixtures/Php82NullStandaloneReturnType.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Tests\\Fixtures;\n\nclass Php82NullStandaloneReturnType\n{\n    public function foo(null $bar): null\n    {\n        return null;\n    }\n}\n"
  },
  {
    "path": "Tests/Fixtures/ReflectionIntersectionTypeFixture.php",
    "content": "<?php\n\nnamespace Symfony\\Component\\VarDumper\\Tests\\Fixtures;\n\nclass ReflectionIntersectionTypeFixture\n{\n    public \\Traversable&\\Countable $a;\n}\n"
  },
  {
    "path": "Tests/Fixtures/ReflectionNamedTypeFixture.php",
    "content": "<?php\n\nnamespace Symfony\\Component\\VarDumper\\Tests\\Fixtures;\n\nclass ReflectionNamedTypeFixture\n{\n    public int $a;\n}\n"
  },
  {
    "path": "Tests/Fixtures/ReflectionUnionTypeFixture.php",
    "content": "<?php\n\nnamespace Symfony\\Component\\VarDumper\\Tests\\Fixtures;\n\nclass ReflectionUnionTypeFixture\n{\n    public int|string $a;\n}\n"
  },
  {
    "path": "Tests/Fixtures/ReflectionUnionTypeWithIntersectionFixture.php",
    "content": "<?php\n\nnamespace Symfony\\Component\\VarDumper\\Tests\\Fixtures;\n\nclass ReflectionUnionTypeWithIntersectionFixture\n{\n    public (\\Traversable&\\Countable)|null $a;\n}\n"
  },
  {
    "path": "Tests/Fixtures/Twig.php",
    "content": "<?php\n\nabstract class AbstractTwigTemplate extends Twig\\Template\n{\n    private function createError()\n    {\n        return new \\RuntimeException('Manually triggered error.');\n    }\n\n    public function provideError()\n    {\n        return $this->createError();\n    }\n}\n\n/* foo.twig */\nclass __TwigTemplate_VarDumperFixture_u75a09 extends AbstractTwigTemplate\n{\n    private $path;\n\n    public function __construct(?Twig\\Environment $env = null, $path = null)\n    {\n        if (null !== $env) {\n            parent::__construct($env);\n        }\n        $this->parent = false;\n        $this->blocks = [];\n        $this->path = $path;\n    }\n\n    protected function doDisplay(array $context, array $blocks = []): array\n    {\n        // line 2\n        throw new \\Exception('Foobar');\n    }\n\n    public function getTemplateName(): string\n    {\n        return 'foo.twig';\n    }\n\n    public function getDebugInfo(): array\n    {\n        return [33 => 1, 34 => 2];\n    }\n\n    public function getSourceContext(): Twig\\Source\n    {\n        return new Twig\\Source(\"   foo bar\\n     twig source\\n\\n\", 'foo.twig', $this->path ?: __FILE__);\n    }\n}\n"
  },
  {
    "path": "Tests/Fixtures/UnitEnumFixture.php",
    "content": "<?php\n\nnamespace Symfony\\Component\\VarDumper\\Tests\\Fixtures;\n\nenum UnitEnumFixture {\n    case Hearts;\n    case Diamonds;\n    case Clubs;\n    case Spades;\n}\n"
  },
  {
    "path": "Tests/Fixtures/VirtualProperty.php",
    "content": "<?php\n\nnamespace Symfony\\Component\\VarDumper\\Tests\\Fixtures;\n\nclass VirtualProperty\n{\n    public string $firstName = 'John';\n    public string $lastName = 'Doe';\n\n    public string $fullName {\n        get {\n            return $this->firstName.' '.$this->lastName;\n        }\n    }\n\n    private $noType {\n        get {\n            return null;\n        }\n    }\n}\n"
  },
  {
    "path": "Tests/Fixtures/dumb-var.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Tests\\Fixture;\n\nif (!class_exists(\\Symfony\\Component\\VarDumper\\Tests\\Fixture\\DumbFoo::class)) {\n    #[\\AllowDynamicProperties]\n    class DumbFoo\n    {\n        public $foo = 'foo';\n    }\n}\n\n$foo = new DumbFoo();\n$foo->bar = 'bar';\n\n$g = fopen(__FILE__, 'r');\n\n$var = [\n    'number' => 1, null,\n    'const' => 1.1, true, false, \\NAN, \\INF, -\\INF, \\PHP_INT_MAX,\n    'str' => \"déjà\\n\", \"\\xE9\\x01test\\t\\ning\", \"bo\\u{feff}m\" => \"te\\u{feff}st\",\n    '[]' => [],\n    'res' => $g,\n    'obj' => $foo,\n    'closure' => function ($a, ?\\PDO &$b = null) {},\n    'line' => __LINE__ - 1,\n    'nobj' => [(object) []],\n];\n\n$r = [];\n$r[] = &$r;\n\n$var['recurs'] = &$r;\n$var[] = &$var[0];\n$var['sobj'] = $var['obj'];\n$var['snobj'] = &$var['nobj'][0];\n$var['snobj2'] = $var['nobj'][0];\n$var['file'] = __FILE__;\n$var[\"bin-key-\\xE9\"] = '';\n\nunset($g, $r);\n"
  },
  {
    "path": "Tests/Fixtures/dump_server.php",
    "content": "<?php\n\nuse Symfony\\Component\\VarDumper\\Cloner\\Data;\nuse Symfony\\Component\\VarDumper\\Cloner\\VarCloner;\nuse Symfony\\Component\\VarDumper\\Dumper\\CliDumper;\nuse Symfony\\Component\\VarDumper\\Server\\DumpServer;\nuse Symfony\\Component\\VarDumper\\VarDumper;\n\n$componentRoot = $_SERVER['COMPONENT_ROOT'];\n\nif (!is_file($file = $componentRoot.'/vendor/autoload.php')) {\n    $file = $componentRoot.'/../../../../vendor/autoload.php';\n}\n\nrequire $file;\n\n$cloner = new VarCloner();\n$cloner->setMaxItems(-1);\n\n$dumper = new CliDumper(null, null, CliDumper::DUMP_LIGHT_ARRAY | CliDumper::DUMP_STRING_LENGTH);\n$dumper->setColors(false);\n\nVarDumper::setHandler(function ($var) use ($cloner, $dumper) {\n    $data = $cloner->cloneVar($var)->withRefHandles(false);\n    $dumper->dump($data);\n});\n\n$server = new DumpServer(getenv('VAR_DUMPER_SERVER'));\n\n$server->start();\n\necho \"READY\\n\";\n\n$server->listen(function (Data $data, array $context, $clientId) {\n    dump((string) $data, $context, $clientId);\n\n    exit(0);\n});\n"
  },
  {
    "path": "Tests/Fixtures/xml_reader.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<foo>\n    <bar></bar>\n    <bar />\n    <bar>With text</bar>\n    <bar foo=\"bar\" baz=\"fubar\"></bar>\n    <bar xmlns:baz=\"http://symfony.com\">\n        <baz:baz></baz:baz>\n    </bar>\n</foo>\n"
  },
  {
    "path": "Tests/Server/ConnectionTest.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Tests\\Server;\n\nuse PHPUnit\\Framework\\TestCase;\nuse Symfony\\Component\\Process\\PhpProcess;\nuse Symfony\\Component\\Process\\Process;\nuse Symfony\\Component\\VarDumper\\Cloner\\VarCloner;\nuse Symfony\\Component\\VarDumper\\Dumper\\ContextProvider\\ContextProviderInterface;\nuse Symfony\\Component\\VarDumper\\Server\\Connection;\n\nclass ConnectionTest extends TestCase\n{\n    private const VAR_DUMPER_SERVER = 'tcp://127.0.0.1:9913';\n\n    public function testDump()\n    {\n        if ('\\\\' === \\DIRECTORY_SEPARATOR) {\n            $this->markTestSkipped('Skip transient test on Windows');\n        }\n\n        $cloner = new VarCloner();\n        $data = $cloner->cloneVar('foo');\n        $connection = new Connection(self::VAR_DUMPER_SERVER, [\n            'foo_provider' => new class implements ContextProviderInterface {\n                public function getContext(): ?array\n                {\n                    return ['foo'];\n                }\n            },\n        ]);\n\n        $dumped = null;\n        $process = $this->getServerProcess();\n        $process->start(function ($type, $buffer) use ($process, &$dumped, $connection, $data) {\n            if (Process::ERR === $type) {\n                $process->stop();\n                $this->fail();\n            } elseif (\"READY\\n\" === $buffer) {\n                $connection->write($data);\n            } else {\n                $dumped .= $buffer;\n            }\n        });\n\n        $process->wait();\n\n        $this->assertTrue($process->isSuccessful());\n        $this->assertStringMatchesFormat(<<<'DUMP'\n            (3) \"foo\"\n            [\n              \"timestamp\" => %d.%d\n              \"foo_provider\" => [\n                (3) \"foo\"\n              ]\n            ]\n            %d\n\n            DUMP,\n            $dumped\n        );\n    }\n\n    public function testNoServer()\n    {\n        $cloner = new VarCloner();\n        $data = $cloner->cloneVar('foo');\n        $connection = new Connection(self::VAR_DUMPER_SERVER);\n        $start = microtime(true);\n        $this->assertFalse($connection->write($data));\n        $this->assertLessThan(4, microtime(true) - $start);\n    }\n\n    private function getServerProcess(): Process\n    {\n        $process = new PhpProcess(file_get_contents(__DIR__.'/../Fixtures/dump_server.php'), null, [\n            'COMPONENT_ROOT' => __DIR__.'/../../',\n            'VAR_DUMPER_SERVER' => self::VAR_DUMPER_SERVER,\n        ]);\n\n        return $process->setTimeout(9);\n    }\n}\n"
  },
  {
    "path": "Tests/Test/VarDumperTestTraitTest.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Tests\\Test;\n\nuse PHPUnit\\Framework\\TestCase;\nuse Symfony\\Component\\VarDumper\\Cloner\\Stub;\nuse Symfony\\Component\\VarDumper\\Dumper\\CliDumper;\nuse Symfony\\Component\\VarDumper\\Test\\VarDumperTestTrait;\n\nclass VarDumperTestTraitTest extends TestCase\n{\n    use VarDumperTestTrait;\n\n    public function testItComparesLargeData()\n    {\n        $howMany = 700;\n        $data = array_fill_keys(range(0, $howMany), ['a', 'b', 'c', 'd']);\n\n        $expected = \\sprintf(\"array:%d [\\n\", $howMany + 1);\n        for ($i = 0; $i <= $howMany; ++$i) {\n            $expected .= <<<EODUMP\n                  $i => array:4 [\n                    0 => \"a\"\n                    1 => \"b\"\n                    2 => \"c\"\n                    3 => \"d\"\n                  ]\\n\n                EODUMP;\n        }\n        $expected .= \"]\\n\";\n\n        $this->assertDumpEquals($expected, $data);\n    }\n\n    public function testAllowsNonScalarExpectation()\n    {\n        $this->assertDumpEquals(new \\ArrayObject(['bim' => 'bam']), new \\ArrayObject(['bim' => 'bam']));\n    }\n\n    public function testItCanBeConfigured()\n    {\n        $this->setUpVarDumper($casters = [\n            \\DateTimeInterface::class => static function (\\DateTimeInterface $date, array $a, Stub $stub): array {\n                $stub->class = 'DateTimeImmutable';\n\n                return ['date' => $date->format('d/m/Y')];\n            },\n        ], CliDumper::DUMP_LIGHT_ARRAY | CliDumper::DUMP_COMMA_SEPARATOR);\n\n        $this->assertSame(CliDumper::DUMP_LIGHT_ARRAY | CliDumper::DUMP_COMMA_SEPARATOR, $this->varDumperConfig['flags']);\n        $this->assertSame($casters, $this->varDumperConfig['casters']);\n\n        $this->assertDumpEquals(<<<DUMP\n            [\n              1,\n              2,\n              DateTimeImmutable {\n                +date: \"09/07/2019\"\n              }\n            ]\n            DUMP,\n            [1, 2, new \\DateTimeImmutable('2019-07-09T0:00:00+00:00')]\n        );\n\n        $this->tearDownVarDumper();\n\n        $this->assertNull($this->varDumperConfig['flags']);\n        $this->assertSame([], $this->varDumperConfig['casters']);\n    }\n}\n"
  },
  {
    "path": "VarDumper.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper;\n\nuse Symfony\\Component\\ErrorHandler\\ErrorRenderer\\FileLinkFormatter;\nuse Symfony\\Component\\HttpFoundation\\Request;\nuse Symfony\\Component\\HttpFoundation\\RequestStack;\nuse Symfony\\Component\\VarDumper\\Caster\\ReflectionCaster;\nuse Symfony\\Component\\VarDumper\\Cloner\\VarCloner;\nuse Symfony\\Component\\VarDumper\\Dumper\\CliDumper;\nuse Symfony\\Component\\VarDumper\\Dumper\\ContextProvider\\CliContextProvider;\nuse Symfony\\Component\\VarDumper\\Dumper\\ContextProvider\\RequestContextProvider;\nuse Symfony\\Component\\VarDumper\\Dumper\\ContextProvider\\SourceContextProvider;\nuse Symfony\\Component\\VarDumper\\Dumper\\ContextualizedDumper;\nuse Symfony\\Component\\VarDumper\\Dumper\\DataDumperInterface;\nuse Symfony\\Component\\VarDumper\\Dumper\\HtmlDumper;\nuse Symfony\\Component\\VarDumper\\Dumper\\ServerDumper;\n\n// Load the global dump() function\nrequire_once __DIR__.'/Resources/functions/dump.php';\n\n/**\n * @author Nicolas Grekas <p@tchwork.com>\n */\nclass VarDumper\n{\n    /**\n     * @var callable|null\n     */\n    private static $handler;\n\n    public static function dump(mixed $var, ?string $label = null): mixed\n    {\n        if (null === self::$handler) {\n            self::register();\n        }\n\n        return (self::$handler)($var, $label);\n    }\n\n    public static function setHandler(?callable $callable): ?callable\n    {\n        $prevHandler = self::$handler;\n\n        // Prevent replacing the handler with expected format as soon as the env var was set:\n        if (isset($_SERVER['VAR_DUMPER_FORMAT'])) {\n            return $prevHandler;\n        }\n\n        self::$handler = $callable;\n\n        return $prevHandler;\n    }\n\n    private static function register(): void\n    {\n        $cloner = new VarCloner();\n        $cloner->addCasters(ReflectionCaster::UNSET_CLOSURE_FILE_INFO);\n\n        $format = $_SERVER['VAR_DUMPER_FORMAT'] ?? null;\n\n        $dumper = match ($format) {\n            'html' => new HtmlDumper(),\n            'cli' => new CliDumper(),\n            'server' => self::selectDumperForAccept($_SERVER['VAR_DUMPER_SERVER'] ?? '127.0.0.1:9912'),\n            default => self::selectDumperForAccept(\n                $format && 'tcp' === parse_url($format, \\PHP_URL_SCHEME) ? $format : null,\n            ),\n        };\n\n        if (!$dumper instanceof ServerDumper) {\n            $dumper = new ContextualizedDumper($dumper, [new SourceContextProvider()]);\n        }\n\n        self::$handler = static function ($var, ?string $label = null) use ($cloner, $dumper) {\n            $var = $cloner->cloneVar($var);\n\n            if (null !== $label) {\n                $var = $var->withContext(['label' => $label]);\n            }\n\n            $dumper->dump($var);\n        };\n    }\n\n    private static function selectDumperForAccept(?string $serverHost): DataDumperInterface\n    {\n        $isCliSapi = \\in_array(\\PHP_SAPI, ['cli', 'phpdbg', 'embed'], true);\n        $accept = $_SERVER['HTTP_ACCEPT'] ?? ($isCliSapi ? 'txt' : 'html');\n\n        $dumper = match (true) {\n            str_contains($accept, 'html'), str_contains($accept, '*/*') => new HtmlDumper(),\n            $isCliSapi => new CliDumper(),\n            default => new CliDumper('php://output'),\n        };\n\n        if (null !== $serverHost) {\n            $dumper = new ServerDumper($serverHost, $dumper, self::getDefaultContextProviders());\n        }\n\n        return $dumper;\n    }\n\n    private static function getDefaultContextProviders(): array\n    {\n        $contextProviders = [];\n\n        if (!\\in_array(\\PHP_SAPI, ['cli', 'phpdbg', 'embed'], true) && class_exists(Request::class)) {\n            $requestStack = new RequestStack();\n            $requestStack->push(Request::createFromGlobals());\n            $contextProviders['request'] = new RequestContextProvider($requestStack);\n        }\n\n        $fileLinkFormatter = class_exists(FileLinkFormatter::class) ? new FileLinkFormatter(null, $requestStack ?? null) : null;\n\n        return $contextProviders + [\n            'cli' => new CliContextProvider(),\n            'source' => new SourceContextProvider(null, null, $fileLinkFormatter),\n        ];\n    }\n}\n"
  },
  {
    "path": "composer.json",
    "content": "{\n    \"name\": \"symfony/var-dumper\",\n    \"type\": \"library\",\n    \"description\": \"Provides mechanisms for walking through any arbitrary PHP variable\",\n    \"keywords\": [\"dump\", \"debug\"],\n    \"homepage\": \"https://symfony.com\",\n    \"license\": \"MIT\",\n    \"authors\": [\n        {\n            \"name\": \"Nicolas Grekas\",\n            \"email\": \"p@tchwork.com\"\n        },\n        {\n            \"name\": \"Symfony Community\",\n            \"homepage\": \"https://symfony.com/contributors\"\n        }\n    ],\n    \"require\": {\n        \"php\": \">=8.4\",\n        \"symfony/polyfill-mbstring\": \"^1.0\"\n    },\n    \"require-dev\": {\n        \"symfony/console\": \"^7.4|^8.0\",\n        \"symfony/http-kernel\": \"^7.4|^8.0\",\n        \"symfony/process\": \"^7.4|^8.0\",\n        \"symfony/uid\": \"^7.4|^8.0\",\n        \"twig/twig\": \"^3.12\"\n    },\n    \"conflict\": {\n        \"symfony/console\": \"<7.4\",\n        \"symfony/error-handler\": \"<7.4\"\n    },\n    \"autoload\": {\n        \"files\": [ \"Resources/functions/dump.php\" ],\n        \"psr-4\": { \"Symfony\\\\Component\\\\VarDumper\\\\\": \"\" },\n        \"exclude-from-classmap\": [\n            \"/Tests/\"\n        ]\n    },\n    \"bin\": [\n        \"Resources/bin/var-dump-server\"\n    ],\n    \"minimum-stability\": \"dev\"\n}\n"
  },
  {
    "path": "phpunit.xml.dist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\n<phpunit xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:noNamespaceSchemaLocation=\"https://schema.phpunit.de/11.3/phpunit.xsd\"\n         backupGlobals=\"false\"\n         colors=\"true\"\n         bootstrap=\"vendor/autoload.php\"\n         failOnDeprecation=\"true\"\n         failOnRisky=\"true\"\n         failOnWarning=\"true\"\n>\n    <php>\n        <ini name=\"error_reporting\" value=\"-1\" />\n        <env name=\"DUMP_LIGHT_ARRAY\" value=\"\" />\n        <env name=\"DUMP_STRING_LENGTH\" value=\"\" />\n    </php>\n\n    <testsuites>\n        <testsuite name=\"Symfony VarDumper Component Test Suite\">\n            <directory>./Tests/</directory>\n            <directory suffix=\".phpt\">./Tests/Dumper/functions/</directory>\n        </testsuite>\n    </testsuites>\n\n    <source ignoreSuppressionOfDeprecations=\"true\">\n        <include>\n            <directory>./</directory>\n        </include>\n        <exclude>\n            <directory>./Resources</directory>\n            <directory>./Tests</directory>\n            <directory>./vendor</directory>\n        </exclude>\n    </source>\n\n    <extensions>\n        <bootstrap class=\"Symfony\\Bridge\\PhpUnit\\SymfonyExtension\" />\n    </extensions>\n</phpunit>\n"
  }
]