Skip to content

Commit 34ea2d9

Browse files
[VarDumper] Add caster for AddressInfo objects
1 parent e5fe662 commit 34ea2d9

File tree

4 files changed

+136
-0
lines changed

4 files changed

+136
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\VarDumper\Caster;
13+
14+
use Symfony\Component\VarDumper\Cloner\Stub;
15+
16+
/**
17+
* @author Nicolas Grekas <p@tchwork.com>
18+
*/
19+
final class AddressInfoCaster
20+
{
21+
private const MAPS = [
22+
'ai_flags' => [
23+
1 => 'AI_PASSIVE',
24+
2 => 'AI_CANONNAME',
25+
4 => 'AI_NUMERICHOST',
26+
8 => 'AI_V4MAPPED',
27+
16 => 'AI_ALL',
28+
32 => 'AI_ADDRCONFIG',
29+
64 => 'AI_IDN',
30+
128 => 'AI_CANONIDN',
31+
1024 => 'AI_NUMERICSERV',
32+
],
33+
'ai_family' => [
34+
1 => 'AF_UNIX',
35+
2 => 'AF_INET',
36+
10 => 'AF_INET6',
37+
44 => 'AF_DIVERT',
38+
],
39+
'ai_socktype' => [
40+
1 => 'SOCK_STREAM',
41+
2 => 'SOCK_DGRAM',
42+
3 => 'SOCK_RAW',
43+
4 => 'SOCK_RDM',
44+
5 => 'SOCK_SEQPACKET',
45+
],
46+
'ai_protocol' => [
47+
1 => 'SOL_SOCKET',
48+
6 => 'SOL_TCP',
49+
17 => 'SOL_UDP',
50+
136 => 'SOL_UDPLITE',
51+
],
52+
];
53+
54+
public static function castAddressInfo(\AddressInfo $h, array $a, Stub $stub, bool $isNested)
55+
{
56+
static $resolvedMaps;
57+
58+
if (!$resolvedMaps) {
59+
foreach (self::MAPS as $k => $map) {
60+
foreach ($map as $v => $name) {
61+
if (\defined($name)) {
62+
$resolvedMaps[$k][\constant($name)] = $name;
63+
} elseif (!isset($resolvedMaps[$k][$v])) {
64+
$resolvedMaps[$k][$v] = $name;
65+
}
66+
}
67+
}
68+
}
69+
70+
foreach (socket_addrinfo_explain($h) as $k => $v) {
71+
$a[Caster::PREFIX_VIRTUAL.$k] = match (true) {
72+
'ai_flags' === $k => ConstStub::fromBitfield($v, $resolvedMaps[$k]),
73+
isset($resolvedMaps[$k][$v]) => new ConstStub($resolvedMaps[$k][$v], $v),
74+
default => $v,
75+
};
76+
}
77+
78+
return $a;
79+
}
80+
}

src/Symfony/Component/VarDumper/Caster/ConstStub.php

+19
Original file line numberDiff line numberDiff line change
@@ -30,4 +30,23 @@ public function __toString(): string
3030
{
3131
return (string) $this->value;
3232
}
33+
34+
/**
35+
* @param array<int, string> $values
36+
*/
37+
public static function fromBitfield(int $value, array $values): self
38+
{
39+
$names = [];
40+
foreach ($values as $v => $name) {
41+
if ($value & $v) {
42+
$names[] = $name;
43+
}
44+
}
45+
46+
if (!$names) {
47+
$names[] = $values[0] ?? 0;
48+
}
49+
50+
return new self(implode(' | ', $names), $value);
51+
}
3352
}

src/Symfony/Component/VarDumper/Cloner/AbstractCloner.php

+2
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ abstract class AbstractCloner implements ClonerInterface
2424
public static array $defaultCasters = [
2525
'__PHP_Incomplete_Class' => ['Symfony\Component\VarDumper\Caster\Caster', 'castPhpIncompleteClass'],
2626

27+
'AddressInfo' => ['Symfony\Component\VarDumper\Caster\AddressInfoCaster', 'castAddressInfo'],
28+
2729
'Symfony\Component\VarDumper\Caster\CutStub' => ['Symfony\Component\VarDumper\Caster\StubCaster', 'castStub'],
2830
'Symfony\Component\VarDumper\Caster\CutArrayStub' => ['Symfony\Component\VarDumper\Caster\StubCaster', 'castCutArray'],
2931
'Symfony\Component\VarDumper\Caster\ConstStub' => ['Symfony\Component\VarDumper\Caster\StubCaster', 'castStub'],
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\VarDumper\Tests\Caster;
13+
14+
use PHPUnit\Framework\TestCase;
15+
use Symfony\Component\VarDumper\Test\VarDumperTestTrait;
16+
17+
/**
18+
* @requires extension sockets
19+
*/
20+
class AddressInfoCasterTest extends TestCase
21+
{
22+
use VarDumperTestTrait;
23+
24+
public function testCaster()
25+
{
26+
$xDump = <<<EODUMP
27+
AddressInfo {
28+
ai_flags: 0
29+
ai_family: AF_INET%A
30+
}
31+
EODUMP;
32+
33+
$this->assertDumpMatchesFormat($xDump, socket_addrinfo_lookup('localhost')[0]);
34+
}
35+
}

0 commit comments

Comments
 (0)