using System.Runtime.CompilerServices;
namespace T3.Editor.Gui.Styling;
///
/// Supports helper for allocation free string interpolation.
///
/// For rendering flexible string content with ImGui generating new string causes a lot of GC
/// allocations. This class provides some helpers to optimized the most common usecases.
///
public static class SpanFormat
{
///
/// Formats an interpolated string directly into a stack-allocated buffer to avoid heap allocations.
///
/// The destination span, typically created via .
/// An internal handler that performs the zero-allocation formatting logic.
/// A view into the portion of the buffer containing the formatted characters.
///
/// This is intended for high-performance UI loops where generating temporary strings would cause GC pressure.
///
///
///
/// Span<char> buffer = stackalloc char[32];
/// var label = buffer.Format($"{count} Items##{id}\0");
/// ImGui.TextUnformatted(label);
///
///
public static ReadOnlySpan Format(this Span buffer,
[InterpolatedStringHandlerArgument("buffer")]
TryWriteHandler handler)
{
return buffer[..handler.CharsWritten];
}
// This simple handler tells the compiler how to use TryWrite under the hood
[InterpolatedStringHandler]
public ref struct TryWriteHandler
{
private readonly Span _destination;
public int CharsWritten { get; private set; }
public TryWriteHandler(int literalLength, int holeCount, Span destination)
{
_destination = destination;
CharsWritten = 0;
}
public bool AppendLiteral(string value)
{
if (value.AsSpan().TryCopyTo(_destination[CharsWritten..]))
{
CharsWritten += value.Length;
return true;
}
return false;
}
public bool AppendFormatted(T value)
{
// Optimized path for numbers and other formattable types
if (value is ISpanFormattable formattable)
{
if (formattable.TryFormat(_destination[CharsWritten..], out int written, default, default))
{
CharsWritten += written;
return true;
}
}
// Fallback for strings or other types
var s = value?.ToString();
if (s != null && s.AsSpan().TryCopyTo(_destination[CharsWritten..]))
{
CharsWritten += s.Length;
return true;
}
return false;
}
}
}