Ipaddress.rb

This content was produced by an LLM and could include errors.

このスクリプトはIPv4ユーティリティ集です。mask_to_cidr はマスクの1ビット数を数えてCIDRへ変換し(255.255.255.024)、cidr_to_mask は逆変換を行います。ip_address? は4オクテット・数値のみ・0〜255・先頭ゼロ禁止を検証し、subnet_mask? はビット列が「1の連続の後に0」となる形式か確認します。network_address? はホスト部ビットがすべて0かどうかでネットワークアドレスを判定します。

# frozen_string_literal: true
#=> nil

def mask_to_cidr(mask)
  # count num of 1.
  mask.split('.').sum { it.to_i.to_s(2).count('1') }
end
#=> :mask_to_cidr

p mask_to_cidr('255.255.255.0')
24
#=> 24

def cidr_to_mask(cidr)
  # Repeat '1' cidr times and then pad with '0's to make 32 bits.
  bits = '1' * cidr + '0' * (32 - cidr)
  # split into chunks of 8 characters.
  bits.scan(/.{8}/).map { it.to_i(2) }.join('.')
end
#=> :cidr_to_mask

p cidr_to_mask(24)
"255.255.255.0"
#=> "255.255.255.0"

def ip_address?(ip)
  parts = ip.split('.')
  return false unless parts.size == 4
  
  parts.all? do |p|
    return false unless p =~ /^\d+$/
    
    num = p.to_i
    return false if num.negative? || num > 255
    return false if p != num.to_s # 先頭ゼロ防止
    
    true
  end
end
#=> :ip_address?

p ip_address?('127.0.0.1')
true
#=> true

def subnet_mask?(mask)
  parts = mask.split('.')
  return false unless parts.size == 4
  
  binary = ''
  parts.each do |p|
    return false unless p =~ /^\d+$/
    
    num = p.to_i
    return false if num.negative? || num > 255
    
    binary += num.to_s(2).rjust(8, '0')
  end
  # 1の後に0が続く形式のみ許可
  return false if binary.include?('01')
  # 全0 or 全1は除外
  return false if binary == '0' * 32 || binary == '1' * 32
  
  true
end
#=> :subnet_mask?

p subnet_mask?('255.0.0.0')
true
#=> true

def network_address?(ip, mask)
  return false unless ip_address?(ip)
  return false unless subnet_mask?(mask)
  
  ip_parts   = ip.split('.').map(&:to_i)
  mask_parts = mask.split('.').map(&:to_i)
  
  4.times do |i|
    # ホスト部が0かチェック
    return false if (ip_parts[i] & (~mask_parts[i] & 0xFF)) != 0
  end
  
  true
end
#=> :network_address?
p network_address?('10.0.0.0', cidr_to_mask(16))
true
#=> true

Ruby 4.0.6