DotNext by .NET Foundation and Contributors

<PackageReference Include="DotNext" Version="4.12.4" />

 PoolingInterpolatedStringHandler

Represents interpolated string builder that utilizes reusable buffer rented from the pool.
using DotNext.Runtime.CompilerServices; using System; using System.ComponentModel; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Threading; using System.Threading.Tasks; namespace DotNext.Buffers { [StructLayout(LayoutKind.Auto)] [InterpolatedStringHandler] [EditorBrowsable(EditorBrowsableState.Never)] public struct PoolingInterpolatedStringHandler : IGrowableBuffer<char>, IReadOnlySpanConsumer<char>, ISupplier<ReadOnlyMemory<char>, CancellationToken, ValueTask>, IFunctional<Func<ReadOnlyMemory<char>, CancellationToken, ValueTask>>, IDisposable, IResettable { private const int MaxBufferSize = 1073741823; private const char Whitespace = ' '; private readonly MemoryAllocator<char> allocator; private readonly IFormatProvider provider; private MemoryOwner<char> buffer; private int count; long IGrowableBuffer<char>.WrittenCount { [IsReadOnly] get { return count; } } private ReadOnlyMemory<char> WrittenMemory { [IsReadOnly] get { if (count <= 0) return ReadOnlyMemory<char>.Empty; return buffer.Memory.Slice(0, count); } } [System.Runtime.CompilerServices.NullableContext(2)] public PoolingInterpolatedStringHandler(int literalLength, int formattedCount, MemoryAllocator<char> allocator, IFormatProvider provider = null) { int num = 10 * formattedCount + literalLength; if ((uint)num > (uint)Array.get_MaxLength()) throw new InsufficientMemoryException(); buffer = allocator.Invoke(num, false); this.allocator = allocator; this.provider = provider; count = 0; } void IGrowableBuffer<char>.Write(ReadOnlySpan<char> value) { AppendFormatted(value); } void IReadOnlySpanConsumer<char>.Invoke(ReadOnlySpan<char> value) { AppendFormatted(value); } void IGrowableBuffer<char>.Write(char value) { AppendFormatted(MemoryMarshal.CreateReadOnlySpan(ref value, 1)); } [IsReadOnly] void IGrowableBuffer<char>.CopyTo<TConsumer>(TConsumer consumer) { ((IReadOnlySpanConsumer<char>)consumer).Invoke(WrittenMemory.Span); } [IsReadOnly] ValueTask IGrowableBuffer<char>.CopyToAsync<TConsumer>(TConsumer consumer, CancellationToken token) { return ((ISupplier<ReadOnlyMemory<char>, CancellationToken, ValueTask>)consumer).Invoke(WrittenMemory, token); } [IsReadOnly] int IGrowableBuffer<char>.CopyTo(Span<char> output) { WrittenMemory.Span.CopyTo(output, out int writtenCount); return writtenCount; } void IGrowableBuffer<char>.Clear() { buffer.Dispose(); count = 0; } [IsReadOnly] bool IGrowableBuffer<char>.TryGetWrittenContent(out ReadOnlyMemory<char> block) { block = WrittenMemory; return true; } internal MemoryOwner<char> DetachBuffer() { MemoryOwner<char> result; if (count == 0) result = default(MemoryOwner<char>); else { result = buffer; result.Truncate(count); count = 0; buffer = default(MemoryOwner<char>); } return result; } private Span<char> GetSpan(int sizeHint) { int sizeHint2 = sizeHint; int length = buffer.Length; int writtenCount = count; if (((IGrowableBuffer<char>)).GetBufferSize(sizeHint2, length, writtenCount, out sizeHint)) ref buffer.Resize(sizeHint, false, allocator); return buffer.Span.Slice(count); } [System.Runtime.CompilerServices.NullableContext(2)] public void AppendLiteral(string value) { AppendFormatted(value.AsSpan()); } [System.Runtime.CompilerServices.NullableContext(2)] public void AppendFormatted<T>([System.Runtime.CompilerServices.Nullable(1)] T value, string format = null) { if (!(((object)value) is ISpanFormattable)) { if (!(((object)value) is IFormattable)) { if (value != null) AppendLiteral(value.ToString()); } else AppendLiteral(((IFormattable)(object)value).ToString(format, provider)); } else { int num = 0; int num2 = default(int); while (true) { Span<char> span = GetSpan(num); if (value.TryFormat(span, ref num2, (ReadOnlySpan<char>)format, provider)) break; if (num > 1073741823) throw new InsufficientMemoryException(); num <<= 1; } count += num2; } } private void AppendFormatted(ReadOnlySpan<char> value, int alignment, bool leftAlign) { int num = alignment - value.Length; if (num <= 0) AppendFormatted(value); else { Span<char> span = GetSpan(alignment); Span<char> span2; if (leftAlign) { span2 = span.Slice(value.Length, num); span2.Fill(' '); value.CopyTo(span); } else { span2 = span.Slice(0, num); span2.Fill(' '); value.CopyTo(span.Slice(num)); } count += alignment; } } public void AppendFormatted(ReadOnlySpan<char> value, int alignment) { bool leftAlign = false; if (alignment < 0) { leftAlign = true; alignment = -alignment; } AppendFormatted(value, alignment, leftAlign); } [System.Runtime.CompilerServices.NullableContext(2)] public void AppendFormatted<T>([System.Runtime.CompilerServices.Nullable(1)] T value, int alignment, string format = null) { bool flag = false; if (alignment < 0) { flag = true; alignment = -alignment; } if (((object)value) is ISpanFormattable) { int num = alignment; while (true) { Span<char> span = GetSpan(num); int num2 = default(int); if (value.TryFormat(span, ref num2, (ReadOnlySpan<char>)format, provider)) { int num3 = alignment - num2; Span<char> span2; if (num3 <= 0) alignment = num2; else if (flag) { span2 = span.Slice(num2, num3); span2.Fill(' '); } else { span2 = span.Slice(0, num2); span2.CopyTo(span.Slice(num3)); span2 = span.Slice(0, num3); span2.Fill(' '); } count += alignment; return; } if (num > 1073741823) break; num <<= 1; } throw new InsufficientMemoryException(); } if (!(((object)value) is IFormattable)) { if (value != null) AppendFormatted(value.ToString().AsSpan(), alignment, flag); } else AppendFormatted(((IFormattable)(object)value).ToString(format, provider).AsSpan(), alignment, flag); } public void AppendFormatted(ReadOnlySpan<char> value) { value.CopyTo(GetSpan(value.Length)); count += value.Length; } [IsReadOnly] [System.Runtime.CompilerServices.NullableContext(1)] public override string ToString() { return WrittenMemory.ToString(); } public void Dispose() { buffer.Dispose(); this = default(PoolingInterpolatedStringHandler); } } }