feat: add TextReader.EnumerateLines/Async

This commit is contained in:
Oliver Booth 2023-03-30 17:55:41 +01:00
parent 4f3f791948
commit 3ce8d281b7
No known key found for this signature in database
GPG Key ID: 20BEB9DC87961025
3 changed files with 137 additions and 0 deletions

View File

@ -75,6 +75,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- X10D: Added `string.IsWhiteSpace()`.
- X10D: Added `string.IsNullOrEmpty()`.
- X10D: Added `string.IsNullOrWhiteSpace()`.
- X10D: Added `TextReader.EnumerateLines()` and `TextReader.EnumerateLinesAsync()`.
- X10D: Added `TimeSpan.TryParse(ReadOnlySpan<char>, out TimeSpan)`.
- X10D: Added `Quaternion.Multiply(Vector3)` - this functions as an equivalent to Unity's `Quaternion * Vector3` operator.
- X10D: Added `Vector2.Deconstruct()`.

View File

@ -0,0 +1,83 @@
using System.Text;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using X10D.IO;
namespace X10D.Tests.IO;
[TestClass]
public class TextReaderTests
{
[TestMethod]
public void EnumerateLines_ShouldYield10Lines_Given10LineString()
{
using var stream = new MemoryStream();
using (var writer = new StreamWriter(stream, Encoding.UTF8, leaveOpen: true))
{
for (var index = 0; index < 10; index++)
{
writer.WriteLine(index);
}
}
stream.Position = 0;
using var reader = new StreamReader(stream, Encoding.UTF8);
var lineCount = 0;
foreach (string _ in reader.EnumerateLines())
{
lineCount++;
}
Assert.AreEqual(10, lineCount);
}
[TestMethod]
public async Task EnumerateLinesAsync_ShouldYield10Lines_Given10LineString()
{
using var stream = new MemoryStream();
await using (var writer = new StreamWriter(stream, Encoding.UTF8, leaveOpen: true))
{
for (var index = 0; index < 10; index++)
{
writer.WriteLine(index);
}
}
stream.Position = 0;
using var reader = new StreamReader(stream, Encoding.UTF8);
var lineCount = 0;
await foreach (string _ in reader.EnumerateLinesAsync().ConfigureAwait(false))
{
lineCount++;
}
Assert.AreEqual(10, lineCount);
}
[TestMethod]
public void EnumerateLines_ShouldThrowArgumentNullException_GivenNullSource()
{
TextReader reader = null!;
Assert.ThrowsException<ArgumentNullException>(() =>
{
foreach (string _ in reader.EnumerateLines())
{
// loop body is intentionally empty
}
});
}
[TestMethod]
public async Task EnumerateLinesAsync_ShouldThrowArgumentNullException_GivenNullSource()
{
TextReader reader = null!;
await Assert.ThrowsExceptionAsync<ArgumentNullException>(async () =>
{
await foreach (string _ in reader.EnumerateLinesAsync().ConfigureAwait(false))
{
// loop body is intentionally empty
}
}).ConfigureAwait(false);
}
}

View File

@ -0,0 +1,53 @@
namespace X10D.IO;
/// <summary>
/// IO-related extension methods for <see cref="TextReader" />.
/// </summary>
public static class TextReaderExtensions
{
/// <summary>
/// Enumerates the lines provided by the current text reader.
/// </summary>
/// <param name="reader">The reader whose lines to enumerate.</param>
/// <returns>An enumerable collection of lines as read from <paramref name="reader" />.</returns>
/// <exception cref="ArgumentNullException"><paramref name="reader" /> is <see langword="null" />.</exception>
public static IEnumerable<string> EnumerateLines(this TextReader reader)
{
#if NET6_0_OR_GREATER
ArgumentNullException.ThrowIfNull(reader);
#else
if (reader is null)
{
throw new ArgumentNullException(nameof(reader));
}
#endif
while (reader.ReadLine() is { } line)
{
yield return line;
}
}
/// <summary>
/// Asynchronously enumerates the lines provided by the current text reader.
/// </summary>
/// <param name="reader">The reader whose lines to enumerate.</param>
/// <returns>An asynchronous enumerable collection of lines as read from <paramref name="reader" />.</returns>
/// <exception cref="ArgumentNullException"><paramref name="reader" /> is <see langword="null" />.</exception>
public static async IAsyncEnumerable<string> EnumerateLinesAsync(this TextReader reader)
{
#if NET6_0_OR_GREATER
ArgumentNullException.ThrowIfNull(reader);
#else
if (reader is null)
{
throw new ArgumentNullException(nameof(reader));
}
#endif
while (await reader.ReadLineAsync().ConfigureAwait(false) is { } line)
{
yield return line;
}
}
}