From: Brian Candler Date: 2007-03-22T15:58:51+09:00 Subject: Re: Extensions to ipaddr.rb Responding to several points at once: > "255.255.255.240".to_i => 255 > > d = a & "255.255.255.240" => # > > :-( Hmm. I guess these operators could do IPAddr.new() on their RHS, unless RHS is already an IPAddr. But arguably the above is simply undefined behaviour, i.e. trying to combine an IPAddr with a string. I agree that using to_int [or IPAddr.new] would give a more helpful error or more useful behaviour. > * IPAddr#<=> > addr1 = IPAddr.new("192.168.0.1") > addr2 = addr1.succ > puts addr1 <=> addr2 # => -1 > puts addr1 <=> addr1 # => 0 > puts addr2 <=> addr1 # => 1 Comparable is a nice idea. However note that this class also encapsulates IPv4, IPv6, and IPv4-in-IPv6 addresses; you'd have to decide what to do when comparing different ones. OTOH, there is already an 'include?' method so the logic can be borrowed from that. Then the include? operator could then be rewritten in terms of a Range. > class IPAddr > def entries > list = [] > 0.upto(~@mask_addr & IN4MASK) do |i| > list << IPAddr.new(_to_string(@addr + i)) > end > list > end > end > > ip = IPAddr.new("192.168.5.0/28") > ip.entries.each do |ip| > puts ip > end I would do it differently; give class IPAddr an 'each' method which yields each of the values (perhaps delegating to Range#each), and then make it Enumerable. Otherwise, if you call 'entries' on a /48 IPv6 address you will generate an intermediate array with 2^80 entries :-( Now, arguably a Range might be better internal data structure than an address plus mask, as both 'include?' and 'size' would be trivial. You could then do IPAddr.new("192.168.0.5", "192.168.0.13") which might be useful. You could even subclass Range. But I wasn't coming here to suggest a redesign of IPAddr - it works, and it does *almost* what I want already. However, given a (say) /28 prefix, I need to be able to find: - the base address + 1 (router IP) - the base address + 2 (dhcp start) - the end of the block - 2 (dhcp end) - the end of the block - 1 (broadcast) - the netmask That's why I proposed those new methods, as there doesn't seem to be a straightforward way to do it otherwise without digging directly in with instance_eval. Regards, Brian.