-- luaxform: Convert IPv4 + hex/netmask to CIDR
-- Example: input="192.168.1.45", arg="0xffffff00" → "192.168.1.0/24"

-- Trim leading/trailing whitespace
local function trim(s)
    return s:match("^%s*(.-)%s*$")
end

-- Parse a mask string (hex format like 0xffffff00)
local function parse_mask(mask_hex)
    if not mask_hex then return nil end
    mask_hex = trim(mask_hex)
    -- Remove optional 0x/0X prefix
    local hex = mask_hex:match("^0[xX](%x+)$") or mask_hex
    local num = tonumber(hex, 16)
    return num
end

-- Count the number of 1 bits in a 32-bit number
local function count_bits(n)
    local count = 0
    for i = 0, 31 do
        if (n & (1 << i)) ~= 0 then count = count + 1 end
    end
    return count
end

-- Convert a 4-byte host-order IPv4 address and a mask to CIDR
local function ip_to_cidr(ip_bytes, mask_hex)
    if not ip_bytes or #ip_bytes ~= 4 then return nil end

    -- Parse the mask
    local mask = parse_mask(mask_hex)
    if not mask then return nil end

    -- Convert host-order bytes to IP number
    local a, b, c, d = string.byte(ip_bytes, 1, 4)
    local ip = (a << 24) | (b << 16) | (c << 8) | d

    -- Compute network
    local net = ip & mask

    -- Count prefix length
    local bits = count_bits(mask)

    -- Convert back to dotted-decimal
    return string.format("%d.%d.%d.%d/%d",
        (net >> 24) & 0xFF,
        (net >> 16) & 0xFF,
        (net >> 8) & 0xFF,
        net & 0xFF,
        bits
    )
end

-- Transform an IPv4 address and a netmask into a CIDR
-- example: 1.2.3.4 0xffffff00 returns 1.2.3.0/24
function transform(input, args)
    if not input or not args or not args[1] then
        return nil, 0
    end

    local cidr = ip_to_cidr(input, args[1])
    if not cidr then return nil, 0 end

    return cidr, #cidr
end
