zhuhaow/NEKit

View on GitHub
src/Utils/IPMask.swift

Summary

Maintainability
B
5 hrs
Test Coverage
import Foundation

public enum IPMask {
    case IPv4(UInt32), IPv6(UInt128)

    func mask(baseIP: IPAddress) -> (IPAddress, IPAddress)? {
        switch (self, baseIP.address) {
        case (.IPv4(var m), .IPv4(let addr)):
            guard m <= 32 else {
                return nil
            }

            if m == 32 {
                return (baseIP, baseIP)
            }

            if m == 0 {
                return (IPAddress(ipv4InNetworkOrder: 0), IPAddress(ipv4InNetworkOrder: UInt32.max))
            }

            m = 32 - m
            let base = (addr.s_addr.byteSwapped >> m) << m
            let end = base | ~((UInt32.max >> m) << m)
            let b = IPAddress(ipv4InNetworkOrder: base.byteSwapped)
            let e = IPAddress(ipv4InNetworkOrder: end.byteSwapped)
            return (b, e)
        case (.IPv6(var m), .IPv6):
            guard m <= 128 else {
                return nil
            }

            if m == 128 {
                return (baseIP, baseIP)
            }

            if m == 0 {
                return (IPAddress(ipv6InNetworkOrder: 0), IPAddress(ipv6InNetworkOrder: UInt128.max))
            }

            m = 128 - m
            let base = (baseIP.address.asUInt128.byteSwapped >> m) << m
            let end = base | ~((UInt128.max >> m) << m)
            let b = IPAddress(ipv6InNetworkOrder: base.byteSwapped)
            let e = IPAddress(ipv6InNetworkOrder: end.byteSwapped)
            return (b, e)
        default:
            return nil
        }
    }
}