Skip to content

Commit

Permalink
Merge pull request #209 from SimonCropp/add-TextWriter-WriteAsync-and…
Browse files Browse the repository at this point in the history
…-Write-for-StringBuilder

add TextWriter WriteAsync and Write for StringBuilder
  • Loading branch information
SimonCropp authored Aug 20, 2024
2 parents 44de6a4 + 0055d1d commit 63223fd
Show file tree
Hide file tree
Showing 4 changed files with 142 additions and 3 deletions.
57 changes: 55 additions & 2 deletions contributing.md
Original file line number Diff line number Diff line change
Expand Up @@ -189,10 +189,12 @@ Example:
// <auto-generated />
#pragma warning disable

#if FeatureMemory && (NETFRAMEWORK || NETSTANDARD2_0 || NETCOREAPP2_0)
#if FeatureMemory

namespace Polyfills;

using System;
using System.Text;
using System.Buffers;
using System.IO;
using System.Runtime.InteropServices;
Expand All @@ -202,6 +204,56 @@ using System.Threading.Tasks;

static partial class Polyfill
{
#if !NETCOREAPP3_0_OR_GREATER
/// <summary>
/// Equivalent to Write(stringBuilder.ToString()) however it uses the
/// StringBuilder.GetChunks() method to avoid creating the intermediate string
/// </summary>
/// <param name="value">The string (as a StringBuilder) to write to the stream</param>
[Link("https://learn.microsoft.com/en-us/dotnet/api/system.io.textwriter.write#system-io-textwriter-write(system-text-stringbuilder)")]
public static void Write(this TextWriter target, StringBuilder? value)
{
if (value != null)
{
foreach (ReadOnlyMemory<char> chunk in value.GetChunks())
{
target.Write(chunk.Span);
}
}
}

/// <summary>
/// Equivalent to WriteAsync(stringBuilder.ToString()) however it uses the
/// StringBuilder.GetChunks() method to avoid creating the intermediate string
/// </summary>
/// <param name="value">The string (as a StringBuilder) to write to the stream</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests.</param>
[Link("https://learn.microsoft.com/en-us/dotnet/api/system.io.textwriter.writeasync#system-io-textwriter-writeasync(system-readonlymemory((system-char))-system-threading-cancellationtoken)")]
public static Task WriteAsync(this TextWriter target, StringBuilder? value, CancellationToken cancellationToken = default)
{
if (cancellationToken.IsCancellationRequested)
{
return Task.FromCanceled(cancellationToken);
}

if (value == null)
{
return Task.CompletedTask;
}

return WriteAsyncCore(value, cancellationToken);

async Task WriteAsyncCore(StringBuilder builder, CancellationToken cancel)
{
foreach (ReadOnlyMemory<char> chunk in builder.GetChunks())
{
await target.WriteAsync(chunk, cancel).ConfigureAwait(false);
}
}
}
#endif

#if NETFRAMEWORK || NETSTANDARD2_0 || NETCOREAPP2_0
#if FeatureValueTask

/// <summary>
Expand Down Expand Up @@ -303,10 +355,11 @@ static partial class Polyfill
pool.Return(array);
}
}
#endif
}
#endif
```
<sup><a href='/src/Polyfill/Polyfill_TextWriter.cs#L1-L119' title='Snippet source file'>snippet source</a> | <a href='#snippet-Polyfill_TextWriter.cs' title='Start of snippet'>anchor</a></sup>
<sup><a href='/src/Polyfill/Polyfill_TextWriter.cs#L1-L172' title='Snippet source file'>snippet source</a> | <a href='#snippet-Polyfill_TextWriter.cs' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->


Expand Down
11 changes: 11 additions & 0 deletions src/Consume/Consume.cs
Original file line number Diff line number Diff line change
Expand Up @@ -482,6 +482,17 @@ void NonGenericTaskCompletionSource()
}

#if FeatureMemory
async Task TextWriter()
{
TextWriter target = new StringWriter();
target.Write(new StringBuilder());
target.WriteAsync(new StringBuilder());
target.WriteLine("a".AsSpan());
await target.WriteLineAsync("a".AsMemory());
target.Write("a".AsSpan());
await target.WriteAsync("a".AsMemory());
}

void RandomNextBytesSpan()
{
var random = new Random();
Expand Down
55 changes: 54 additions & 1 deletion src/Polyfill/Polyfill_TextWriter.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
// <auto-generated />
#pragma warning disable

#if FeatureMemory && (NETFRAMEWORK || NETSTANDARD2_0 || NETCOREAPP2_0)
#if FeatureMemory

namespace Polyfills;

using System;
using System.Text;
using System.Buffers;
using System.IO;
using System.Runtime.InteropServices;
Expand All @@ -14,6 +16,56 @@ namespace Polyfills;

static partial class Polyfill
{
#if !NETCOREAPP3_0_OR_GREATER
/// <summary>
/// Equivalent to Write(stringBuilder.ToString()) however it uses the
/// StringBuilder.GetChunks() method to avoid creating the intermediate string
/// </summary>
/// <param name="value">The string (as a StringBuilder) to write to the stream</param>
[Link("https://learn.microsoft.com/en-us/dotnet/api/system.io.textwriter.write#system-io-textwriter-write(system-text-stringbuilder)")]
public static void Write(this TextWriter target, StringBuilder? value)
{
if (value != null)
{
foreach (ReadOnlyMemory<char> chunk in value.GetChunks())
{
target.Write(chunk.Span);
}
}
}

/// <summary>
/// Equivalent to WriteAsync(stringBuilder.ToString()) however it uses the
/// StringBuilder.GetChunks() method to avoid creating the intermediate string
/// </summary>
/// <param name="value">The string (as a StringBuilder) to write to the stream</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests.</param>
[Link("https://learn.microsoft.com/en-us/dotnet/api/system.io.textwriter.writeasync#system-io-textwriter-writeasync(system-readonlymemory((system-char))-system-threading-cancellationtoken)")]
public static Task WriteAsync(this TextWriter target, StringBuilder? value, CancellationToken cancellationToken = default)
{
if (cancellationToken.IsCancellationRequested)
{
return Task.FromCanceled(cancellationToken);
}

if (value == null)
{
return Task.CompletedTask;
}

return WriteAsyncCore(value, cancellationToken);

async Task WriteAsyncCore(StringBuilder builder, CancellationToken cancel)
{
foreach (ReadOnlyMemory<char> chunk in builder.GetChunks())
{
await target.WriteAsync(chunk, cancel).ConfigureAwait(false);
}
}
}
#endif

#if NETFRAMEWORK || NETSTANDARD2_0 || NETCOREAPP2_0
#if FeatureValueTask

/// <summary>
Expand Down Expand Up @@ -115,5 +167,6 @@ public static void WriteLine(
pool.Return(array);
}
}
#endif
}
#endif
22 changes: 22 additions & 0 deletions src/Tests/PolyfillTests_TextWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,28 @@ public async Task TextWriterWriteSpan()
Assert.AreEqual("value", s);
}

[Test]
public async Task TextWriterWriteStringBuilder()
{
using var stream = new MemoryStream();
using var writer = new StreamWriter(stream);
writer.Write(new StringBuilder("value"));
await writer.FlushAsync();
var s = Encoding.UTF8.GetString(stream.ToArray());
Assert.AreEqual("value", s);
}

[Test]
public async Task TextWriterWriteStringBuilderAsync()
{
using var stream = new MemoryStream();
using var writer = new StreamWriter(stream);
await writer.WriteAsync(new StringBuilder("value"));
await writer.FlushAsync();
var s = Encoding.UTF8.GetString(stream.ToArray());
Assert.AreEqual("value", s);
}

[Test]
public async Task TextWriterWriteLineSpan()
{
Expand Down

0 comments on commit 63223fd

Please sign in to comment.