Skip to content

Commit

Permalink
Add Utf8.TryWrite (#83852)
Browse files Browse the repository at this point in the history
* Add Utf8.TryWrite

Initial implementation of Utf8.TryWriteUtf8. The performance of this won't be great at present, but will improve as our cores types add implementation of IUtf8SpanFormattable. For tests, I copy/pasted the tests we had for MemoryExtensions.TryWrite and searched/replaced to make them work for Utf8.TryWrite.

* Address PR feedback
  • Loading branch information
stephentoub authored Apr 6, 2023
1 parent cc01464 commit 2c8cb12
Show file tree
Hide file tree
Showing 7 changed files with 1,286 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -517,6 +517,7 @@
<Compile Include="$(MSBuildThisFileDirectory)System\IObserver.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\IProgress.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\ISpanFormattable.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\IUtf8SpanFormattable.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Lazy.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\LazyOfTTMetadata.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\LoaderOptimization.cs" />
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

namespace System
{
/// <summary>Provides functionality to format the string representation of an object into a span as UTF8.</summary>
public interface IUtf8SpanFormattable
{
/// <summary>Tries to format the value of the current instance as UTF8 into the provided span of bytes.</summary>
/// <param name="destination">When this method returns, this instance's value formatted as a span of bytes.</param>
/// <param name="bytesWritten">When this method returns, the number of bytes that were written in <paramref name="destination"/>.</param>
/// <param name="format">A span containing the characters that represent a standard or custom format string that defines the acceptable format for <paramref name="destination"/>.</param>
/// <param name="provider">An optional object that supplies culture-specific formatting information for <paramref name="destination"/>.</param>
/// <returns><see langword="true"/> if the formatting was successful; otherwise, <see langword="false"/>.</returns>
/// <remarks>
/// An implementation of this interface should produce the same string of characters as an implementation of <see cref="IFormattable.ToString"/> or <see cref="ISpanFormattable.TryFormat"/>
/// on the same type. TryFormat should return false only if there is not enough space in the destination buffer; any other failures should throw an exception.
/// </remarks>
bool TryFormat(Span<byte> destination, out int bytesWritten, ReadOnlySpan<char> format, IFormatProvider? provider);
}
}
418 changes: 418 additions & 0 deletions src/libraries/System.Private.CoreLib/src/System/Text/Unicode/Utf8.cs

Large diffs are not rendered by default.

27 changes: 27 additions & 0 deletions src/libraries/System.Runtime/ref/System.Runtime.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3865,6 +3865,10 @@ public partial interface ISpanParsable<TSelf> : System.IParsable<TSelf> where TS
static abstract TSelf Parse(System.ReadOnlySpan<char> s, System.IFormatProvider? provider);
static abstract bool TryParse(System.ReadOnlySpan<char> s, System.IFormatProvider? provider, [System.Diagnostics.CodeAnalysis.MaybeNullWhenAttribute(false)] out TSelf result);
}
public partial interface IUtf8SpanFormattable
{
bool TryFormat(System.Span<byte> destination, out int bytesWritten, System.ReadOnlySpan<char> format, System.IFormatProvider? provider);
}
public partial class Lazy<[System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)]T>
{
public Lazy() { }
Expand Down Expand Up @@ -14437,6 +14441,29 @@ public static partial class Utf8
{
public static System.Buffers.OperationStatus FromUtf16(System.ReadOnlySpan<char> source, System.Span<byte> destination, out int charsRead, out int bytesWritten, bool replaceInvalidSequences = true, bool isFinalBlock = true) { throw null; }
public static System.Buffers.OperationStatus ToUtf16(System.ReadOnlySpan<byte> source, System.Span<char> destination, out int bytesRead, out int charsWritten, bool replaceInvalidSequences = true, bool isFinalBlock = true) { throw null; }
public static bool TryWrite(System.Span<byte> destination, [System.Runtime.CompilerServices.InterpolatedStringHandlerArgumentAttribute("destination")] ref System.Text.Unicode.Utf8.TryWriteInterpolatedStringHandler handler, out int bytesWritten) { throw null; }
public static bool TryWrite(System.Span<byte> destination, IFormatProvider? provider, [System.Runtime.CompilerServices.InterpolatedStringHandlerArgumentAttribute("destination", "provider")] ref System.Text.Unicode.Utf8.TryWriteInterpolatedStringHandler handler, out int bytesWritten) { throw null; }
[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
[System.Runtime.CompilerServices.InterpolatedStringHandlerAttribute]
public ref struct TryWriteInterpolatedStringHandler
{
private readonly object _dummy;
private readonly int _dummyPrimitive;
public TryWriteInterpolatedStringHandler(int literalLength, int formattedCount, System.Span<byte> destination, out bool shouldAppend) { throw null; }
public TryWriteInterpolatedStringHandler(int literalLength, int formattedCount, System.Span<byte> destination, IFormatProvider? provider, out bool shouldAppend) { throw null; }
public bool AppendLiteral(string value) { throw null; }
public bool AppendFormatted(scoped System.ReadOnlySpan<char> value) { throw null; }
public bool AppendFormatted(scoped System.ReadOnlySpan<char> value, int alignment = 0, string? format = null) { throw null; }
public bool AppendFormatted(scoped System.ReadOnlySpan<byte> utf8Value) { throw null; }
public bool AppendFormatted(scoped System.ReadOnlySpan<byte> utf8Value, int alignment = 0, string? format = null) { throw null; }
public bool AppendFormatted<T>(T value) { throw null; }
public bool AppendFormatted<T>(T value, string? format) { throw null; }
public bool AppendFormatted<T>(T value, int alignment) { throw null; }
public bool AppendFormatted<T>(T value, int alignment, string? format) { throw null; }
public bool AppendFormatted(object? value, int alignment = 0, string? format = null) { throw null; }
public bool AppendFormatted(string? value) { throw null; }
public bool AppendFormatted(string? value, int alignment = 0, string? format = null) { throw null; }
}
}
}
namespace System.Threading
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,7 @@
<Compile Include="System\Text\RuneTests.TestData.cs" />
<Compile Include="System\Text\Unicode\Utf16UtilityTests.ValidateChars.cs" />
<Compile Include="System\Text\Unicode\Utf8Tests.cs" />
<Compile Include="System\Text\Unicode\Utf8Tests.TryWrite.cs" />
<Compile Include="System\Text\Unicode\Utf8UtilityTests.ValidateBytes.cs" />
<Compile Include="System\ArgIteratorTests.cs" />
<Compile Include="$(CommonPath)..\tests\System\RealFormatterTestsBase.cs" Link="System\RealFormatterTestsBase.cs" />
Expand Down
Loading

0 comments on commit 2c8cb12

Please sign in to comment.