Skip to content

Commit

Permalink
Merge branch 'main' into ubuntu-24.04-arm
Browse files Browse the repository at this point in the history
  • Loading branch information
nietras authored Jan 24, 2025
2 parents 5c9955a + 9b65d49 commit 7a49bdc
Show file tree
Hide file tree
Showing 38 changed files with 3,006 additions and 1,152 deletions.
41 changes: 38 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,12 @@ public bool Unescape { get; init; } = false;
/// 32) character is trimmed, not any whitespace character.
/// </remarks>
public SepTrim Trim { get; init; } = SepTrim.None;
/// <summary>
/// Forwarded to <see
/// cref="System.Threading.Tasks.ValueTask.ConfigureAwait(bool)"/> or
/// similar when async methods are called.
/// </summary>
public bool AsyncContinueOnCapturedContext { get; init; } = false;
```

#### Unescaping
Expand Down Expand Up @@ -867,6 +873,12 @@ public SepColNotSetOption ColNotSetOption { get; init; } = SepColNotSetOption.Th
/// too, but only the written name.
/// </remarks>
public bool Escape { get; init; } = false;
/// <summary>
/// Forwarded to <see
/// cref="System.Threading.Tasks.ValueTask.ConfigureAwait(bool)"/> or
/// similar when async methods are called.
/// </summary>
public bool AsyncContinueOnCapturedContext { get; init; } = false;
```

#### Escaping
Expand Down Expand Up @@ -1916,17 +1928,25 @@ namespace nietras.SeparatedValues
public static char Separator { get; }
}
[System.Diagnostics.DebuggerDisplay("{DebuggerDisplay,nq}")]
public sealed class SepReader : nietras.SeparatedValues.SepReaderState, System.Collections.Generic.IEnumerable<nietras.SeparatedValues.SepReader.Row>, System.Collections.Generic.IEnumerator<nietras.SeparatedValues.SepReader.Row>, System.Collections.IEnumerable, System.Collections.IEnumerator, System.IDisposable
public sealed class SepReader : nietras.SeparatedValues.SepReaderState, System.Collections.Generic.IAsyncEnumerable<nietras.SeparatedValues.SepReader.Row>, System.Collections.Generic.IEnumerable<nietras.SeparatedValues.SepReader.Row>, System.Collections.Generic.IEnumerator<nietras.SeparatedValues.SepReader.Row>, System.Collections.IEnumerable, System.Collections.IEnumerator, System.IDisposable
{
public nietras.SeparatedValues.SepReader.Row Current { get; }
public bool HasHeader { get; }
public bool HasRows { get; }
public nietras.SeparatedValues.SepReaderHeader Header { get; }
public bool IsEmpty { get; }
public nietras.SeparatedValues.SepSpec Spec { get; }
public nietras.SeparatedValues.SepReader.AsyncEnumerator GetAsyncEnumerator(System.Threading.CancellationToken cancellationToken = default) { }
public nietras.SeparatedValues.SepReader GetEnumerator() { }
public bool MoveNext() { }
public System.Threading.Tasks.ValueTask<bool> MoveNextAsync(System.Threading.CancellationToken cancellationToken = default) { }
public string ToString(int index) { }
public readonly struct AsyncEnumerator : System.Collections.Generic.IAsyncEnumerator<nietras.SeparatedValues.SepReader.Row>, System.IAsyncDisposable
{
public nietras.SeparatedValues.SepReader.Row Current { get; }
public System.Threading.Tasks.ValueTask DisposeAsync() { }
public System.Threading.Tasks.ValueTask<bool> MoveNextAsync() { }
}
[System.Diagnostics.DebuggerDisplay("{DebuggerDisplay}")]
[System.Obsolete(("Types with embedded references are not supported in this version of your compiler" +
"."), true)]
Expand Down Expand Up @@ -2008,8 +2028,15 @@ namespace nietras.SeparatedValues
public static nietras.SeparatedValues.SepReader From(in this nietras.SeparatedValues.SepReaderOptions options, System.IO.TextReader reader) { }
public static nietras.SeparatedValues.SepReader From(in this nietras.SeparatedValues.SepReaderOptions options, string name, System.Func<string, System.IO.Stream> nameToStream) { }
public static nietras.SeparatedValues.SepReader From(in this nietras.SeparatedValues.SepReaderOptions options, string name, System.Func<string, System.IO.TextReader> nameToReader) { }
public static System.Threading.Tasks.ValueTask<nietras.SeparatedValues.SepReader> FromAsync(this nietras.SeparatedValues.SepReaderOptions options, byte[] buffer, System.Threading.CancellationToken cancellationToken = default) { }
public static System.Threading.Tasks.ValueTask<nietras.SeparatedValues.SepReader> FromAsync(this nietras.SeparatedValues.SepReaderOptions options, System.IO.Stream stream, System.Threading.CancellationToken cancellationToken = default) { }
public static System.Threading.Tasks.ValueTask<nietras.SeparatedValues.SepReader> FromAsync(this nietras.SeparatedValues.SepReaderOptions options, System.IO.TextReader reader, System.Threading.CancellationToken cancellationToken = default) { }
public static System.Threading.Tasks.ValueTask<nietras.SeparatedValues.SepReader> FromAsync(this nietras.SeparatedValues.SepReaderOptions options, string name, System.Func<string, System.IO.Stream> nameToStream, System.Threading.CancellationToken cancellationToken = default) { }
public static System.Threading.Tasks.ValueTask<nietras.SeparatedValues.SepReader> FromAsync(this nietras.SeparatedValues.SepReaderOptions options, string name, System.Func<string, System.IO.TextReader> nameToReader, System.Threading.CancellationToken cancellationToken = default) { }
public static nietras.SeparatedValues.SepReader FromFile(in this nietras.SeparatedValues.SepReaderOptions options, string filePath) { }
public static System.Threading.Tasks.ValueTask<nietras.SeparatedValues.SepReader> FromFileAsync(this nietras.SeparatedValues.SepReaderOptions options, string filePath, System.Threading.CancellationToken cancellationToken = default) { }
public static nietras.SeparatedValues.SepReader FromText(in this nietras.SeparatedValues.SepReaderOptions options, string text) { }
public static System.Threading.Tasks.ValueTask<nietras.SeparatedValues.SepReader> FromTextAsync(this nietras.SeparatedValues.SepReaderOptions options, string text, System.Threading.CancellationToken cancellationToken = default) { }
public static System.Collections.Generic.IEnumerable<T> ParallelEnumerate<T>(this nietras.SeparatedValues.SepReader reader, nietras.SeparatedValues.SepReader.RowFunc<T> select) { }
public static System.Collections.Generic.IEnumerable<T> ParallelEnumerate<T>(this nietras.SeparatedValues.SepReader reader, nietras.SeparatedValues.SepReader.RowTryFunc<T> trySelect) { }
public static System.Collections.Generic.IEnumerable<T> ParallelEnumerate<T>(this nietras.SeparatedValues.SepReader reader, nietras.SeparatedValues.SepReader.RowFunc<T> select, int degreeOfParallism) { }
Expand Down Expand Up @@ -2041,6 +2068,7 @@ namespace nietras.SeparatedValues
{
public SepReaderOptions() { }
public SepReaderOptions(nietras.SeparatedValues.Sep? sep) { }
public bool AsyncContinueOnCapturedContext { get; init; }
public System.Collections.Generic.IEqualityComparer<string> ColNameComparer { get; init; }
public nietras.SeparatedValues.SepCreateToString CreateToString { get; init; }
public System.Globalization.CultureInfo? CultureInfo { get; init; }
Expand All @@ -2061,6 +2089,7 @@ namespace nietras.SeparatedValues
{
public static void CopyTo(this nietras.SeparatedValues.SepReader.Row readerRow, nietras.SeparatedValues.SepWriter.Row writerRow) { }
public static nietras.SeparatedValues.SepWriter.Row NewRow(this nietras.SeparatedValues.SepWriter writer, nietras.SeparatedValues.SepReader.Row rowToCopy) { }
public static nietras.SeparatedValues.SepWriter.Row NewRow(this nietras.SeparatedValues.SepWriter writer, nietras.SeparatedValues.SepReader.Row rowToCopy, System.Threading.CancellationToken cancellationToken) { }
}
public readonly struct SepSpec : System.IEquatable<nietras.SeparatedValues.SepSpec>
{
Expand Down Expand Up @@ -2090,19 +2119,22 @@ namespace nietras.SeparatedValues
AfterUnescape = 2,
All = 3,
}
public sealed class SepWriter : System.IDisposable
public sealed class SepWriter : System.IAsyncDisposable, System.IDisposable
{
public nietras.SeparatedValues.SepWriterHeader Header { get; }
public nietras.SeparatedValues.SepSpec Spec { get; }
public void Dispose() { }
public System.Threading.Tasks.ValueTask DisposeAsync() { }
public void Flush() { }
public System.Threading.Tasks.Task FlushAsync(System.Threading.CancellationToken cancellationToken = default) { }
public nietras.SeparatedValues.SepWriter.Row NewRow() { }
public nietras.SeparatedValues.SepWriter.Row NewRow(System.Threading.CancellationToken cancellationToken) { }
public override string ToString() { }
[System.Obsolete(("Types with embedded references are not supported in this version of your compiler" +
"."), true)]
[System.Runtime.CompilerServices.CompilerFeatureRequired("RefStructs")]
[System.Runtime.CompilerServices.IsByRefLike]
public struct Row : System.IDisposable
public struct Row : System.IAsyncDisposable, System.IDisposable
{
public nietras.SeparatedValues.SepWriter.Col this[int colIndex] { get; }
public nietras.SeparatedValues.SepWriter.Col this[string colName] { get; }
Expand All @@ -2111,6 +2143,7 @@ namespace nietras.SeparatedValues
public nietras.SeparatedValues.SepWriter.Cols this[System.Collections.Generic.IReadOnlyList<string> colNames] { get; }
public nietras.SeparatedValues.SepWriter.Cols this[string[] colNames] { get; }
public void Dispose() { }
public System.Threading.Tasks.ValueTask DisposeAsync() { }
}
[System.Obsolete(("Types with embedded references are not supported in this version of your compiler" +
"."), true)]
Expand Down Expand Up @@ -2195,11 +2228,13 @@ namespace nietras.SeparatedValues
public void Add(string colName) { }
public void Add(string[] colNames) { }
public void Write() { }
public System.Threading.Tasks.ValueTask WriteAsync(System.Threading.CancellationToken cancellationToken = default) { }
}
public readonly struct SepWriterOptions : System.IEquatable<nietras.SeparatedValues.SepWriterOptions>
{
public SepWriterOptions() { }
public SepWriterOptions(nietras.SeparatedValues.Sep sep) { }
public bool AsyncContinueOnCapturedContext { get; init; }
public nietras.SeparatedValues.SepColNotSetOption ColNotSetOption { get; init; }
public System.Globalization.CultureInfo? CultureInfo { get; init; }
public bool DisableColCountCheck { get; init; }
Expand Down
9 changes: 9 additions & 0 deletions src/Sep.ComparisonBenchmarks/PackageAssetsBench.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Threading.Tasks;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Configs;
using CsvHelper;
Expand Down Expand Up @@ -78,6 +79,14 @@ public void Sep______()
foreach (var row in reader) { }
}

[Benchmark]
public async ValueTask Sep_Async()
{
using var reader = await Sep.Reader(o => o with { HasHeader = false })
.FromAsync(Reader.CreateReader());
await foreach (var row in reader) { }
}

[Benchmark]
public void Sep_Unescape()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
<PropertyGroup>
<RootNamespace>nietras.SeparatedValues.Benchmarks</RootNamespace>
<OutputType>Exe</OutputType>
<NoWarn>$(NoWarn);CA2007</NoWarn>
</PropertyGroup>

<PropertyGroup>
Expand Down
12 changes: 7 additions & 5 deletions src/Sep.Test/Internals/InterpolatedStringHandlerRow.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.Contracts;
using System.Runtime.CompilerServices;
Expand Down Expand Up @@ -28,29 +29,30 @@ public void set_Item2(string index, [InterpolatedStringHandlerArgument("")] ref
[InterpolatedStringHandler]
public ref struct TraceInterpolatedStringHandler
{
static readonly Action<string> Log = t => { };
// Storage for the built-up string
readonly StringBuilder _builder;

public TraceInterpolatedStringHandler(int literalLength, int formattedCount)
{
_builder = new StringBuilder(literalLength);
Trace.WriteLine($"\tliteral length: {literalLength}, formattedCount: {formattedCount}");
Log($"\tliteral length: {literalLength}, formattedCount: {formattedCount}");
}

public TraceInterpolatedStringHandler(int literalLength, int formattedCount, InterpolatedStringHandlerRow row)
{
Contract.Assume(row is not null);
row._stringBuilder.Clear();
_builder = row._stringBuilder;
Trace.WriteLine($"\tliteral length: {literalLength}, formattedCount: {formattedCount} REUSE");
Log($"\tliteral length: {literalLength}, formattedCount: {formattedCount} REUSE");
}

public void AppendLiteral(string s)
{
Trace.WriteLine($"\tAppendLiteral called: {{{s}}}");
Log($"\tAppendLiteral called: {{{s}}}");

_builder.Append(s);
Trace.WriteLine($"\tAppended the literal string");
Log($"\tAppended the literal string");
}

public void AppendFormatted<T>(T t)
Expand Down
46 changes: 42 additions & 4 deletions src/Sep.Test/PackageAssetsTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace nietras.SeparatedValues.Test;
Expand Down Expand Up @@ -35,6 +36,23 @@ public class PackageAssetsTest
public void PackageAssetsTest_Read_WithQuotes_Unescape(SepCreateToString createToString) => VerifyRead(WithQuotes, createToString, unescape: true);


[DataTestMethod]
[DynamicData(nameof(ToStrings))]
public async ValueTask PackageAssetsTest_Read_NoQuotes_Async(SepCreateToString createToString) => await VerifyReadAsync(NoQuotes, createToString);

[DataTestMethod]
[DynamicData(nameof(ToStrings))]
public async ValueTask PackageAssetsTest_Read_NoQuotes_Unescape_Async(SepCreateToString createToString) => await VerifyReadAsync(NoQuotes, createToString, unescape: true);

[DataTestMethod]
[DynamicData(nameof(ToStrings))]
public async ValueTask PackageAssetsTest_Read_WithQuotes_Async(SepCreateToString createToString) => await VerifyReadAsync(WithQuotes, createToString);

[DataTestMethod]
[DynamicData(nameof(ToStrings))]
public async ValueTask PackageAssetsTest_Read_WithQuotes_Unescape_Async(SepCreateToString createToString) => await VerifyReadAsync(WithQuotes, createToString, unescape: true);


[DataTestMethod]
[DynamicData(nameof(ToStrings))]
public void PackageAssetsTest_Enumerate_NoQuotes(SepCreateToString createToString) =>
Expand Down Expand Up @@ -184,15 +202,35 @@ static void VerifyRead(string text, SepCreateToString createToString, bool unesc
var rowIndex = 0;
foreach (var row in reader)
{
var expectedCols = expected[rowIndex];
expectedCols = unescape ? UnescapeColsByTrim(expectedCols) : expectedCols;
Assert.AreEqual(expectedCols.Length, row.ColCount);
CollectionAssert.AreEqual(expectedCols, row[..].ToStringsArray());
AssertCols(row, rowIndex, unescape, expected);
++rowIndex;
}
Assert.AreEqual(expected.Count, rowIndex);
}

static async ValueTask VerifyReadAsync(string text, SepCreateToString createToString, bool unescape = false)
{
var expected = ReadLineSplitAsList(text);
using var reader = await Sep
.Reader(o => o with { HasHeader = false, CreateToString = createToString, Unescape = unescape })
.FromTextAsync(text);
var rowIndex = 0;
await foreach (var row in reader)
{
AssertCols(row, rowIndex, unescape, expected);
++rowIndex;
}
Assert.AreEqual(expected.Count, rowIndex);
}

static void AssertCols(SepReader.Row row, int rowIndex, bool unescape, List<string[]> expected)
{
var expectedCols = expected[rowIndex];
expectedCols = unescape ? UnescapeColsByTrim(expectedCols) : expectedCols;
Assert.AreEqual(expectedCols.Length, row.ColCount);
CollectionAssert.AreEqual(expectedCols, row[..].ToStringsArray());
}

static void VerifyEnumerate(string text, SepCreateToString createToString,
Func<SepReader, SepReader.RowFunc<string[]>, IEnumerable<string[]>> enumerate,
bool unescape = false)
Expand Down
3 changes: 2 additions & 1 deletion src/Sep.Test/Sep.Test.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
<RootNamespace>nietras.SeparatedValues.Test</RootNamespace>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<IsPackable>false</IsPackable>
<NoWarn>$(NoWarn);CA2007</NoWarn>
</PropertyGroup>

<ItemGroup>
Expand All @@ -15,7 +16,7 @@
</ItemGroup>

<ItemGroup>
<PackageReference Include="coverlet.collector" Version="6.0.3">
<PackageReference Include="coverlet.collector" Version="6.0.4">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
Expand Down
6 changes: 3 additions & 3 deletions src/Sep.Test/SepParserTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@ public void SepParserTest_ParseColEnds_NewLinesOnly(object parserObject)
_chars.AsSpan(0, charsEnd).Fill('\n');
_state._currentRowColCount = 0;
var parsedRowsLength = _state._parsedRows.Length;
Trace.WriteLine($"{nameof(parsedRowsLength)} {parsedRowsLength} {nameof(charsEnd)} {charsEnd}");

var rowCount = Math.Min(charsEnd, parsedRowsLength);
var charsStart = 0;
var lineNumberOffset = 4;
Expand Down Expand Up @@ -331,7 +331,8 @@ void AssertOutput(ISepParser parser, int charsStart, int charsEnd, ExpectedOutpu
Assert.AreEqual(expectedParsingRow.ColCount, s._parsingRowColCount, nameof(s._parsingRowColCount));
}

int TraceParseState(SepReaderState s)
[Conditional("SEPREADERTRACE")]
void TraceParseState(SepReaderState s)
{
var sb = new StringBuilder();
var indent = " ";
Expand All @@ -347,7 +348,6 @@ int TraceParseState(SepReaderState s)
var colEndsParsing = _colEndsOrColInfos.AsSpan().Slice(colEndsFrom, s._parsingRowColCount + 1);
sb.AppendLine($"{indent}}}, new({nameof(ExpectedParsingRow.ColEnds)}: new[]{{ {string.Join(", ", colEndsParsing.ToArray())} }}, {nameof(ExpectedParsingRow.LineNumberTo)}: {s._parsingLineNumber}, {nameof(ExpectedParsingRow.CharsStartIndex)}: {s._parsingRowCharsStartIndex}, {nameof(ExpectedParsingRow.ColEndsStartIndex)}: {s._parsingRowColEndsOrInfosStartIndex}, {nameof(ExpectedParsingRow.ColCount)}: {s._parsingRowColCount}));");
Trace.WriteLine(sb.ToString());
return colEndsFrom;
}

static void AreEqual(ReadOnlySpan<int> expected, int[] actual, int actualFrom, int actualTo)
Expand Down
Loading

0 comments on commit 7a49bdc

Please sign in to comment.