diff --git a/lib/ipaddress/ipv4.rb b/lib/ipaddress/ipv4.rb index 70d1a51..75d2e54 100644 --- a/lib/ipaddress/ipv4.rb +++ b/lib/ipaddress/ipv4.rb @@ -478,6 +478,35 @@ def each end end + # + # Returns the successor to the IP address + # + # Example: + # + # ip = IPAddress("192.168.45.23/16") + # + # ip.succ.to_string + # => "192.168.45.24/16" + # + def succ + self.class.new("#{IPAddress.ntoa(to_u32.succ % 0x100000000)}/#{prefix}") + end + alias_method :next, :succ + + # + # Returns the predecessor to the IP address + # + # Example: + # + # ip = IPAddress("192.168.45.23/16") + # + # ip.pred.to_string + # => "192.168.45.22/16" + # + def pred + self.class.new("#{IPAddress.ntoa(to_u32.pred % 0x100000000)}/#{prefix}") + end + # # Spaceship operator to compare IPv4 objects # diff --git a/lib/ipaddress/ipv6.rb b/lib/ipaddress/ipv6.rb index f427954..e7d9c11 100644 --- a/lib/ipaddress/ipv6.rb +++ b/lib/ipaddress/ipv6.rb @@ -491,6 +491,35 @@ def each end end + # + # Returns the successor to the IP address + # + # Example: + # + # ip6 = IPAddress("2001:db8::8:800:200c:417a/64") + # + # ip6.succ.to_string + # => "2001:db8::8:800:200c:417b/64" + # + def succ + IPAddress::IPv6.parse_u128(to_u128.succ, prefix) + end + alias_method :next, :succ + + # + # Returns the predecessor to the IP address + # + # Example: + # + # ip6 = IPAddress("2001:db8::8:800:200c:417a/64") + # + # ip6.pred.to_string + # => "2001:db8::8:800:200c:4179/64" + # + def pred + IPAddress::IPv6.parse_u128(to_u128.pred, prefix) + end + # # Spaceship operator to compare IPv6 objects # diff --git a/test/ipaddress/ipv4_test.rb b/test/ipaddress/ipv4_test.rb index 19e0450..8954d2b 100644 --- a/test/ipaddress/ipv4_test.rb +++ b/test/ipaddress/ipv4_test.rb @@ -258,6 +258,36 @@ def test_method_each assert_equal expected, arr end + def test_method_succ + ip = @klass.new("192.168.100.0/24") + assert_instance_of @klass, ip.succ + assert_equal "192.168.100.1/24", ip.succ.to_string + ip = @klass.new("192.168.100.50/24") + assert_instance_of @klass, ip.succ + assert_equal "192.168.100.51/24", ip.succ.to_string + ip = @klass.new("0.0.0.0/32") + assert_instance_of @klass, ip.succ + assert_equal "0.0.0.1/32", ip.succ.to_string + ip = @klass.new("255.255.255.255/32") + assert_instance_of @klass, ip.succ + assert_equal "0.0.0.0/32", ip.succ.to_string + end + + def test_method_pred + ip = @klass.new("192.168.100.0/24") + assert_instance_of @klass, ip.pred + assert_equal "192.168.99.255/24", ip.pred.to_string + ip = @klass.new("192.168.100.50/24") + assert_instance_of @klass, ip.pred + assert_equal "192.168.100.49/24", ip.pred.to_string + ip = @klass.new("0.0.0.0/32") + assert_instance_of @klass, ip.pred + assert_equal "255.255.255.255/32", ip.pred.to_string + ip = @klass.new("255.255.255.255/32") + assert_instance_of @klass, ip.pred + assert_equal "255.255.255.254/32", ip.pred.to_string + end + def test_method_size ip = @klass.new("10.0.0.1/29") assert_equal 8, ip.size diff --git a/test/ipaddress/ipv6_test.rb b/test/ipaddress/ipv6_test.rb index 9d7736d..bae2cdb 100644 --- a/test/ipaddress/ipv6_test.rb +++ b/test/ipaddress/ipv6_test.rb @@ -282,6 +282,35 @@ def test_method_each assert_equal expected, arr end + def test_method_succ + ip = @klass.new("2001:db8:0:cd30::/64") + assert_instance_of @klass, ip.succ + assert_equal "2001:db8:0:cd30::1/64", ip.succ.to_string + ip = @klass.new("::") + assert_instance_of @klass, ip.succ + assert_equal "::1/128", ip.succ.to_string + ip = @klass.new("::1") + assert_instance_of @klass, ip.succ + assert_equal "::2/128", ip.succ.to_string + ip = @klass.new("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/64") + assert_instance_of @klass, ip.succ + assert_equal "::/64", ip.succ.to_string + end + + def test_method_pred + ip = @klass.new("2001:db8:0:cd30::/64") + assert_instance_of @klass, ip.pred + assert_equal "2001:db8:0:cd2f:ffff:ffff:ffff:ffff/64", ip.pred.to_string + ip = @klass.new("::") + assert_instance_of @klass, ip.pred + assert_equal "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/128", ip.pred.to_string + ip = @klass.new("::1") + assert_instance_of @klass, ip.pred + assert_equal "::/128", ip.pred.to_string + ip = @klass.new("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/64") + assert_instance_of @klass, ip.pred + assert_equal "ffff:ffff:ffff:ffff:ffff:ffff:ffff:fffe/64", ip.pred.to_string + def test_allocate_addresses ip = @klass.new("2001:db8::4/125") ip1 = ip.allocate