-
Notifications
You must be signed in to change notification settings - Fork 4.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[API Proposal]: MemoryExtensions.TryWrite for UTF8 #79376
Comments
Tagging subscribers to this area: @dotnet/area-system-buffers Issue DetailsBackground and motivationIn .NET 6, as part of rolling out the improved support for string interpolation, we added some TryWrite extension methods to MemoryExtensions that enable interpolating directly into a Span<char> span = ...;
bool wrote = span.TryWrite($"The current day/time is {DateTime.Now}", out int charsWritten); We should consider enabling the same capability for writing UTF8 into a API Proposalnamespace System.Buffers.Text
{
public static partial class Utf8Formatter
{
public static bool TryWrite(this Span<byte> destination, [InterpolatedStringHandlerArgument("destination")] ref TryWriteInterpolatedStringHandler handler, out int bytesWritten);
public static bool TryWrite(this Span<byte> destination, IFormatProvider? provider, [InterpolatedStringHandlerArgument("destination", "provider")] ref TryWriteInterpolatedStringHandler handler, out int bytesWritten);
[EditorBrowsable(EditorBrowsableState.Never)]
[InterpolatedStringHandlerAttribute]
public ref struct TryWriteInterpolatedStringHandler
{
public TryWriteInterpolatedStringHandler(int literalLength, int formattedCount, Span<byte> destination, out bool shouldAppend);
public TryWriteInterpolatedStringHandler(int literalLength, int formattedCount, Span<byte> destination, IFormatProvider? provider, out bool shouldAppend);
public bool AppendLiteral(string value);
public bool AppendFormatted(scoped ReadOnlySpan<char> value);
public bool AppendFormatted(scoped ReadOnlySpan<char> value, int alignment = 0, string? format = null);
public bool AppendFormatted(scoped ReadOnlySpan<byte> value);
public bool AppendFormatted(scoped ReadOnlySpan<byte> value, int alignment = 0, string? format = null);
public bool AppendFormatted<T>(T value);
public bool AppendFormatted<T>(T value, string? format);
public bool AppendFormatted<T>(T value, int alignment);
public bool AppendFormatted<T>(T value, int alignment, string? format);
public bool AppendFormatted(object? value, int alignment = 0, string? format = null);
public bool AppendFormatted(string? value) { throw null; }
public bool AppendFormatted(string? value, int alignment = 0, string? format = null);
}
} This is essentially the exact same design as for
Also note that the API UsageSpan<byte> span = ...;
bool wrote = span.TryWrite($"The current day/time is {DateTime.Now}", out int bytesWritten); Alternative DesignsNo response RisksNo response
|
cc: @333fred for string interpolation |
Love it! |
@stephentoub was there a specific thing you wanted me to comment on, or just awareness? |
Just awareness. |
namespace System;
public static partial class MemoryExtensions
{
public static bool TryWriteUtf8(this Span<byte> destination, [InterpolatedStringHandlerArgument("destination")] ref TryWriteUtf8InterpolatedStringHandler handler, out int bytesWritten);
public static bool TryWriteUtf8(this Span<byte> destination, IFormatProvider? provider, [InterpolatedStringHandlerArgument("destination", "provider")] ref TryWriteUtf8InterpolatedStringHandler handler, out int bytesWritten);
[EditorBrowsable(EditorBrowsableState.Never)]
[InterpolatedStringHandlerAttribute]
public ref struct TryWriteUtf8InterpolatedStringHandler
{
public TryWriteInterpolatedStringHandler(int literalLength, int formattedCount, Span<byte> utf8Destination, out bool shouldAppend);
public TryWriteInterpolatedStringHandler(int literalLength, int formattedCount, Span<byte> utf8Destination, IFormatProvider? provider, out bool shouldAppend);
public bool AppendLiteral(string value);
// public bool AppendLiteral(ReadOnlySpan<byte> value); // if the C# compiler supports interpolation with u8 literals
public bool AppendFormatted(scoped ReadOnlySpan<char> value);
public bool AppendFormatted(scoped ReadOnlySpan<char> value, int alignment = 0, string? format = null);
public bool AppendFormatted(scoped ReadOnlySpan<byte> utf8Value);
public bool AppendFormatted(scoped ReadOnlySpan<byte> utf8Value, int alignment = 0, string? format = null);
public bool AppendFormatted<T>(T value);
public bool AppendFormatted<T>(T value, string? format);
public bool AppendFormatted<T>(T value, int alignment);
public bool AppendFormatted<T>(T value, int alignment, string? format);
public bool AppendFormatted(object? value, int alignment = 0, string? format = null);
public bool AppendFormatted(string? value);
public bool AppendFormatted(string? value, int alignment = 0, string? format = null);
}
} |
namespace System.Text.Unicode;
public static partial class Utf8
{
public static bool TryWrite(Span<byte> destination, [InterpolatedStringHandlerArgument("destination")] ref TryWriteUtf8InterpolatedStringHandler handler, out int bytesWritten);
public static bool TryWrite(Span<byte> destination, IFormatProvider? provider, [InterpolatedStringHandlerArgument("destination", "provider")] ref TryWriteUtf8InterpolatedStringHandler handler, out int bytesWritten);
[EditorBrowsable(EditorBrowsableState.Never)]
[InterpolatedStringHandlerAttribute]
public ref struct TryWriteInterpolatedStringHandler
{
public TryWriteInterpolatedStringHandler(int literalLength, int formattedCount, Span<byte> utf8Destination, out bool shouldAppend);
public TryWriteInterpolatedStringHandler(int literalLength, int formattedCount, Span<byte> utf8Destination, IFormatProvider? provider, out bool shouldAppend);
public bool AppendLiteral(string value);
// public bool AppendLiteral(ReadOnlySpan<byte> value); // if the C# compiler supports interpolation with u8 literals
public bool AppendFormatted(scoped ReadOnlySpan<char> value);
public bool AppendFormatted(scoped ReadOnlySpan<char> value, int alignment = 0, string? format = null);
public bool AppendFormatted(scoped ReadOnlySpan<byte> utf8Value);
public bool AppendFormatted(scoped ReadOnlySpan<byte> utf8Value, int alignment = 0, string? format = null);
public bool AppendFormatted<T>(T value);
public bool AppendFormatted<T>(T value, string? format);
public bool AppendFormatted<T>(T value, int alignment);
public bool AppendFormatted<T>(T value, int alignment, string? format);
public bool AppendFormatted(object? value, int alignment = 0, string? format = null);
public bool AppendFormatted(string? value);
public bool AppendFormatted(string? value, int alignment = 0, string? format = null);
}
} |
Background and motivation
In .NET 6, as part of rolling out the improved support for string interpolation, we added some TryWrite extension methods to MemoryExtensions that enable interpolating directly into a
Span<char>
, e.g.We should consider enabling the same capability for writing UTF8 into a
Span<byte>
.API Proposal
This is essentially the exact same design as for
MemoryExtensions.TryWrite
, with a few specific differences:TryWrite
methods take aSpan<byte>
instead of aSpan<char>
.ReadOnlySpan<char>
-basedAppendFormatted
methods, there are alsoReadOnlySpan<byte>
-basedAppendFormatted
methods, the latter of which is expected to be UTF8 data, like a u8 literal. TheReadOnlySpan<byte>
data would be memcpy'd into the destination, whereas theReadOnlySpan<char>
data would beEncoding.UTF8
-encoded into the destination.Append<T>
will check forIUtf8SpanFormattable
before it checks forISpanFormattable
, prefering to use a type's built-in UTF8 formatting support if supplied.Also note that the
AppendLiteral
method takes astring value
, as that's what's supported by the C# language. If C# were to ever support u8 literals in string interpolation, we could add an appropriateAppendLiteral(ReadOnlySpan<byte> utf8Value)
overload.API Usage
Alternative Designs
No response
Risks
No response
The text was updated successfully, but these errors were encountered: