Skip to content

Commit

Permalink
Add InternetAddress::tryFromString()
Browse files Browse the repository at this point in the history
  • Loading branch information
trowski authored and kelunik committed Apr 6, 2023
1 parent ef0b246 commit 70a72fb
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 21 deletions.
54 changes: 36 additions & 18 deletions src/InternetAddress.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,44 @@
final class InternetAddress implements SocketAddress
{
/**
* @throws SocketException
* @throws SocketException Thrown if the address or port is invalid.
*/
public static function fromString(string $address): self
{
if (!\str_contains($address, ':')) {
throw new SocketException('Missing port in address: ' . $address);
}

return self::tryFromString($address)
?? throw new SocketException('Invalid address: ' . $address);
}

/**
* @return self|null Returns null if the address is invalid.
*/
public static function tryFromString(string $address): ?self
{
$colon = \strrpos($address, ':');
if ($colon === false) {
throw new \ValueError('Missing port in address: ' . $address);
return null;
}

$ip = \substr($address, 0, $colon);
$port = \substr($address, $colon + 1);
$port = (int) \substr($address, $colon + 1);

/** @psalm-suppress ArgumentTypeCoercion */
return new self($ip, (int) $port);
if ($port < 0 || $port > 65535) {
return null;
}

if (\strrpos($ip, ':')) {
$ip = \trim($ip, '[]');
}

if (!\inet_pton($ip)) {
return null;
}

return new self($ip, $port);
}

private readonly string $binaryAddress;
Expand All @@ -31,32 +55,26 @@ public static function fromString(string $address): self
/**
* @param int<0, 65535> $port
*
* @throws SocketException If an invalid address is given.
* @throws SocketException If an invalid address or port is given.
*/
public function __construct(string $address, int $port)
{
/** @psalm-suppress TypeDoesNotContainType */
if ($port < 0 || $port > 65535) {
throw new \ValueError('Port number must be an integer between 0 and 65535; got ' . $port);
throw new SocketException('Port number must be an integer between 0 and 65535; got ' . $port);
}

if (\strrpos($address, ':')) {
$address = \trim($address, '[]');
}

\set_error_handler(static fn () => throw new SocketException('Invalid address: ' . $address));

try {
$binaryAddress = \inet_pton($address);
if ($binaryAddress === false) {
throw new SocketException('Invalid address: ' . $address);
}

$this->binaryAddress = $binaryAddress;
} finally {
\restore_error_handler();
$binaryAddress = \inet_pton($address);
if ($binaryAddress === false) {
throw new SocketException('Invalid address: ' . $address);
}

$this->binaryAddress = $binaryAddress;

$this->textualAddress = \inet_ntop($binaryAddress);
$this->port = $port;
}
Expand Down
6 changes: 3 additions & 3 deletions test/InternetAddressTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public function testFromString(): void
*/
public function testFromStringMissingPort(): void
{
$this->expectException(\ValueError::class);
$this->expectException(SocketException::class);
$this->expectExceptionMessage('Missing port');

InternetAddress::fromString('1.1.1.1');
Expand All @@ -35,8 +35,8 @@ public function testFromStringMissingPort(): void
*/
public function testFromStringInvalidPort(): void
{
$this->expectException(\ValueError::class);
$this->expectExceptionMessage('Port number must be an integer between 0 and 65535');
$this->expectException(SocketException::class);
$this->expectExceptionMessage('Invalid address');

InternetAddress::fromString('1.1.1.1:-1');
}
Expand Down

0 comments on commit 70a72fb

Please sign in to comment.