protected function prepareLengthFromStop(int $stop, int $offset, int $total): int
    {
        $remainder = $total - $offset;

        if ($stop === 0) {
            return $remainder;
        }

        if ($stop > 0) {
            $length = $stop - $offset;
        } else {
            $length = ($total + $stop) - $offset;
        }

        if ($length < 0) {
            $message = sprintf('Stop (%d) out of range[%d, %d]', $stop, -$remainder, $total - 1);
            throw new DomainException($message);
        }

        if ($length > $remainder) {
            return $remainder;
        }

        return $length;
    }