protected function prepareLength(int $length, int $offset, int $total): int
    {
        $remainder = $total - $offset;

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

        if ($length < 0) {
            if (($length + $remainder) < 0) {
                $message = sprintf('Length (%d) out of range[%d, %d]', $length, -$remainder, $remainder);
                throw new DomainException($message);
            }
            $length += $remainder;
        } else {
            if (($offset + $length) > $total) {
                return $remainder;
            }
        }

        return $length;
    }