You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

32 lines
901 B

  1. # frozen_string_literal: true
  2. class FastIpMap
  3. MAX_IPV4_PREFIX = 32
  4. MAX_IPV6_PREFIX = 128
  5. # @param [Enumerable<IPAddr>] addresses
  6. def initialize(addresses)
  7. @fast_lookup = {}
  8. @ranges = []
  9. # Hash look-up is faster but only works for exact matches, so we split
  10. # exact addresses from non-exact ones
  11. addresses.each do |address|
  12. if (address.ipv4? && address.prefix == MAX_IPV4_PREFIX) || (address.ipv6? && address.prefix == MAX_IPV6_PREFIX)
  13. @fast_lookup[address.to_s] = true
  14. else
  15. @ranges << address
  16. end
  17. end
  18. # We're more likely to hit wider-reaching ranges when checking for
  19. # inclusion, so make sure they're sorted first
  20. @ranges.sort_by!(&:prefix)
  21. end
  22. # @param [IPAddr] address
  23. # @return [Boolean]
  24. def include?(address)
  25. @fast_lookup[address.to_s] || @ranges.any? { |cidr| cidr.include?(address) }
  26. end
  27. end