Class: IPAddr::Base

Inherits:
IPAddr show all
Includes:
BetterIpaddr::Constants, BetterIpaddr::InstanceMethods, Comparable, Enumerable
Defined in:
lib/better_ipaddr/classes.rb

Overview

An intermediate superclass for all BetterIpaddr classes

Direct Known Subclasses

MAC, V4, V6

Constant Summary

Constants included from BetterIpaddr::Constants

BetterIpaddr::Constants::FAMILY_TO_BIT_LENGTH, BetterIpaddr::Constants::NETMASK_TO_PREFIX_LENGTH, BetterIpaddr::Constants::PREFIX_LENGTH_TO_NETMASK, BetterIpaddr::Constants::SYMBOL_TO_FAMILY

Instance Attribute Summary

Attributes included from BetterIpaddr::InstanceMethods

#family, #mask_addr

Class Method Summary collapse

Instance Method Summary collapse

Methods included from BetterIpaddr::InstanceMethods

#+, #-, #<=>, #==, #[], #base, #better_to_s, #cidr, #cover?, #each, #first, #grow, #hash, #host?, included, #inspect, #last, #netmask, #overlap?, #shrink, #size, #summarize_with, #to_range, #wildcard

Methods inherited from IPAddr

Host

Class Method Details

.[](address, mask = nil, family: self::FAMILY, classful: false) ⇒ IPAddr, Nil

Create an IPAddr from the given object.

Returns nil if the object is of a type that can’t be converted to an IPAddr.

Parameters:

  • address (Integer, IPAddr, String)
  • mask (Integer, IPAddr, String, Nil) (defaults to: nil)
  • family (Integer) (defaults to: self::FAMILY)
  • classful (Boolean) (defaults to: false)

    see Base.from_string

Returns:



23
24
25
26
27
28
29
30
31
32
33
34
# File 'lib/better_ipaddr/classes.rb', line 23

def self.[](address, mask = nil, family: self::FAMILY, classful: false)
  prefix_length = mask && object_to_prefix_length(mask, family)

  case address
  when Integer
    from_integer(address, prefix_length, family: family)
  when IPAddr
    from_ipaddr(address, prefix_length, family: family)
  when String
    from_string(address, prefix_length, family: family, classful: classful)
  end
end

.class_convert(address, mask = nil, classful: nil, exception: false) ⇒ IPAddr, Nil

Convert the given object using its class_converter, if one exists.

Returns:



114
115
116
117
118
119
120
121
122
123
124
125
126
# File 'lib/better_ipaddr/classes.rb', line 114

def self.class_convert(address, mask = nil, classful: nil, exception: false)
  converter = class_converter(address)
  converter && converter.call(
    address,
    mask,
    classful: classful,
    exception: exception
  ) || (
    if exception
      (raise TypeError, "can't convert #{address.inspect} to #{self}")
    end
  )
end

.class_converter(address) ⇒ Proc, ...

Return the class_converter for the given object, if one exists.

Checks by both class identity and class name so that every class with a converter doesn’t need to be loaded for this file to load.

Returns:

  • (Proc, Method, Nil)


101
102
103
104
# File 'lib/better_ipaddr/classes.rb', line 101

def self.class_converter(address)
  class_converters[address.class] ||= class_converters[address.class.name]
  class_converters[address.class]
end

.class_converter?(address) ⇒ Boolean

Returns:

  • (Boolean)


106
107
108
109
# File 'lib/better_ipaddr/classes.rb', line 106

def self.class_converter?(address)
  class_converters.key?(address.class) ||
    class_converters.key?(address.class.name)
end

.class_convertersHash{String, Class => Proc, Method}

A Hash of classes and class names which can be converted to IPAddr::Base subclasses, but which are not necessarily loaded at the same time as this file.

Conversion callables for custom classes can be registered here, e.g., with custom class Foo:

IPAddr::Base.class_converters[Foo] = proc { |foo, _| foo.to_ipaddr }

The arguments passed to the callable will be the same as the parameters of Kernel#IPAddr.

Returns:

  • (Hash{String, Class => Proc, Method})


88
89
90
91
92
93
# File 'lib/better_ipaddr/classes.rb', line 88

def self.class_converters
  @class_converters ||= {
    'Resolv::IPv4' => V4.method(:from_string_representable),
    'Resolv::IPv6' => V6.method(:from_string_representable)
  }
end

.from(address, exception: false, classful: false) ⇒ IPAddr, Nil

Create an IPAddr from the given object, guessing the type of address given based on its type and content.

Note that an Integer that corresponds to an IPv4 address will be converted to an IPAddr::V4, even though all such Integers also correspond to valid IPv6 addresses.

Returns nil if the object can’t be converted based on its type and content.

Parameters:

  • address (Integer, IPAddr, String)
  • exception (Boolean) (defaults to: false)

    If true, then when the given object can’t be converted to an IPAddr, a TypeError will be raise rather than returning nil.

  • classful (Boolean) (defaults to: false)

    see Base.from_string

Returns:



54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
# File 'lib/better_ipaddr/classes.rb', line 54

def self.from(address, exception: false, classful: false)
  if class_converter?(address)
    return class_convert(address, classful: classful, exception: exception)
  end

  case address
  when IPAddr
    specialize address
  when Regex::IPV4, 0..V4::MAX_INT
    V4[address, classful: classful]
  when Regex::IPV6, 0..V6::MAX_INT
    V6[address]
  end || (
    if exception
      (raise TypeError, "can't convert #{address.inspect} to #{self}")
    end
  )
end

.from_integer(address, prefix_length, family: self::FAMILY) ⇒ IPAddr

Create an IPAddr from an Integer.

Parameters:

  • address (Integer)
  • mask (Integer, String)

    a netmask or prefix length

  • family (Integer, Nil) (defaults to: self::FAMILY)

Returns:



153
154
155
# File 'lib/better_ipaddr/classes.rb', line 153

def self.from_integer(address, prefix_length, family: self::FAMILY)
  new(address, family).mask(prefix_length || FAMILY_TO_BIT_LENGTH[family])
end

.from_ipaddr(address, prefix_length, family: self::FAMILY) ⇒ IPAddr

Create an IPAddr from an IPAddr.

Parameters:

  • address (IPAddr)
  • mask (Integer, String)

    a netmask or prefix length

  • family (Integer, Nil) (defaults to: self::FAMILY)

Returns:



163
164
165
166
# File 'lib/better_ipaddr/classes.rb', line 163

def self.from_ipaddr(address, prefix_length, family: self::FAMILY)
  address = specialize(address)
  new(address.to_i, family).mask(prefix_length || address.prefix_length)
end

.from_string(address, mask = nil, family: self::FAMILY, classful: false) ⇒ IPAddr

Create an IPAddr from a String.

Parameters:

  • address (String)
  • mask (Integer, String) (defaults to: nil)

    a netmask or prefix length

  • family (Integer, Nil) (defaults to: self::FAMILY)
  • classful (Boolean) (defaults to: false)

    controls the conversion of IPv4 addresses without a prefix length in CIDR notation. When false, these are assumed to be host networks (/32). When true, these are assumed to be classful (rfc791) networks, with an implicit prefix length. Has no effect on IPv6 addresses.

Returns:



179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
# File 'lib/better_ipaddr/classes.rb', line 179

def self.from_string(
  address,
  mask = nil,
  family: self::FAMILY,
  classful: false
)
  if mask
    new(address, family).mask(mask)
  elsif !classful || address.include?('/')
    new(address, family)
  else
    ipaddr = new(address, family)
    return ipaddr unless ipaddr.ipv4?
    ipaddr.classful || ipaddr
  end
end

.from_string_representable(address, mask = nil, family: self::FAMILY, classful: false, exception: false) ⇒ IPAddr

Create an IPAddr from an object that can be converted to a String via #to_s.

Parameters:

  • address (#to_s)
  • mask (Integer, String) (defaults to: nil)

    a netmask or prefix length

  • family (Integer, Nil) (defaults to: self::FAMILY)
  • classful (Boolean) (defaults to: false)

    controls the conversion of IPv4 addresses without a prefix length in CIDR notation. When false, these are assumed to be host networks (/32). When true, these are assumed to be classful (rfc791) networks, with an implicit prefix length. Has no effect on IPv6 addresses.

Returns:



209
210
211
212
213
214
215
216
217
# File 'lib/better_ipaddr/classes.rb', line 209

def self.from_string_representable(
  address,
  mask = nil,
  family: self::FAMILY,
  classful: false,
  exception: false
)
  from_string(address.to_s, mask, family: family, classful: classful)
end

.host_from(address, exception: false) ⇒ IPAddr::Host, Nil

Create an IPAddr host subclass from the given object, guessing the type of address given based on its type and content.

Uses .from internally, so the same concerns apply, though the returned object is guaranteed to be of a Host class or nil.

Parameters:

  • address (Integer, IPAddr, String)
  • exception (Boolean) (defaults to: false)

    See IPAddr::Base.from

Returns:

  • (IPAddr::Host, Nil)


138
139
140
141
142
143
144
145
# File 'lib/better_ipaddr/classes.rb', line 138

def self.host_from(address, exception: false)
  ip = from(address, exception: exception)
  if ip && ip.ipv4?
    V4::Host[ip]
  elsif ip && ip.ipv6?
    V6::Host[ip]
  end
end

.integer_to_prefix_length(mask, family = self::FAMILY) ⇒ Integer

Convert an integer to a prefix length.

If the integer is within the range of possible prefix lengths, returns the same integer. Otherwise it assumes that the given integer is the integer representation of a netmask.

Returns nil if the integer can’t be converted.

Parameters:

  • mask (Integer)

Returns:

  • (Integer)


247
248
249
250
251
252
253
254
# File 'lib/better_ipaddr/classes.rb', line 247

def self.integer_to_prefix_length(mask, family = self::FAMILY)
  if valid_prefix_length?(mask)
    mask
  else
    NETMASK_TO_PREFIX_LENGTH[family][mask] ||
      (raise ArgumentError, "Can't convert #{mask} to prefix length")
  end
end

.ipaddr_to_prefix_length(mask, family = self::FAMILY) ⇒ Integer

Convert a netmask represented as an IPAddr to a prefix length.

Returns nil if the IPAddr can’t be converted.

Parameters:

Returns:

  • (Integer)


262
263
264
# File 'lib/better_ipaddr/classes.rb', line 262

def self.ipaddr_to_prefix_length(mask, family = self::FAMILY)
  NETMASK_TO_PREFIX_LENGTH[family][mask.to_i]
end

.object_to_prefix_length(mask, family = self::FAMILY) ⇒ Integer

Convert an object to a prefix length.

Parameters:

  • mask (Integer, String)
  • family (Integer, Nil) (defaults to: self::FAMILY)

Returns:

  • (Integer)


224
225
226
227
228
229
230
231
232
233
234
235
# File 'lib/better_ipaddr/classes.rb', line 224

def self.object_to_prefix_length(mask, family = self::FAMILY)
  case mask
  when Integer
    integer_to_prefix_length(mask, family)
  when String
    string_to_prefix_length(mask, family)
  when IPAddr
    ipaddr_to_prefix_length(mask, family)
  else
    raise ArgumentError, "Can't convert #{mask.class} to prefix length"
  end
end

.parse(address) ⇒ IPAddr::V4, ...

Convert the given string to an IPAddr subclass.

Parameters:

  • address (String)

    the string to convert

Returns:



295
296
297
# File 'lib/better_ipaddr/classes.rb', line 295

def self.parse(address)
  specialize IPAddr.new(address)
end

.specialize(address) ⇒ IPAddr::V4, ...

Return the given address as an instance of a class specific to its address family.

Parameters:

  • address (IPAddr)

    the address to convert

Returns:



304
305
306
307
308
309
310
311
312
313
314
# File 'lib/better_ipaddr/classes.rb', line 304

def self.specialize(address)
  return address unless address.class == IPAddr
  case address.family
  when Family::IPV4
    IPAddr::V4[address.to_i, address.instance_variable_get(:@mask_addr)]
  when Family::IPV6
    IPAddr::V6[address.to_i, address.instance_variable_get(:@mask_addr)]
  when Family::EUI48
    IPAddr::MAC[address.to_i, address.instance_variable_get(:@mask_addr)]
  end
end

.specialize_constants(family) ⇒ Object



316
317
318
319
320
321
322
323
324
325
326
# File 'lib/better_ipaddr/classes.rb', line 316

def self.specialize_constants(family)
  const_set(:FAMILY, family)
  const_set(:BIT_LENGTH, FAMILY_TO_BIT_LENGTH.fetch(self::FAMILY))
  const_set(:NETMASK_TO_PREFIX_LENGTH,
            NETMASK_TO_PREFIX_LENGTH.fetch(self::FAMILY))
  const_set(:PREFIX_LENGTH_TO_NETMASK,
            PREFIX_LENGTH_TO_NETMASK.fetch(self::FAMILY))
  const_set(:MAX_INT, 2**self::BIT_LENGTH - 1)
  const_set(:HOST_NETMASK,
            self::PREFIX_LENGTH_TO_NETMASK.fetch(self::BIT_LENGTH))
end

.string_to_prefix_length(mask, family = self::FAMILY) ⇒ Integer

Convert a string to a prefix length.

Accepts the decimal representations of integers as well as netmasks in dotted quad notation.

Returns nil if the string can’t be converted.

Parameters:

  • mask (String)

Returns:

  • (Integer)


275
276
277
278
279
280
281
# File 'lib/better_ipaddr/classes.rb', line 275

def self.string_to_prefix_length(mask, family = self::FAMILY)
  if mask =~ /^\d+$/
    integer_to_prefix_length(mask.to_i, family)
  else
    NETMASK_TO_PREFIX_LENGTH[family][new(mask).to_i]
  end
end

.valid_prefix_length?(prefix_length, family: self::FAMILY) ⇒ Boolean

Return true if the given number is a valid prefix length, false otherwise.

Parameters:

  • prefix_length (Integer)

Returns:

  • (Boolean)


287
288
289
# File 'lib/better_ipaddr/classes.rb', line 287

def self.valid_prefix_length?(prefix_length, family: self::FAMILY)
  0 <= prefix_length && prefix_length <= FAMILY_TO_BIT_LENGTH[family]
end

Instance Method Details

#address_family_bit_lengthObject



328
329
330
# File 'lib/better_ipaddr/classes.rb', line 328

def address_family_bit_length
  self.class::BIT_LENGTH
end

#network?Boolean

Returns:

  • (Boolean)


332
333
334
# File 'lib/better_ipaddr/classes.rb', line 332

def network?
  prefix_length < self.class::BIT_LENGTH
end

#prefix_lengthObject



336
337
338
# File 'lib/better_ipaddr/classes.rb', line 336

def prefix_length
  self.class::NETMASK_TO_PREFIX_LENGTH[mask_addr]
end

#to_s(cidr: false, full: false) ⇒ Object



340
341
342
# File 'lib/better_ipaddr/classes.rb', line 340

def to_s(cidr: false, full: false)
  better_to_s(cidr: cidr, full: full)
end