<?php


namespace Mainto\RpcServer\Util;

use Mainto\RpcServer\Util\Binary\BigEndian;
use Mainto\RpcServer\Util\Binary\LittleEndian;
use RuntimeException;

class Binary {
    /**
     * @var string|LittleEndian
     */
    public static string $littleEndian = LittleEndian::class;

    /**
     * @var string|BigEndian
     */
    public static string $bigEndian = BigEndian::class;

    /**
     * @param $dist
     * @param $start
     * @param $end
     * @param $src
     * @return int
     */
    public static function copy (string &$dist, int $start, int $end, string $src): int {
        $distLen = strlen($dist);
        if ($end === 0) {
            $end = $distLen;
        }

        $giveLen = $end - $start;
        if ($giveLen === 0) {
            return 0;
        }

        if ($end > $distLen) {
            throw new RuntimeException(sprintf("buff size offset: max [%d] and given [%d]", strlen($dist), $end));
        }

        if ($src === "") {
            $src = self::makeBytes($giveLen);
        }

        $replace = substr($src, 0, $giveLen);
        $replaceLen = strlen($replace);

        $dist = substr_replace($dist, $replace, $start, $giveLen > $replaceLen ? $replaceLen : $giveLen );

        return $replaceLen;
    }

    /**
     * @param int $size
     * @return string
     */
    public static function makeBytes (int $size): string {
        return str_repeat("\x00", $size);
    }

    public static function putUint8 (&$str, $start, int $int): void {
        $str = substr_replace($str, self::intToUint8($int), $start, 1);
    }

    public static function intToUint8 (int $int): string {
        return chr($int & 0xFF);
    }

    /**
     * @param string $str
     * @return int
     */
    public static function strToUint8 (string $str): int {
        return ord($str[0]);
    }
}