class BetterIpaddr::Space

Address space utilities

Attributes

family[R]
networks[R]
space[R]

Public Class Methods

new(networks, space: nil, family: nil) click to toggle source
# File lib/better_ipaddr/space.rb, line 11
def initialize(networks, space: nil, family: nil)
  @family = family || infer_address_family(space, *networks)
  @networks = networks.map { |network| import(network) }.sort
  return unless space
  @space = space
  outlier = @networks.find { |net| !@space.cover?(net) }
  return unless outlier
  raise ArgumentError, "Address space #{@space.inspect} does not cover "\
                       "network #{outlier.inspect}"
end

Public Instance Methods

+(other) click to toggle source
# File lib/better_ipaddr/space.rb, line 22
def +(other)
  self.class.new(networks + other.networks, family: family)
end
==(other) click to toggle source
# File lib/better_ipaddr/space.rb, line 26
def ==(other)
  networks == other.networks
end
each() { |network| ... } click to toggle source
# File lib/better_ipaddr/space.rb, line 30
def each
  if block_given?
    networks.each do |network|
      yield network
    end
  else
    networks.each
  end
end
find_by_minimum_prefix_length(length) click to toggle source
# File lib/better_ipaddr/space.rb, line 44
def find_by_minimum_prefix_length(length)
  find_all { |net| net.prefix_length >= length }.min_by(&:prefix_length)
end
find_by_minimum_size(size) click to toggle source
# File lib/better_ipaddr/space.rb, line 40
def find_by_minimum_size(size)
  find_all { |net| net.size >= size }.min_by(&:prefix_length)
end
gaps() click to toggle source
# File lib/better_ipaddr/space.rb, line 48
def gaps
  return export([space]) if space && networks.empty?
  gap_networks = if space
                   gaps_before + gaps_between + gaps_after
                 else
                   gaps_between
                 end
  self.class.new(gap_networks, family: family)
end
summarize() click to toggle source
# File lib/better_ipaddr/space.rb, line 58
def summarize
  out = []
  networks.each do |network|
    summary = network.summarize_with(out.last)
    if summary
      out[-1] = summary
      summarize_backtrack(out)
    else
      out << network
    end
  end
  export(out)
end
summarize_backtrack(list) click to toggle source
# File lib/better_ipaddr/space.rb, line 72
def summarize_backtrack(list)
  loop do
    break unless list.size >= 2
    summary = list[-1].summarize_with(list[-2])
    break unless summary
    list.pop 2
    list << summary
  end
end
with_space(space) click to toggle source
# File lib/better_ipaddr/space.rb, line 82
def with_space(space)
  export(networks, space: space)
end

Private Instance Methods

export(new_networks, space: nil) click to toggle source
# File lib/better_ipaddr/space.rb, line 103
def export(new_networks, space: nil)
  self.class.new(new_networks, space: space, family: family)
end
gaps_after() click to toggle source
# File lib/better_ipaddr/space.rb, line 107
def gaps_after
  export([networks.last.last, space.last + 1]).gaps
end
gaps_before() click to toggle source
# File lib/better_ipaddr/space.rb, line 111
def gaps_before
  export([space.first - 1, networks.first.first]).gaps
end
gaps_between() click to toggle source
# File lib/better_ipaddr/space.rb, line 115
def gaps_between
  gap_networks = []
  summarize.each_cons(2) do |a, b|
    gap_networks.concat(subnets_between(a, b))
  end
  export(gap_networks)
end
import(network) click to toggle source
# File lib/better_ipaddr/space.rb, line 88
def import(network)
  case network
  when String, Numeric
    IPAddr[network, family]
  else
    network
  end
end
infer_address_family(*networks) click to toggle source
# File lib/better_ipaddr/space.rb, line 97
def infer_address_family(*networks)
  example = networks.find { |net| net.respond_to?(:family) }
  return example.family if example
  raise "Unable to infer address family"
end
max_supernet_between(before, after, start) click to toggle source
# File lib/better_ipaddr/space.rb, line 135
def max_supernet_between(before, after, start)
  next_candidate = start
  until next_candidate.overlap?(before) || next_candidate.overlap?(after)
    candidate = next_candidate
    next_candidate = next_candidate.grow(1)
  end
  candidate
end
subnets_between(before, after) click to toggle source
# File lib/better_ipaddr/space.rb, line 123
def subnets_between(before, after)
  subnets = []
  candidate = before.last + 1
  while candidate < after
    candidate = max_supernet_between(before, after, candidate)
    break unless candidate
    subnets << candidate
    candidate = candidate.last + 1
  end
  subnets
end