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;
}
}
[NullableContext(1)]
public BufferWriterInterpolatedStringHandler(int literalLength, int formattedCount, IBufferWriter<char> buffer, [Nullable(2)] IFormatProvider provider = null)
{
count = 0;
if (buffer == null)
throw new ArgumentNullException("buffer");
this.buffer = buffer;
this.provider = provider;
buffer.GetSpan(formattedCount * 10 + literalLength);
}
[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) {
Span<char> span = buffer.GetSpan(0);
while (!value.TryFormat(span, ref result, (ReadOnlySpan<char>)format, provider)) {
int length = span.Length;
if (length > 1073741823)
throw new InsufficientMemoryException();
length <<= 1;
span = buffer.GetSpan(length);
}
buffer.Advance(result);
return result;
}
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;
}
[NullableContext(2)]
public void AppendFormatted<T>([Nullable(1)] T value, string format = null)
{
count += AppendFormatted(buffer, value, format, provider);
}
public void AppendFormatted([ScopedRef] ReadOnlySpan<char> value)
{
buffer.Write(value);
count += value.Length;
}
private void AppendFormatted([ScopedRef] ReadOnlySpan<char> value, int alignment, bool leftAlign)
{
int num = alignment - value.Length;
if (num <= 0)
AppendFormatted(value);
else {
Span<char> rest = buffer.GetSpan(alignment);
(leftAlign ? rest.Slice(value.Length, num) : rest.TrimLength(num, out rest)).Fill(' ');
value.CopyTo(rest);
buffer.Advance(alignment);
count += alignment;
}
}
public void AppendFormatted([ScopedRef] ReadOnlySpan<char> value, int alignment)
{
bool leftAlign;
if (leftAlign = (alignment < 0))
alignment = -alignment;
AppendFormatted(value, alignment, leftAlign);
}
[NullableContext(2)]
public void AppendFormatted<T>([Nullable(1)] T value, int alignment, string format = null)
{
bool flag;
if (flag = (alignment < 0))
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.TrimLength(num3, out Span<char> rest);
span.Slice(0, num2).CopyTo(rest);
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);
}
}
}