protected function valueToString($value): string
    {
        if ($value === false) {
            return 'false';
        }
        if ($value === true) {
            return 'true';
        }
        if ($value === null) {
            return 'null';
        }
        if (is_string($value)) {
            if (call_user_func(function_exists('mb_strlen') ? 'mb_strlen' : 'strlen', $value) > 100) {
                $value = call_user_func(function_exists('mb_substr') ? 'mb_substr' : 'substr', $value, 0, 97).'...';
            }
            return '"'.$value.'"';
        }
        if (is_object($value)) {
            return 'a '.get_class($value).' instance';
        }
        if (is_array($value)) {
            $keys = array_keys($value);
            $isAssociative = $keys !== array_keys($keys);
            $valuesStrings = [];

            foreach ($value as $key => $subValue) {
                $valuesStrings[] = ($isAssociative ? $this->valueToString($key).' => ' : '')
                    . $this->valueToString($subValue);
            }

            return '['.implode(', ', $valuesStrings).']';
        }
        if (is_resource($value)) {
            return 'a resource';
        }
        return (string)$value;
    }