<?php namespace App\Services;
class IpMatcher
{
    public function matches(string $ip, string $rule): bool
    {
        if (!str_contains($rule, '/')) return $ip === $rule;
        [$subnet,$bits]=explode('/',$rule,2); $bits=(int)$bits;
        $ipBin=@inet_pton($ip); $subnetBin=@inet_pton($subnet);
        if($ipBin===false || $subnetBin===false || strlen($ipBin)!==strlen($subnetBin)) return false;
        $max=strlen($ipBin)*8; if($bits<0 || $bits>$max) return false;
        $bytes=intdiv($bits,8); $rem=$bits%8;
        if($bytes && substr($ipBin,0,$bytes)!==substr($subnetBin,0,$bytes)) return false;
        if($rem===0) return true;
        $mask=(0xFF << (8-$rem)) & 0xFF;
        return (ord($ipBin[$bytes]) & $mask)===(ord($subnetBin[$bytes]) & $mask);
    }
}
