BufferWriterInterpolatedStringHandler
Represents handler of the interpolated string
that can be written to IBufferWriter<T> without temporary allocations.
using System;
using System.Buffers;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
namespace DotNext.Buffers
{
[StructLayout(LayoutKind.Auto)]
[InterpolatedStringHandler]
[EditorBrowsable(EditorBrowsableState.Never)]
public struct BufferWriterInterpolatedStringHandler
{
private const int MaxBufferSize = 1073741823;
private const char Whitespace = ' ';
private readonly IBufferWriter<char> buffer;
private readonly IFormatProvider provider;
private int count;
public int WrittenCount {
[IsReadOnly]
get {
return count;
}
}
[System.Runtime.CompilerServices.NullableContext(1)]
public BufferWriterInterpolatedStringHandler(int literalLength, int formattedCount, IBufferWriter<char> buffer, [System.Runtime.CompilerServices.Nullable(2)] IFormatProvider provider = null)
{
if (buffer == null)
throw new ArgumentNullException("buffer");
this.buffer = buffer;
this.provider = provider;
buffer.GetSpan(formattedCount * 10 + literalLength);
count = 0;
}
[System.Runtime.CompilerServices.NullableContext(2)]
public void AppendLiteral(string value)
{
AppendFormatted(value.AsSpan());
}
internal static int AppendFormatted<T>(IBufferWriter<char> buffer, T value, string format, IFormatProvider provider)
{
int result = default(int);
if (((object)value) is ISpanFormattable) {
int num = 0;
while (true) {
Span<char> span = buffer.GetSpan(num);
if (value.TryFormat(span, ref result, (ReadOnlySpan<char>)format, provider)) {
buffer.Advance(result);
return result;
}
if (num > 1073741823)
break;
num <<= 1;
}
throw new InsufficientMemoryException();
}
if (((object)value) is IFormattable) {
result = <AppendFormatted>g__Write|9_0<T>(buffer, ((IFormattable)(object)value).ToString(format, provider));
return result;
}
if (value == null) {
result = 0;
return result;
}
result = <AppendFormatted>g__Write|9_0<T>(buffer, value.ToString());
return result;
}
[System.Runtime.CompilerServices.NullableContext(2)]
public void AppendFormatted<T>([System.Runtime.CompilerServices.Nullable(1)] T value, string format = null)
{
count += AppendFormatted(buffer, value, format, provider);
}
public void AppendFormatted([LifetimeAnnotation(false, true)] ReadOnlySpan<char> value)
{
buffer.Write(value);
count += value.Length;
}
private void AppendFormatted([LifetimeAnnotation(false, true)] ReadOnlySpan<char> value, int alignment, bool leftAlign)
{
int num = alignment - value.Length;
if (num <= 0)
AppendFormatted(value);
else {
Span<char> span = buffer.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));
}
buffer.Advance(alignment);
count += alignment;
}
}
public void AppendFormatted([LifetimeAnnotation(false, true)] 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 = buffer.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(' ');
}
buffer.Advance(alignment);
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);
}
}
}