diff --git a/README.rdoc b/README.rdoc index 0419f6cd7b7b8073d067da8c73abd10d3ec11fee..e6f618504505fdd7f73414771ae207680720e2ee 100644 --- a/README.rdoc +++ b/README.rdoc @@ -87,7 +87,7 @@ or, in a easier way, using the IPAddress parse method ip = IPAddress.parse "172.16.10.1/24" -which accepts and parses any kind of IP (IPv4, IPV6 and +which accepts and parses any kind of IP (uint32, IPv4, IPV6 and IPv4 IPv6 Mapped addresses). If you like syntactic sugar, you can use the wrapper method @@ -118,7 +118,14 @@ The new created object has prefix /32, which is the same as we created the following: host = IPAddress::IPv4.new "10.1.1.1/32" - + +You can also pass a uint32 to obtain an IPAddress::IPv4 object: + + # Create host object + ip = IPAddress 167837953 + puts ip.to_string + #=> "10.1.1.1/32" + === Handling the IPv4 address Once created, you can obtain the attributes for an IPv4 object: diff --git a/lib/ipaddress.rb b/lib/ipaddress.rb index e2161e1346f294e587b1dbd82342bf95a6b5d413..4033c3a202cd7a38d9cb9bc6051e057bdccebc71 100644 --- a/lib/ipaddress.rb +++ b/lib/ipaddress.rb @@ -26,6 +26,7 @@ module IPAddress # Parse the argument string to create a new # IPv4, IPv6 or Mapped IP object # + # ip = IPAddress.parse 167837953 # 10.1.1.1 # ip = IPAddress.parse "172.16.10.1/24" # ip6 = IPAddress.parse "2001:db8::8:800:200c:417a/64" # ip_mapped = IPAddress.parse "::ffff:172.16.10.1/128" @@ -41,6 +42,12 @@ module IPAddress # #=> IPAddress::IPv6::Mapped # def IPAddress::parse(str) + + # Check if an int was passed + if str.kind_of? Integer + return IPAddress::IPv4.new(ntoa(str)) + end + case str when /:.+\./ IPAddress::IPv6::Mapped.new(str) @@ -53,6 +60,24 @@ module IPAddress end end + # + # Converts a unit32 to IPv4 + # + # IPAddress::ntoa(167837953) + # #-> "10.1.1.1" + # + def self.ntoa(uint) + unless(uint.is_a? Numeric and uint <= 0xffffffff) + raise(::ArgumentError, "not a long integer: #{uint.inspect}") + end + ret = [] + 4.times do + ret.unshift(uint & 0xff) + uint >>= 8 + end + ret.join('.') + end + # # True if the object is an IPv4 address # diff --git a/test/ipaddress_test.rb b/test/ipaddress_test.rb index 8e2bb66858d6c211e4a9b6149ae8f50632f6c14f..c8bf2e7b434f0c8852dd3baa7ec6d39d6643ff09 100644 --- a/test/ipaddress_test.rb +++ b/test/ipaddress_test.rb @@ -11,9 +11,28 @@ class IPAddressTest < Test::Unit::TestCase @invalid_ipv6 = ":1:2:3:4:5:6:7" @invalid_mapped = "::1:2.3.4" + @valid_ipv4_uint32 = [4294967295, # 255.255.255.255 + 167772160, # 10.0.0.0 + 3232235520, # 192.168.0.0 + 0] + + @invalid_ipv4_uint32 = [4294967296, # 256.0.0.0 + "A294967295", # Invalid uINT + -1] # Invalid + + @ipv4class = IPAddress::IPv4 @ipv6class = IPAddress::IPv6 @mappedclass = IPAddress::IPv6::Mapped + + @invalid_ipv4 = ["10.0.0.256", + "10.0.0.0.0", + "10.0.0", + "10.0"] + + @valid_ipv4_range = ["10.0.0.1-254", + "10.0.1-254.0", + "10.1-254.0.0"] @method = Module.method("IPAddress") end @@ -31,6 +50,15 @@ class IPAddressTest < Test::Unit::TestCase assert_raise(ArgumentError) {@method.call(@invalid_ipv6)} assert_raise(ArgumentError) {@method.call(@invalid_mapped)} + assert_instance_of @ipv4class, @method.call(@valid_ipv4_uint32[0]) + assert_instance_of @ipv4class, @method.call(@valid_ipv4_uint32[1]) + assert_instance_of @ipv4class, @method.call(@valid_ipv4_uint32[2]) + assert_instance_of @ipv4class, @method.call(@valid_ipv4_uint32[3]) + + assert_raise(ArgumentError) {@method.call(@invalid_ipv4_uint32[0])} + assert_raise(ArgumentError) {@method.call(@invalid_ipv4_uint32[1])} + assert_raise(ArgumentError) {@method.call(@invalid_ipv4_uint32[2])} + end def test_module_method_valid? diff --git a/test/test_helper.rb b/test/test_helper.rb index 61e381e0be747e75819d9b77557d093a6d8fbd77..99fd5e998c96c521e656bcaa4902bc261a418901 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -1,4 +1,5 @@ require 'rubygems' +require 'minitest/autorun' require 'test/unit' $LOAD_PATH.unshift(File.dirname(__FILE__))