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; } } }