From 58606502363481dce0be5f6d819c889c987148e1 Mon Sep 17 00:00:00 2001 From: Zan Baldwin Date: Fri, 3 Jul 2026 14:15:13 +0200 Subject: [PATCH] =?UTF-8?q?feature(contracts):=20=E2=9C=A8=20add=20non-thr?= =?UTF-8?q?owing=20tryFrom=20siblings=20for=20the=20integer=20constructors?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Contracts/Factory4Interface.php | 7 +++++ src/Contracts/FactoryInterface.php | 8 ++++++ src/Version/IPv4.php | 18 ++++++++++++ src/Version/IPv6.php | 9 ++++++ src/Version/Multi.php | 18 ++++++++++++ tests/Version/IPv4Test.php | 44 +++++++++++++++++++++++++++++ tests/Version/IPv6Test.php | 22 +++++++++++++++ tests/Version/MultiTest.php | 40 ++++++++++++++++++++++++++ 8 files changed, 166 insertions(+) diff --git a/src/Contracts/Factory4Interface.php b/src/Contracts/Factory4Interface.php index cc90b26..5551213 100644 --- a/src/Contracts/Factory4Interface.php +++ b/src/Contracts/Factory4Interface.php @@ -20,4 +20,11 @@ interface Factory4Interface extends FactoryInterface * @return static */ public static function fromInteger(int $integer); + + /** + * Create a New IP From an Integer, or Null on Failure + * + * @return static|null + */ + public static function tryFromInteger(int $integer); } diff --git a/src/Contracts/FactoryInterface.php b/src/Contracts/FactoryInterface.php index d89ad90..c6d5b06 100644 --- a/src/Contracts/FactoryInterface.php +++ b/src/Contracts/FactoryInterface.php @@ -71,6 +71,14 @@ public static function tryFromHex(string $hex); */ public static function fromIntegerString(string $integer); + /** + * Create a New IP From an Integer Represented as a Decimal String, or + * Null on Failure + * + * @return static|null + */ + public static function tryFromIntegerString(string $integer); + /** Whether the supplied string is valid IP protocol notation. */ public static function isValid(string $ip): bool; } diff --git a/src/Version/IPv4.php b/src/Version/IPv4.php index 3cdfc90..327bb14 100644 --- a/src/Version/IPv4.php +++ b/src/Version/IPv4.php @@ -127,6 +127,15 @@ public static function fromInteger(int $integer) ); } + public static function tryFromInteger(int $integer) + { + try { + return static::fromInteger($integer); + } catch (Exception\InvalidIpAddressException $e) { + return null; + } + } + public static function fromIntegerString(string $integer) { try { @@ -137,6 +146,15 @@ public static function fromIntegerString(string $integer) return static::fromBinary($binary); } + public static function tryFromIntegerString(string $integer) + { + try { + return static::fromIntegerString($integer); + } catch (Exception\InvalidIpAddressException $e) { + return null; + } + } + public static function isValid(string $ip): bool { return null !== static::tryFromProtocol($ip); diff --git a/src/Version/IPv6.php b/src/Version/IPv6.php index 5725856..215250b 100644 --- a/src/Version/IPv6.php +++ b/src/Version/IPv6.php @@ -119,6 +119,15 @@ public static function fromIntegerString(string $integer) return static::fromBinary($binary); } + public static function tryFromIntegerString(string $integer) + { + try { + return static::fromIntegerString($integer); + } catch (Exception\InvalidIpAddressException $e) { + return null; + } + } + public static function isValid(string $ip): bool { return null !== static::tryFromProtocol($ip); diff --git a/src/Version/Multi.php b/src/Version/Multi.php index b88989c..0c8b854 100644 --- a/src/Version/Multi.php +++ b/src/Version/Multi.php @@ -173,6 +173,15 @@ public static function fromInteger(int $integer, ?EmbeddingStrategyInterface $st return static::fromBinary(IPv4::fromInteger($integer)->getBinary(), $strategy); } + public static function tryFromInteger(int $integer, ?EmbeddingStrategyInterface $strategy = null) + { + try { + return static::fromInteger($integer, $strategy); + } catch (Exception\InvalidIpAddressException $e) { + return null; + } + } + public static function fromIntegerString(string $integer, ?EmbeddingStrategyInterface $strategy = null) { try { @@ -183,6 +192,15 @@ public static function fromIntegerString(string $integer, ?EmbeddingStrategyInte return static::fromBinary($binary, $strategy); } + public static function tryFromIntegerString(string $integer, ?EmbeddingStrategyInterface $strategy = null) + { + try { + return static::fromIntegerString($integer, $strategy); + } catch (Exception\InvalidIpAddressException $e) { + return null; + } + } + public static function isValid(string $ip, ?EmbeddingStrategyInterface $strategy = null): bool { return null !== static::tryFromProtocol($ip, $strategy); diff --git a/tests/Version/IPv4Test.php b/tests/Version/IPv4Test.php index 4ec047b..1ac26e6 100644 --- a/tests/Version/IPv4Test.php +++ b/tests/Version/IPv4Test.php @@ -902,6 +902,28 @@ public function testFromIntegerThrowsOnOutOfRange(int $integer): void $this->fail(); } + /** + * @test + * @dataProvider \Darsyn\IP\Tests\DataProvider\IPv4::getIntegerAddresses() + */ + #[PHPUnit\Test] + #[PHPUnit\DataProviderExternal(IPv4DataProvider::class, 'getIntegerAddresses')] + public function testTryFromIntegerReturnsInstanceForValid(string $value, int $integer): void + { + $this->assertInstanceOf(Version4Interface::class, IP::tryFromInteger($integer)); + } + + /** + * @test + * @dataProvider \Darsyn\IP\Tests\DataProvider\IPv4::getInvalidIntegers() + */ + #[PHPUnit\Test] + #[PHPUnit\DataProviderExternal(IPv4DataProvider::class, 'getInvalidIntegers')] + public function testTryFromIntegerReturnsNullForOutOfRange(int $integer): void + { + $this->assertNull(IP::tryFromInteger($integer)); + } + /** * @test * @dataProvider \Darsyn\IP\Tests\DataProvider\IPv4::getIntegerStringData() @@ -955,6 +977,28 @@ public function testFromIntegerStringThrowsOnInvalidInput(string $value): void $this->fail(); } + /** + * @test + * @dataProvider \Darsyn\IP\Tests\DataProvider\IPv4::getIntegerStringData() + */ + #[PHPUnit\Test] + #[PHPUnit\DataProviderExternal(IPv4DataProvider::class, 'getIntegerStringData')] + public function testTryFromIntegerStringReturnsInstanceForValid(string $value, string $decimal): void + { + $this->assertInstanceOf(Version4Interface::class, IP::tryFromIntegerString($decimal)); + } + + /** + * @test + * @dataProvider \Darsyn\IP\Tests\DataProvider\IPv4::getInvalidIntegerStrings() + */ + #[PHPUnit\Test] + #[PHPUnit\DataProviderExternal(IPv4DataProvider::class, 'getInvalidIntegerStrings')] + public function testTryFromIntegerStringReturnsNullForInvalid(string $value): void + { + $this->assertNull(IP::tryFromIntegerString($value)); + } + /** * @test * @dataProvider \Darsyn\IP\Tests\DataProvider\IPv4::getHexStringData() diff --git a/tests/Version/IPv6Test.php b/tests/Version/IPv6Test.php index 7698449..0f79d46 100644 --- a/tests/Version/IPv6Test.php +++ b/tests/Version/IPv6Test.php @@ -971,6 +971,28 @@ public function testFromIntegerStringThrowsOnInvalidInput(string $value): void $this->fail(); } + /** + * @test + * @dataProvider \Darsyn\IP\Tests\DataProvider\IPv6::getValidBinarySequences() + */ + #[PHPUnit\Test] + #[PHPUnit\DataProviderExternal(IPv6DataProvider::class, 'getValidBinarySequences')] + public function testTryFromIntegerStringReturnsInstanceForValid(string $value, string $hex, string $expanded, string $compacted): void + { + $this->assertInstanceOf(Version6Interface::class, IP::tryFromIntegerString(Binary::toDecimalString($value))); + } + + /** + * @test + * @dataProvider \Darsyn\IP\Tests\DataProvider\IPv6::getInvalidIntegerStrings() + */ + #[PHPUnit\Test] + #[PHPUnit\DataProviderExternal(IPv6DataProvider::class, 'getInvalidIntegerStrings')] + public function testTryFromIntegerStringReturnsNullForInvalid(string $value): void + { + $this->assertNull(IP::tryFromIntegerString($value)); + } + /** * @test * @dataProvider \Darsyn\IP\Tests\DataProvider\IPv6::getValidBinarySequences() diff --git a/tests/Version/MultiTest.php b/tests/Version/MultiTest.php index 3b215b2..f5e2d7c 100644 --- a/tests/Version/MultiTest.php +++ b/tests/Version/MultiTest.php @@ -1034,6 +1034,24 @@ public function testFromIntegerThrowsOnOutOfRange(int $integer): void IP::fromInteger($integer); } + /** @test */ + #[PHPUnit\Test] + public function testTryFromIntegerReturnsInstanceForValid(): void + { + $this->assertInstanceOf(MultiVersionInterface::class, IP::tryFromInteger(203569230)); + } + + /** + * @test + * @dataProvider \Darsyn\IP\Tests\DataProvider\IPv4::getInvalidIntegers() + */ + #[PHPUnit\Test] + #[PHPUnit\DataProviderExternal(IPv4DataProvider::class, 'getInvalidIntegers')] + public function testTryFromIntegerReturnsNullForOutOfRange(int $integer): void + { + $this->assertNull(IP::tryFromInteger($integer)); + } + /** @test */ #[PHPUnit\Test] public function testToHexStringReturnsFullWidthWhenEmbedded(): void @@ -1083,6 +1101,28 @@ public function testFromIntegerStringThrowsOnInvalidInput(string $value): void IP::fromIntegerString($value); } + /** + * @test + * @dataProvider \Darsyn\IP\Tests\DataProvider\Multi::getValidBinarySequences() + */ + #[PHPUnit\Test] + #[PHPUnit\DataProviderExternal(MultiDataProvider::class, 'getValidBinarySequences')] + public function testTryFromIntegerStringReturnsInstanceForValid(string $value, string $hex, string $expanded, string $compacted, ?string $dot): void + { + $this->assertInstanceOf(MultiVersionInterface::class, IP::tryFromIntegerString(Binary::toDecimalString($value))); + } + + /** + * @test + * @dataProvider \Darsyn\IP\Tests\DataProvider\IPv6::getInvalidIntegerStrings() + */ + #[PHPUnit\Test] + #[PHPUnit\DataProviderExternal(IPv6DataProvider::class, 'getInvalidIntegerStrings')] + public function testTryFromIntegerStringReturnsNullForInvalid(string $value): void + { + $this->assertNull(IP::tryFromIntegerString($value)); + } + /** * @test * @dataProvider \Darsyn\IP\Tests\DataProvider\Multi::getValidProtocolIpVersion4Addresses()