<?php
/**
 * Réécriture d'IP « conserver l'hôte, changer le réseau ».
 * Toute l'arithmétique en entiers non signés 32 bits.
 */
class SubnetRemap
{
    /**
     * Transpose la partie hôte de $ip du réseau source vers le réseau cible.
     *
     * @param string $ip        IP à transposer (doit appartenir au réseau source)
     * @param int    $srcPrefix préfixe source (0-32)
     * @param int    $dstNet    entier réseau cible (non signé)
     * @param int    $dstPrefix préfixe cible (0-32)
     * @return string|null  null si l'hôte déborde le masque cible
     */
    public static function remapIp(string $ip, int $srcPrefix, int $dstNet, int $dstPrefix): ?string
    {
        $ipInt = (int)sprintf('%u', ip2long($ip));

        $srcMask = $srcPrefix <= 0 ? 0 : (0xFFFFFFFF << (32 - $srcPrefix)) & 0xFFFFFFFF;
        $host    = $ipInt & (~$srcMask & 0xFFFFFFFF);

        $dstMask = $dstPrefix <= 0 ? 0 : (0xFFFFFFFF << (32 - $dstPrefix)) & 0xFFFFFFFF;
        $maxHost = ~$dstMask & 0xFFFFFFFF;
        if ($host > $maxHost) {
            return null; // l'hôte ne rentre pas dans le masque cible
        }

        $result = ($dstNet & $dstMask) | $host;
        return long2ip($result);
    }
}
